// // Created by cfif on 22.09.2025. // #include "Clock.h" #include "LoggerToSerialPort.h" #include "LoggerInterface.h" #include "StorageOnFlash.h" #include "Rtcs.h" #include "SerialPorts.h" #include "CmsisRtosThreadUtils.h" #include "SystemDelayInterface.h" #include "DeviceStorage.h" #include "BootJump.h" #include "FirmwareLoader.h" #define BOOT_AREA_LENGTH (256 * 1024) // Размер загрузчика #define FIRMWARE_MAIN_AREA_LENGTH (512 * 1024) // Размер основной программы #define FIRMWARE_MAIN_ADDR (0x01000000 + BOOT_AREA_LENGTH) // Адрес основной программы #define FIRMWARE_MAIN_UPDATE_ADDR 0x01100000 // Адрес основной программы (обновление) typedef struct { tLoggerToSerialPort slog; tDeviceStorage storage; tFirmwareLoader FIRMWARE_HVAC; struct { osThreadId_t id; uint32_t stack[2048]; StaticTask_t controlBlock; osThreadAttr_t attr; } thread; } tBootMma; tBootMma MAIN_BOOT_ENV; #define LOGGER &MAIN_ENV.slog.logger #define LOG_SIGN "Boot" _Noreturn void stop() { while (1) { asm("nop"); } } #define STOP stop(); #if (configCHECK_FOR_STACK_OVERFLOW > 0) void vApplicationStackOverflowHook(TaskHandle_t xTask, const char *pcTaskName) { PROCESS_UNUSED_VAR(xTask); PROCESS_UNUSED_VAR(pcTaskName); STOP } #endif const DMA_InitType dmaInitCfg = { .eArbitrationAlgorithm = DMA_ARBITRATION_ALGORITHM_FIXED_PRIORITY, .bHaltOnError = false }; static _Noreturn void MainTransmitter_Thread(tBootMma *env) { DMA_Init(DMA_INSTANCE_0, &dmaInitCfg); Rtcs_Init(); // Настройка таймера реального времени time_t set_timestamp = 0; RtcSet(&RTCS.rtcI0, &set_timestamp); SerialPorts_Init(); LoggerToSerialPort_Init( &env->slog, 0, &SERIAL_PORTS.cliVirtualPortOut_Io, &SERIAL_PORTS.SerialPortLog_IO, &RTCS.rtcI0, SERIAL_LOGGER_SHOW_TIME | SERIAL_LOGGER_SHOW_AUTHOR | SERIAL_LOGGER_SHOW_LOG_LEVEL, 5 ); LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Start logging") LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Initialization of subsystems") // StorageOnFlash_Init(&env->slog.logger); // NVM_STORAGE.nf_storage_param.logger = &env->slog.logger; // NVM_STORAGE.nf_storage_calib.logger = &env->slog.logger; // bool result = DeviceStorage_Init(&env->storage, true, &NVM_STORAGE.interface_calib, &NVM_STORAGE.interface_param, // &env->slog.logger); FirmwareLoader_Init(&env->FIRMWARE_HVAC, FIRMWARE_MAIN_AREA_LENGTH, FIRMWARE_MAIN_ADDR, FIRMWARE_MAIN_UPDATE_ADDR); bool isMain = FirmwareLoader_CheckBlock(&env->FIRMWARE_HVAC, &env->FIRMWARE_HVAC.main); if (isMain) { LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Main firmware: Checksum is correct") } else { LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Main firmware: Checksum is not correct") if (*env->FIRMWARE_HVAC.main.metadata.crc == 0) { LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Main firmware: Checksum not found (The program may have been flashed using JTAG ?)") } } bool isUpdate = FirmwareLoader_CheckBlock(&env->FIRMWARE_HVAC, &env->FIRMWARE_HVAC.update); if (isUpdate) { LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Recovery firmware: Checksum is correct") } else { LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Recovery firmware: Checksum is not correct") } // Есть обновление if (isUpdate) { // Если текущая прошивка (isMain) неисправна (не загружена) или в секции обновления находится отличная от текущей прошивка bool isNewFirmware = FirmwareLoader_IsUpdateAndMainAreDifferent(&env->FIRMWARE_HVAC); // !isMain - Не совпадает crc основной прошивки isNewFirmware - есть рабочая прошивка в обновлении, которая отличается от основной (main) if ((!isMain) || (isNewFirmware)) { LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Update detected") LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Starting the update process") // Обновление // FirmwareLoader_CopyUpdateToMain(&env->FIRMWARE_HVAC); LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Update complete") // Проверка crc isMain = FirmwareLoader_CheckBlock(&env->FIRMWARE_HVAC, &env->FIRMWARE_HVAC.main); if (isMain) { LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Main firmware (after update): Checksum is correct") } else { LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Main firmware (after update): Checksum is not correct") } } } SystemDelayMs(10); BootJumpToAddress(FIRMWARE_MAIN_ADDR); for (;;) { SystemDelayMs(1000); } } void MainTransmitter_StartThread(tBootMma *env) { if (!env->thread.id) { env->thread.id = osThreadNew((osThreadFunc_t) (MainTransmitter_Thread), (void *) (env), &env->thread.attr); } } int main(void) { Bsp_CLOCK_Init(); NVIC_SetPriorityGrouping(NVIC_PRIORITY_GROUP_4); osKernelInitialize(); tBootMma *env = &MAIN_BOOT_ENV; InitThreadAtrStatic(&env->thread.attr, "BootMma", env->thread.controlBlock, env->thread.stack, osPriorityNormal); MainTransmitter_StartThread(env); osKernelStart(); STOP }