Files
Balsam_167/tests/testlamp/model.inc
T
Andrey 52683164af Перенести улучшения прошивки в ветку 166
Добавить CAN heartbeat и передачу по изменению с повтором через 1,3 с,
компактный логгер v4, паспорт прошивки и блочное чтение EEPROM.
Подключить автоматическую версию и проверяемую сборку BIN.
Сохранить локальные исправления стробов и защиты Timer1.
Обновить тесты, документацию, UTF-8 и исключения временных файлов.

Проверки: CAN, R3, EEPROM, паспорт, TESTLAMP, логгер, START/STOP;
9 сценариев сборки, включая реальную конверсию TI.
Все 17 внутренних модулей скомпилированы TI C2000 без ошибок.
2026-10-19 13:46:29 +03:00

109 lines
16 KiB
C++

/* Проверяет удержание TESTLAMP и выбор пакетов при уже включённых рабочих лампах. */
#include <stdio.h> /* Выводит конкретные нарушенные условия и итог сценария. */
#include <string.h> /* Обнуляет регистровое пространство перед началом проверки. */
#define interrupt /* Убирает аппаратный атрибут ISR при компиляции модели на ПК. */
typedef float FILTERBAT; /* Позволяет подключить production-заголовок с интерфейсами фильтров. */
#include "measure.h" /* Получает настоящие READY_FREQ, BLINK_TIME, CANPOWSE и maximum_bright. */
#include "package.h" /* Получает настоящие адреса TESTLAMP, яркости, ламп и типов плат. */
#include "DSP2833x_SWPrioritizedIsrLevels.h" /* Использует реальную вычисляемую маску приоритетов TI MINT13. */
typedef union { /* Моделирует слово Modbus размером хостового int, сохраняя номера битов production-псевдонимов. */
unsigned int all; /* Обеспечивает запись целого слова по тому же смещению массива. */
struct { /* Размещает шестнадцать технологических битов в младшей части слова. */
unsigned int bit0:1, bit1:1, bit2:1, bit3:1, bit4:1, bit5:1, bit6:1, bit7:1; /* Сохраняет позиции кнопок и команд 0..7. */
unsigned int bit8:1, bit9:1, bitA:1, bitB:1, bitC:1, bitD:1, bitE:1, bitF:1; /* Сохраняет позиции повторителей входов и старших команд 8..15. */
} bit; /* Предоставляет production-псевдонимам доступ к полям регистра. */
} WORDE; /* Завершает хостовое представление одного регистра Modbus. */
struct gpio_bits { /* Предоставляет входы всех ветвей настоящей get_Buttons, без моделирования электрических свойств. */
unsigned GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7, GPIO8, GPIO9, GPIO10, GPIO11; /* Представляет дискретные входы нескольких типов плат. */
unsigned GPIO20, GPIO21, GPIO22, GPIO23, GPIO24, GPIO25, GPIO26, GPIO27; /* Представляет перемычки и вход TESTLAMP GPIO26 пульта. */
unsigned GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53; /* Представляет входы банка B, читаемые get_Buttons. */
}; /* Завершает перечень моделируемых входов. */
struct gpio_reg { struct gpio_bits bit; }; /* Даёт регистрам GPADAT и GPBDAT production-форму обращения. */
static struct { struct gpio_reg GPADAT, GPBDAT; } GpioDataRegs; /* Хранит управляемые сценарием уровни входов. */
static struct { unsigned long all; } DigErr; /* Принимает диагностическую маску посторонней ветви SHKF. */
static struct { unsigned long InterruptCount; } CpuTimer1; /* Учитывает вызовы настоящего обработчика пульта. */
int modbus[129], Desk; /* Предоставляет технологические регистры и выбирает ветвь пульта. */
long INcount0; /* Повторяет тип накопителя в peripher.c проекта 166 и параметр long * функции er_anal, чтобы модель проверяла настоящий фильтр без несовместимых указателей. */
unsigned int CanPowse, CanGO; /* Хранит счётчик тактов выдачи CAN и признак готовности очередной передачи. */
unsigned long isMask, Lonely; /* Хранит тестовую маску и возраст последней связи. */
int isNumb, quaLamp = 6; /* Сохраняет тестовые цифры и число ламп из pulto.c. */
static unsigned int IER, mask_at_eint, entry_mask, failures, sends, nested_entries, timer_pending; /* Отслеживает разрешения прерываний, пакетные вызовы и возможность вложенного Timer1. */
static unsigned long lamp_word; /* Запоминает последний пакет шести сигнальных ламп канала 2. */
static long digit_word; /* Сохраняет последнее значение одного из двух семисегментных индикаторов в текущем такте. */
static int digit_dot, digit_sends; /* Запоминает режим форматирования цифр и наличие числового пакета в текущем такте. */
#define M_INT13 0x1000U /* Повторяет бит 12 INT13 из DSP2833x_Device.h для модели регистра IER. */
#define EALLOW ((void)0) /* Не моделирует защиту аппаратных регистров, поскольку она не влияет на рассматриваемые ветви. */
#define EDIS ((void)0) /* Завершает заглушку защищённой записи. */
#define EINT (mask_at_eint = IER) /* Снимает реально применённую маску в момент разрешения вложенных прерываний. */
#define ServiceDog() ((void)0) /* Исключает аппаратный сторожевой таймер из проверки индикации. */
#define toggle_ONLINE() ((void)0) /* Не моделирует электрический сигнал готовности ПЛИС. */
#define toggle_RES_OUT_1() ((void)0) /* Исключает резервный GPIO из логики выбора TESTLAMP. */
#define toggle_RES_OUT_2() ((void)0) /* Исключает второй резервный GPIO из пакетной проверки. */
void cpu_timer1_isr_PULT(void); /* Позволяет заглушке передачи смоделировать повторное аппаратное событие Timer1. */
static void kanal_Send(int adr, long dat, int dot) /* Записывает передаваемые данные, не подменяя проверяемый выбор режима. */
{ /* Начинает обработку одного production-вызова передачи. */
sends++; /* Позволяет обнаружить дополнительные вызовы передачи при повторном входе в ISR. */
if (timer_pending && (IER & M_INT13)) { /* Моделирует новый такт Timer1 во время незаконченной передачи, только когда собственное прерывание ошибочно разрешено. */
timer_pending = 0; /* Ограничивает искусственное событие одним вложенным вызовом. */
nested_entries++; /* Регистрирует перемешивание обработки двух тактов. */
cpu_timer1_isr_PULT(); /* Запускает настоящую production-функцию повторно при неверной маске. */
} /* Завершает моделирование потенциального повторного входа. */
if (adr == 2) lamp_word = (unsigned long)dat; /* Сохраняет именно канал сигнальных ламп, обновляемый в каждом такте. */
if (adr < 2) { /* Записывает также передачу цифр, чтобы обнаружить переход семисегментного индикатора в рабочий режим при провале кнопки. */
digit_word = dat; /* Сохраняет переданное production-функцией числовое значение. */
digit_dot = dot; /* Различает тест четырёх одинаковых цифр и обычное форматирование измерений. */
digit_sends++; /* Отмечает присутствие числового пакета в текущем такте. */
} /* Завершает фиксацию передачи на семисегментный индикатор. */
} /* Завершает заглушку аппаратной передачи. */
/* HANDLERS */
static void check(int condition, const char *name) /* Накапливает ошибки, позволяя проверить все последствия одного дефекта. */
{ /* Начинает регистрацию одного требования. */
if (!condition) { /* Выводит только нарушенные условия. */
printf("FAIL %s\n", name); /* Даёт мутационному тесту устойчивое имя обнаруженного дефекта. */
failures++; /* Делает код завершения ненулевым при любой регрессии. */
} /* Завершает обработку ошибки. */
} /* Завершает проверку одного требования. */
static void tick(void) /* Моделирует сохранение и восстановление IER на границе аппаратного ISR. */
{ /* Начинает один такт индикации. */
IER = entry_mask; /* Возвращает исходные разрешения источников перед новым обработчиком. */
sends = 0; /* Отделяет вызовы передачи текущего такта от предыдущих. */
digit_sends = 0; /* Не принимает пакет предыдущего такта за обновление цифр в текущем. */
cpu_timer1_isr_PULT(); /* Выполняет настоящий алгоритм выбора режима, PWM и пакетов. */
check(mask_at_eint == (entry_mask & MINT13 & ~M_INT13), "interrupt mask"); /* Проверяет отсутствие собственного Timer1 и запрет включения ранее выключенных источников. */
check(sends >= 1 && sends <= 2, "packet count"); /* Требует штатный объём одного такта: пакет ламп и не более одного пакета очередного индикатора. */
} /* Завершает один такт индикации. */
int main(void) /* Проверяет двухсекундное удержание по Timer1 и защиту стробов DATA/CLOCK от повторного входа. */
{ /* Начинает независимые сценарии физической кнопки, удалённой команды и яркости. */
int i, pwm_on = 0; /* Считает такты удержания и включённые фазы десятишагового PWM. */
memset(modbus, 0, sizeof(modbus)); /* Очищает команды и входы перед запуском production-функций. */
check(sizeof(WORDE) == sizeof(modbus[0]), "register layout"); /* Подтверждает совместимость битовых псевдонимов с массивом хостовой модели. */
Desk = dsk_EPLT; modbus[2] = 1; Bright[0] = maximum_bright; /* Выбирает пульт и заранее включает рабочую лампу с полной яркостью. */
entry_mask = M_INT13 | (1U << 0) | (1U << 13); /* Проверяет Timer1 вместе с ранее разрешёнными источниками разных приоритетов. */
tick(); check(lamp_word == 1, "normal lamp before test"); /* Проверяет рабочую индикацию до начала удержания. */
GpioDataRegs.GPADAT.bit.GPIO26 = 1; /* Нажатие TESTLAMP представлено высоким уровнем входа платы. */
for (i = 0; i < 4000; i++) get_Buttons(); /* Частый main не должен ускорять выдержку, которую теперь считает только Timer1. */
check(!bTestLamp, "polling independent"); /* Доказывает независимость порога от числа опросов главного цикла. */
for (i = 0; i < 2 * READY_FREQ - 1; i++) { tick(); check(!bTestLamp, "short test"); } /* Даже 1999 тактов при 1000 Гц ещё не разрешают местный тест. */
tick(); check(bTestLamp, "test activation"); /* Двухтысячный такт включает тест точно после двух секунд удержания. */
for (i = 0; i < 600; i++) { /* Проверяет непрерывный тест дольше периода BLINK_TIME=500 без потери защиты стробов. */
timer_pending = 1; tick(); /* Имитирует новый такт во время передачи, когда прежний ISR ещё не завершился. */
check(bTestLamp && lamp_word == isMask, "held test"); /* Требует передачу тестовой фазы вместо исходной рабочей маски. */
check(!digit_sends || (digit_word == isNumb && digit_dot == 4), "test digit packet"); /* Проверяет тестовый формат числового индикатора. */
check(nested_entries == 0, "nested transmission"); timer_pending = 0; /* Единственный владелец DATA/CLOCK исключает перемешивание пакетов. */
} /* Завершает длительное удержание физической кнопки. */
GpioDataRegs.GPADAT.bit.GPIO26 = 0; tick(); /* Отпускание сбрасывает местный тест в следующем такте Timer1. */
check(!bTestLamp && lamp_word == 1, "release"); /* Возвращает заранее включённую рабочую лампу без дополнительной задержки. */
for (i = 0; i < 3; i++) { /* Отдельные короткие нажатия суммарно превышают две секунды, но не должны включать тест. */
int held; GpioDataRegs.GPADAT.bit.GPIO26 = 1; /* Начинает очередное независимое нажатие. */
for (held = 0; held < READY_FREQ; held++) tick(); /* Удерживает вход одну секунду, то есть меньше порога. */
check(!bTestLamp, "separate presses"); /* Не позволяет сложить длительности разных нажатий. */
GpioDataRegs.GPADAT.bit.GPIO26 = 0; tick(); /* Сбрасывает накопленную выдержку отпусканием. */
} /* Завершает сценарий повторных коротких нажатий. */
cTestLamp = 1; tick(); check(lamp_word == isMask, "remote test"); /* Команда Modbus сохраняет немедленный независимый запуск теста. */
cTestLamp = 0; Bright[0] = 6; /* Возвращает рабочий режим с яркостью шесть тактов из десяти. */
for (i = 0; i < 10; i++) { tick(); check(lamp_word <= 1, "normal PWM packet"); pwm_on += lamp_word == 1; } /* Измеряет полный период реального алгоритма яркости после теста. */
check(pwm_on == 6, "normal PWM duty"); /* Подтверждает сохранение настроенной скважности рабочего сигнала. */
printf("%s TESTLAMP: 2-second hold, main independent, single ISR, release, remote command, PWM\n", failures ? "FAIL" : "PASS"); /* Указывает проверенные программные свойства без заявления об аппаратном испытании. */
return failures ? 1 : 0; /* Любое нарушенное условие завершает процесс проверки с ошибкой. */
} /* Завершает проверку кнопки и защищённой передачи индикации. */