#include "cmsis_os.h" #include "at32f435_437_clock.h" #include "FirmwareLoader.h" #include "FirmwareMetadataSection.h" #include "StorageOnFlash.h" #include "DeviceStorage.h" #include "string.h" #include "stdlib.h" #include "SystemDelayInterface.h" #include "ld_adr.h" #include "BootJump.h" #include "BaseTypes.h" /* #include "Gpios.h" #include "Rtcs.h" #include "SerialPorts.h" #include "CmsisRtosThreadUtils.h" #include "LoggerToSerialPort.h" #include "EgtsProcessing.h" #include "ComInt.h" #include "aes.h" #include "ext_telematica.h" */ #define FIRMWARE_MAIN_ADDR (0x08000000 + BOOT_AREA_LENGTH) #define FIRMWARE_MAIN_RECOVERY_ADDR (FIRMWARE_MAIN_ADDR + FIRMWARE_MAIN_AREA_LENGTH) #define FIRMWARE_TELE_MAIN_ADDR (FIRMWARE_MAIN_RECOVERY_ADDR + FIRMWARE_MAIN_UPDATE_AREA_LENGTH) #define FIRMWARE_TELE_RECOVERY_ADDR (FIRMWARE_MAIN_ADDR + FIRMWARE_MAIN_AREA_LENGTH) tFirmwareLoader FIRMWARE_UVEOS_LOADER; tFirmwareLoader FIRMWARE_TELE_LOADER; tFirmwareLoader FIRMWARE_UPDATE_LOADER; tDeviceStorage deviceStorage; bool resultStorage; uint8_t findDelimiter(tString32 *address, char ch) { for (uint8_t i = 0; i < address->length; ++i) { if (address->data[i] == ch) return i; } return 0; } void run() { // if (FirmwareLoader_IsLoadUpdate(&FIRMWARE_UVEOS_LOADER)) { // bool result = FirmwareLoader_CheckAndUpdate(&FIRMWARE_UVEOS_LOADER); // } // if (!FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.main)) { // Сбой прошивки // asm("nop"); // } // FirmwareLoader_RunFirmware(&FIRMWARE_UVEOS_LOADER); BootJumpToAddress(FIRMWARE_MAIN_ADDR); } /* _Noreturn void stop() { while (1) { asm("nop"); } } #define STOP stop(); tStaticThreadBlock(1024) mainThread; tLoggerToSerialPort slog; tDeviceStorage deviceStorage; tEgtsProcessing EgtsProcessing; tGsmWithGnss gsm; tComInt comInt; #define LOG_SIGN "BOOT" #define LOGGER &slog.logger struct { uint8_t gsmRx[1024]; uint8_t gsmTx[1024]; } mem; tAtCmd gsmAt; void run() { // if (FirmwareLoader_IsLoadUpdate(&FIRMWARE_UVEOS_LOADER)) { // bool result = FirmwareLoader_CheckAndUpdate(&FIRMWARE_UVEOS_LOADER); // } // if (!FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.main)) { // Сбой прошивки // asm("nop"); // } // FirmwareLoader_RunFirmware(&FIRMWARE_UVEOS_LOADER); BootJumpToAddress(FIRMWARE_MAIN_ADDR); } bool GsmWithGnssWaitStartup(tGsmWithGnss *env) { volatile AtCommandResult res = AT_ERROR; if (osMutexAcquire(env->gsmAt->access, 1000) == osOK) { res = AtCmdWaitOk(env->gsmAt, 1000, 20000); osMutexRelease(env->gsmAt->access); return res; } return res; } tStringStatic teDeviceModesNames[] = { StringStaticInit("Загрузчик") }; #define timeOutWaitConnect 30 #define timeOutWaitLoading (5 * 60) bool resultStorage; _Noreturn void MainThread(void *env) { for (;;) { LoggerToSerialPort_Init( &slog, 0, &SERIAL_PORTS.cliVirtualInIo, &RTCS.rtcI0, SERIAL_LOGGER_SHOW_AUTHOR | SERIAL_LOGGER_SHOW_LOG_LEVEL | SERIAL_LOGGER_SHOW_TIME// | SERIAL_LOGGER_SHOW_TIME ); tStringLink currentModeName = StringStaticGetLink(&teDeviceModesNames[0]); tString16 alertId; String16CopyStatic(&alertId, "BOOT"); ComInt_Init( &comInt, &SERIAL_PORTS.Rs485_HalfDuplexIo, &alertId, &SERIAL_PORTS.Modem_snif_IO, &SERIAL_PORTS.cliVirtualOutIo, ¤tModeName ); ComInt_StartThread(&comInt); LoggerInfoStatic(LOGGER, LOG_SIGN, "Загрузчик. Начало логирования") // bool resultStorage = DeviceStorage_Init(&deviceStorage, &NVM_STORAGE.interface); if (!resultStorage) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Первый запуск. Не введен адрес сервера") } if ((deviceStorage.nvm.SettingsServerConnection.EGTS_SERVER_ADDRESS.length == 0) || (deviceStorage.nvm.SettingsServerConnection.EGTS_GPRS_APN.length == 0)) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход. Не введен адрес сервера или apn") run(); } if (deviceStorage.nvm.SettingsServerConnection.EGTS_FLEET_ON == 0) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход. Телематика отключена") run(); } uint32_t timeOutWaitAuth = 30; if (deviceStorage.nvm.SettingsServerConnection.EGTS_TIME_WAIT_FIRMWARE > timeOutWaitAuth) timeOutWaitAuth = deviceStorage.nvm.SettingsServerConnection.EGTS_TIME_WAIT_FIRMWARE; GpioPinEnable(&GPIOS.standby); GpioPinEnable(&GPIOS.enable); GpioPinEnable(&GPIOS.PowerRS485); AtCmdInit( &gsmAt, &SERIAL_PORTS.Modem_IO, mem.gsmTx, sizeof(mem.gsmTx), mem.gsmRx, sizeof(mem.gsmRx), 2000, 2000 ); GsmWithGnssInit(&gsm, &slog, &gsmAt, &RTCS.rtcI0); EgtsProcessing_Init( &EgtsProcessing, &gsm, &deviceStorage, &RTCS.rtcI0, &slog ); PwmSim7600e_Startup(&GPIOS.sim7600); LoggerInfoStatic(LOGGER, LOG_SIGN, "Ожидание загрузки модема") bool result = GsmWithGnssWaitStartup(&gsm); if (result) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Ответ от модема получен") } else { LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка. Нет ответа от модема") run(); } GsmWithGnss_start(&gsm); EgtsProcessing_Start(&EgtsProcessing); uint32_t timeWaitConnect = SystemGetMs() + timeOutWaitConnect * 1000; uint32_t timeWaitAuth = SystemGetMs() + timeOutWaitAuth * 1000; uint32_t timeWaitLoad = SystemGetMs() + timeOutWaitLoading * 1000; for (;;) { // Если не было соединения if (EgtsProcessing.egtsLoaderUpdate == EGTS_LOADER_INIT) { uint32_t time = SystemGetMs(); if (timeWaitConnect < SystemGetMs()) { LoggerFormatInfo(LOGGER, LOG_SIGN, "Выход по таймеру: Не было соединения с сервером в течении %d сек", timeOutWaitConnect) run(); } } // Если не было соединения if (EgtsProcessing.egtsLoaderUpdate == EGTS_LOADER_ERR_CON) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход: Не было соединения с сервером. Все попытки соединения были исчерпаны") run(); } // Если не было обновления после соединения if (EgtsProcessing.egtsLoaderUpdate == EGTS_LOADER_AUTH) { if (timeWaitAuth < SystemGetMs()) { LoggerFormatInfo(LOGGER, LOG_SIGN, "Выход по таймеру: Не было обновления после соединения с сервером в течении %d сек", timeOutWaitAuth) EgtsProcessingCloseConnection(&EgtsProcessing); run(); } } // Если в процессе обновления больше if (EgtsProcessing.egtsLoaderUpdate == EGTS_LOADER_LOADING) { if (timeWaitLoad < SystemGetMs()) { LoggerFormatInfo(LOGGER, LOG_SIGN, "Выход по таймеру: Процесс обновления занял больше, %d сек", timeOutWaitLoading) EgtsProcessingCloseConnection(&EgtsProcessing); run(); } } if (EgtsProcessing.egtsLoaderUpdate == EGTS_LOADER_END_LOADING) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход по обновлению") SystemDelayMs(1000); EgtsProcessingCloseConnection(&EgtsProcessing); run(); } SystemDelayMs(1000); } } } */ int main(void) { system_clock_config(); crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE); /* gpio_init_type GPIOInit; gpio_default_para_init(&GPIOInit); GPIOInit.gpio_mode = GPIO_MODE_OUTPUT; GPIOInit.gpio_pull = GPIO_PULL_NONE; GPIOInit.gpio_pins = GPIO_PINS_3; gpio_init(GPIOD, &GPIOInit); gpio_bits_reset(GPIOD, GPIO_PINS_3); gpio_default_para_init(&GPIOInit); GPIOInit.gpio_mode = GPIO_MODE_OUTPUT; GPIOInit.gpio_pull = GPIO_PULL_NONE; GPIOInit.gpio_pins = GPIO_PINS_7; gpio_init(GPIOB, &GPIOInit); gpio_bits_reset(GPIOB, GPIO_PINS_7); */ // osKernelInitialize(); // Gpios_Init(); // SerialPorts_Init(&GPIOS.comIntDir); StorageOnFlash_Init(); // Rtcs_Init(); resultStorage = DeviceStorage_Init(&deviceStorage, &NVM_STORAGE.interface); if (deviceStorage.nvm.SettingsServerConnection.REGION_SIZE_UPDATE <= FIRMWARE_MAIN_AREA_LENGTH) { FirmwareLoader_Init(&FIRMWARE_UVEOS_LOADER, FIRMWARE_MAIN_AREA_LENGTH, FIRMWARE_MAIN_ADDR, FIRMWARE_TELE_RECOVERY_ADDR); FirmwareLoader_Init(&FIRMWARE_TELE_LOADER, FIRMWARE_TELE_AREA_LENGTH, FIRMWARE_TELE_MAIN_ADDR, FIRMWARE_TELE_RECOVERY_ADDR); bool is_FW_UVEOS_main = FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.main); bool is_FW_TELE_main = FirmwareLoader_CheckBlock(&FIRMWARE_TELE_LOADER, &FIRMWARE_TELE_LOADER.main); FirmwareLoader_Init(&FIRMWARE_UPDATE_LOADER, deviceStorage.nvm.SettingsServerConnection.REGION_SIZE_UPDATE, 0, FIRMWARE_TELE_RECOVERY_ADDR); bool is_update = FirmwareLoader_CheckBlock(&FIRMWARE_UPDATE_LOADER, &FIRMWARE_UVEOS_LOADER.update); // Есть обновление if (is_update) { tString32 FW_NAME; FW_NAME.length = *FIRMWARE_UVEOS_LOADER.update.metadata.nameLength; memcpy(FW_NAME.data, FIRMWARE_UVEOS_LOADER.update.metadata.name, FW_NAME.length); uint8_t posDel = findDelimiter(&FW_NAME, '_') + 1; // Получена прошивка телематики if (memcmp(&FW_NAME.data[posDel], "TELE", 4) == 0) { bool is_FW_TELE_update = FirmwareLoader_CheckBlock(&FIRMWARE_TELE_LOADER, &FIRMWARE_TELE_LOADER.update); // Если текущая прошивка неисправна (не загружена) или в секции обновления находится отличная от текущей прошивка bool isNewFirmware = FirmwareLoader_IsUpdateAndMainAreDifferent(&FIRMWARE_TELE_LOADER); if ((!is_FW_TELE_main) || (isNewFirmware)) { FirmwareLoader_CopyUpdateToMain(&FIRMWARE_TELE_LOADER); is_FW_TELE_main = FirmwareLoader_CheckBlock(&FIRMWARE_TELE_LOADER, &FIRMWARE_TELE_LOADER.main); if (is_FW_TELE_main == false) { // Ошибка обновления Телематики } asm("nop"); } asm("nop"); // Получена прошивка УВЭОС } else if (memcmp(&FW_NAME.data[posDel], "UVEOS", 5) == 0) { bool is_FW_UVEOS_update = FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.update); // Если текущая прошивка неисправна (не загружена) или в секции обновления находится отличная от текущей прошивка bool isNewFirmware = FirmwareLoader_IsUpdateAndMainAreDifferent(&FIRMWARE_UVEOS_LOADER); // Если текущая прошивка неисправна (не загружена) или в секции обновления находится отличная от текущей прошивка if ((!is_FW_UVEOS_main) || (isNewFirmware)) { FirmwareLoader_CopyUpdateToMain(&FIRMWARE_UVEOS_LOADER); is_FW_UVEOS_main = FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.main); if (is_FW_UVEOS_main == false) { // Ошибка обновления УВЭОС } asm("nop"); } asm("nop"); // Получена прошивка ключей } else if (memcmp(&FW_NAME.data[0], "CERT", 4) == 0) { asm("nop"); // Получена неизвестная прошивка } else { } } } run(); /* if (deviceStorage.nvm.SettingsServerConnection.EGTS_FLEET_ON == true) { bool isTelematica = loadMetaTelematica(); if (isTelematica) { run(); } else { } } else { run(); } // Если включен модуль телематики, пытаемся загрузить телематику из загрузчика FirmwareLoader_Init(&FIRMWARE_TELE_LOADER, FIRMWARE_TELE_AREA_LENGTH, FIRMWARE_TELE_MAIN_ADDR, FIRMWARE_TELE_RECOVERY_ADDR); InitThreadBlock(mainThread, "main", osPriorityNormal); ThreadBlock_Start(mainThread, 0, MainThread); osKernelStart(); */ }