Files
Andrey 05be38a04a Обновить Flash/CAN, версии сборок и управление периферией
Добавить защищённое обновление приложения через RS и CAN с сохранением
загрузчика, проверкой CRC, восстановлением передачи и защитой EEPROM.
Подключить общий процесс сборки C2000 и автоматический счётчик версии
для согласованных RAM, Flash, CAN и паспортов бинарных образов.

Уточнить запуск ЦАП, обработку измерений и параметров нагрузки,
начальную индикацию и документацию регистров GAS.
Дополнить модели аппаратуры и изолировать заголовки CAN в тестах.

Проверка: 26 тестов выпуска, 4 теста восстановления CAN и восемь
программных моделей CAN, Flash, EEPROM, ЦАП, параметров и TESTLAMP.
2026-11-06 16:11:11 +03:00

66 lines
12 KiB
C

#include <stdint.h> /* Использует точные host-типы для 16-битных слов и 32-битных адресов C28x. */
#include <setjmp.h> /* Перехватывает автономное завершение прошивки, не выполняя бесконечный аппаратный watchdog-цикл. */
#include <string.h> /* Инициализирует исключительно тестовые массивы модели внутренней Flash. */
#include "f28335_flash_app.c" /* Компилирует настоящий валидатор запуска постоянного загрузчика, а не его копию на Python. */
typedef uint16_t Uint16; /* Слово TI C28x содержит 16 бит независимо от разрядности host-компилятора. */
typedef uint32_t Uint32; /* Адрес CPU и длина транспортного образа имеют 32 бита. */
typedef int FLASH_ST; /* Модель не использует внутренние диагностические поля официального TI API. */
typedef struct { unsigned int unused; } RS_DATA; /* Автономный writer передаёт RS-контекст только в подменённый итоговый ответ. */
static Uint16 program_buffer[128], packed[0xFC00], memory[0x40000]; /* Буферы соответствуют production writer, staging ZONE7A и всей внутренней Flash A–H. */
static FLASH_ST api_status; /* Writer получает отдельную структуру результата, как при вызове настоящего API. */
static struct { Uint16 WDCR; } SysCtrlRegs; /* Завершение перехватывается до записи watchdog; поле необходимо для компиляции неизменённого writer. */
static jmp_buf completed; /* Контекст возврата принадлежит одной синхронной проверке модели. */
static Uint16 result, erase_mask; /* Хранит подтверждённый статус и фактическую маску Flash_Erase производственного алгоритма. */
static unsigned int programs, fault_at, last_count; /* Позволяет оборвать каждую стадию записи, включая публикацию FAB1. */
static Uint32 last_address; /* Доказывает, что описание приложения программируется последним. */
#define EALLOW ((void)0) /* Host не имеет защищённых аппаратных регистров; алгоритм записи Flash остаётся неизменным. */
#define EDIS ((void)0) /* Снятие аппаратного разрешения моделируется без побочных эффектов для ПК. */
static Uint16 Flash_Erase(Uint16 mask, FLASH_ST *status); /* Подменяется только физическая операция стирания секторов. */
static Uint16 Flash_Program(Uint16 *target, Uint16 *data, Uint32 count, FLASH_ST *status); /* Сохраняет адреса и данные реального writer для модели памяти. */
static Uint16 Flash_Verify(Uint16 *target, Uint16 *data, Uint32 count, FLASH_ST *status); /* Проверяет уже записанные слова модели, не возвращая безусловный успех. */
static void reply_status(RS_DATA *rs, Uint16 status); /* Итоговый RS-ответ завершает модель вместо перехода в аппаратный reset. */
void ServiceDog(void) {} /* Host не имеет watchdog; производственная предварительная CRC сохраняет своё место обслуживания таймера. */
#include "production.inc" /* Тестовый runner извлекает byte/word/CRC, validate_image и program_image непосредственно из production flash_rs.c. */
static Uint16 Flash_Erase(Uint16 mask, FLASH_ST *status) /* Реализует маску TI: A — бит 0, H — бит 7. */
{ /* Модель позволяет обнаружить стирание boot даже при отсутствии последующих записей в сектор A. */
Uint32 index; (void)status; erase_mask = mask; /* Сохраняет неизменённый аргумент настоящего Flash_Erase. */
for (index = 0; index < 0x40000UL; ++index) if (mask & (1U << ((0x3FFFFUL - index) / 0x8000UL))) memory[index] = 0xFFFFU; /* Каждый сектор содержит 0x8000 адресуемых слов. */
return 0U; /* Само стирание модели успешно; ошибки программирования вводятся независимо. */
} /* Проверка сохранности boot выполняется даже после смоделированного обрыва. */
static Uint16 Flash_Program(Uint16 *target, Uint16 *data, Uint32 count, FLASH_ST *status) /* Моделирует частичный результат при потере питания во время выбранной записи. */
{ /* Использует числовой адрес указателя C28x, не разыменовывая его в памяти ПК. */
Uint32 address = (Uint32)(uintptr_t)target, i, written = count; (void)status; /* Числовой LOAD-адрес сохраняется без преобразования в байтовый адрес. */
++programs; last_address = address; last_count = (unsigned int)count; /* Фиксирует порядок реальных вызовов writer. */
if (address < F28335_FLASH_APP_START || address + count > F28335_FLASH_APP_STOP) return 77U; /* Даже ошибочный writer не выходит за тестовый массив; отдельная проверка всё равно обнаружит запрос сектора A. */
if (fault_at == programs) written = count / 2UL; /* Обрыв оставляет половину текущей порции, включая половину FAB1 на последней стадии. */
for (i = 0; i < written; ++i) memory[address - F28335_FLASH_APP_START + i] &= data[i]; /* Программирование Flash может только сбрасывать биты; скрытое перезаписывание без erase не моделируется как успех. */
return fault_at == programs ? 22U : 0U; /* Код 22 отличает введённый обрыв от успешного выполнения. */
} /* Последующая Flash_Verify вызывается только при нулевом статусе, как на плате. */
static Uint16 Flash_Verify(Uint16 *target, Uint16 *data, Uint32 count, FLASH_ST *status) /* Сверяет фактическую память модели с исходной staging RAM. */
{ /* Неверно выбранный адрес либо данные не должны получить подтверждение. */
Uint32 address = (Uint32)(uintptr_t)target, i; (void)status; /* Адреса остаются в единицах слов C28x. */
for (i = 0; i < count; ++i) if (memory[address - F28335_FLASH_APP_START + i] != data[i]) return 40U; /* Несовпадение возвращает ненулевой статус аппаратной проверки. */
return 0U; /* Подтверждает только побайтно совпавшие слова после записи. */
} /* Не подменяет проверку полной CRC описания FAB1. */
static void reply_status(RS_DATA *rs, Uint16 status) { (void)rs; result = status; longjmp(completed, 1); } /* Завершает испытание после реального пути записи и проверки, до бесконечного watchdog-цикла. */
static uint16_t flash_word(void *user, uint32_t address) { (void)user; return memory[address - F28335_FLASH_APP_START]; } /* Читает модель Flash для настоящей boot-проверки CRC. */
static void pack(const Uint16 *octets, Uint32 length) /* Повторяет существующую упаковку RS_RX_Handler в staging RAM. */
{ /* Один октет ctypes передаётся отдельным host-словом для независимости от char C28x. */
Uint32 i; memset(packed, 0, sizeof(packed)); /* Очищает только тестовый staging-буфер текущего запуска. */
for (i = 0; i < length; ++i) packed[i / 2UL] |= octets[i] << ((i & 1UL) ? 0U : 8U); /* Чётная октета помещается в старший байт слова, как production RS LOAD. */
} /* Содержание исходного SCI8 не меняется при подготовке C-вызова. */
__declspec(dllexport) Uint16 check_image(const Uint16 *octets, Uint32 length) { pack(octets, length); return validate_image(packed, length); } /* Экспортирует настоящий MCU-валидатор для проверок Python. */
__declspec(dllexport) Uint16 check_program(const Uint16 *octets, Uint32 length, unsigned int fault) /* Выполняет настоящий writer на изолированной модели Flash. */
{ /* Обязательная входная проверка предшествует любому обращению к модели erase. */
Uint32 i, entry; Uint16 checked; pack(octets, length); /* Подготавливает staging в том же представлении, что устройство. */
checked = validate_image(packed, length); if (checked) return checked; /* Повреждённый FAB1 или слово сектора A не допускаются к записи. */
for (i = 0; i < 0x40000UL; ++i) memory[i] = i >= 0x38000UL ? 0xA35AU : 0U; /* Старый boot заполняется контрольным рисунком; область приложения требует настоящего erase. */
result = erase_mask = 0U; programs = 0U; fault_at = fault; /* Исключает влияние предыдущего испытания и задаёт точку обрыва. */
if (!setjmp(completed)) program_image(0, packed, length); /* Вызов возвращается только через перехваченный итоговый ответ. */
if (erase_mask != 0xFEU) return 0x7001U; /* Сектор A должен быть исключён из реального аргумента Flash_Erase. */
for (i = 0x38000UL; i < 0x40000UL; ++i) if (memory[i] != 0xA35AU) return 0x7002U; /* Все 0x8000 слов постоянного boot сохраняются после успеха и каждого обрыва. */
if (!result && (last_address != F28335_FLASH_APP_START || last_count != F28335_FLASH_APP_HEADER_WORDS || !f28335_flash_app_validate(flash_word, 0, &entry))) return 0x7003U; /* Успех требует последней публикации FAB1 и действительного запускаемого образа. */
if (result && f28335_flash_app_validate(flash_word, 0, &entry)) return 0x7004U; /* Частично записанная программа не должна проходить boot-проверку и вытеснять резерв EEPROM. */
return result; /* Сохраняет исходный код TI API при одновременно доказанной сохранности boot. */
} /* Модель никогда не открывает JTAG, COM или CAN-адаптер пользователя. */