#include /* Использует точные host-типы для 16-битных слов и 32-битных адресов C28x. */ #include /* Перехватывает автономное завершение прошивки, не выполняя бесконечный аппаратный watchdog-цикл. */ #include /* Инициализирует исключительно тестовые массивы модели внутренней 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-адаптер пользователя. */