#include "DSP2833x_Device.h" /* Предоставляет реальные типы C28x, частоту SYSCLKOUT, CSM и маскирование IRQ. */ #include "../../../ports/tms320f28335/f28335_flash_update.h" /* Подключает проверяемый алгоритм staging SCI8 и аппаратный контракт записи. */ #include "Flash2833x_API_Library.h" /* Использует официальный TI Flash API v2.10 для F28335, а не запись Flash обычным указателем. */ #include /* Копирует код и таблицы TI API из постоянного сектора A во внутреннюю RAM до операции Flash. */ extern Uint16 FlashApiLoadStart, FlashApiLoadEnd, FlashApiRunStart; /* Символы LOAD/RUN задаёт linker в адресуемых словах CPU. */ static FLASH_ST flash_status; /* Диагностика TI хранится во внутренней RAM во время стирания и программирования. */ static bool erase_flash(void *user) /* Стирает только область приложения, сохраняя постоянный загрузчик. */ { /* Даже IRQ из сектора A запрещены, поскольку F28335 имеет общий банк Flash для A–H. */ Uint16 saved, status; (void)user; /* Сохраняет прежнее состояние IRQ и точный результат TI API. */ saved = __disable_interrupts(); status = Flash_Erase(0x00FEU, &flash_status); __restore_interrupts(saved); /* Бит 0 — сектор A; маска FE выбирает только B–H согласно TI API v2.10. */ return status == STATUS_SUCCESS; /* Ошибка erase запрещает любую последующую публикацию FAB1. */ } /* После возврата TI API банк Flash снова доступен коду постоянного загрузчика. */ static bool program_flash(void *user, uint32_t address, uint16_t *data, unsigned int words) /* Записывает и проверяет одну ограниченную порцию Flash. */ { /* Аппаратный слой повторно защищает сектор A независимо от валидатора SCI8. */ Uint16 saved, status; (void)user; /* Результат API и маска IRQ не размещаются в обновляемой Flash. */ if (!words || address < F28335_FLASH_APP_START || address >= F28335_FLASH_APP_STOP || words > F28335_FLASH_APP_STOP - address) return false; /* Не допускает даже частичного выхода за B–H, включая CSM и аппаратный boot. */ saved = __disable_interrupts(); status = Flash_Program((Uint16 *)address, data, words, &flash_status); /* Во время программирования процессор выполняет только скопированный в RAM TI API. */ if (!status) status = Flash_Verify((Uint16 *)address, data, words, &flash_status); /* Проверяет фактические слова до подтверждения этой порции. */ __restore_interrupts(saved); return status == STATUS_SUCCESS; /* Возвращает исходное состояние IRQ даже при отказе записи или readback. */ } /* Общий writer опубликует FAB1 лишь после успешной записи остальных порций. */ static uint16_t read_flash(void *user, uint32_t address) /* Читает физическую Flash для итоговой проверки FAB1/CRC. */ { /* Этот callback вызывается только после окончания аппаратных операций TI API. */ (void)user; return *(volatile Uint16 *)address; /* Адрес уже ограничен общим валидатором диапазоном приложения B–H. */ } /* Программирование не подменяется чтением staging EEPROM. */ bool F28335Boot_FlashProgram(f28335_flash_update_t *s) /* Единственная точка фактической записи внутренней Flash из CAN COMMIT. */ { /* Постоянный загрузчик может вернуться к CAN recovery при любой ошибке. */ f28335_flash_ops_t ops; /* Аппаратные операции передаются проверяемому транспортно-независимому writer. */ if (CsmRegs.CSMSCR.bit.SECURE) return false; /* Защищённый CSM запрещает стирание до любого вызова TI API. */ memcpy(&FlashApiRunStart, &FlashApiLoadStart, &FlashApiLoadEnd - &FlashApiLoadStart); /* API и его константы должны быть в RAM даже при сохранении сектора A. */ Flash_CPUScaleFactor = (Uint32)(1048576.0L * (200.0L * (long double)SYSCLKOUT / 1000000000.0L)); /* Формула TI IQ20 использует реальную частоту SYSCLKOUT в герцах. */ Flash_CallbackPtr = 0; ops.erase = erase_flash; ops.program = program_flash; ops.read = read_flash; ops.user = 0; /* Исключает callback во Flash во время занятости общего банка A–H. */ return f28335_flash_update_program(s, &ops); /* Итоговый ACK COMMIT появляется только после CRC физической Flash; REBOOT остаётся отдельной командой клиента. */ } /* Постоянный boot, handoff и EEPROM-параметры не программируются. */