#include "main.h" void soft_wdt(void *params); void init_task(void *params); bool jump_to_app(uint32_t address); void (*pftarget)(void); bool boot_failed = false; int main() { uint8_t load_mode; uint8_t boot_try; uint8_t fw_invalid = 0; nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE); pwc_battery_powered_domain_access(TRUE); system_clock_config(); delay_init(); uart_print_init(115200); // Флаг - нужно ли обновляться load_mode = bpr_data_read(BPR_DATA1); // Число попыток загрузки основного ПО boot_try = bpr_data_read(BPR_DATA2); DBG printf("[IAP] load_mode: %u, boot_try: %u\r\n", load_mode, boot_try); #if 1 // Если есть попытки, то пытаемся загрузить FW. // Используем ограниченное число попыток загрузить основное FW. if (boot_try > 1) { boot_try--; bpr_data_write(BPR_DATA2, boot_try); if (!jump_to_app(USER_FLASH_FIRST_PAGE_ADDRESS)) { // Флеш пустая. Нечего загружать fw_invalid = 1; boot_failed = false; DBG printf("FW empty! Bootloader starting...\n\r"); } } else if (boot_try == 1) { boot_failed = true; DBG printf("FW boot failed. Bootloader starting...\r\n"); load_mode = 1; boot_try = 0; bpr_data_write(BPR_DATA1, load_mode); bpr_data_write(BPR_DATA2, boot_try); } if ((load_mode == 0) && (!fw_invalid)) { DBG printf("Run main FW\r\n"); bpr_data_write(BPR_DATA2, BOOT_TRY); DBG printf("Go to main FW...\r\n"); jump_to_app(USER_FLASH_FIRST_PAGE_ADDRESS); } #endif DBG printf("IAP starting...\r\n"); #if 0 // ------------------------------------------------------------------------- // Для теста. Сброс. DBG printf("For test reset load_mode flag and jump to FW\r\n"); bpr_data_write(BPR_DATA1, 0); jump_to_app(0x08021000); #endif gpio_wdt_init(); gpio_mbaddr_init(); taskENTER_CRITICAL(); xTaskCreate(soft_wdt, "soft_wdt", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); xTaskCreate(init_task, "init_task", 10*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL); taskEXIT_CRITICAL(); vTaskStartScheduler(); while (1) {} } // bool jump_to_app(uint32_t address) { uint32_t stkptr, jumpaddr; stkptr = *(uint32_t *)address; jumpaddr = *(uint32_t *)(address + sizeof(uint32_t)); //if (((*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x20000000) == 0x20000000) if (*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS != 0xFFFFFFFF) { __set_MSP(stkptr); pftarget = (void (*) (void))jumpaddr; pftarget(); } return false; } // void soft_wdt(void *params) { (void)params; for (;;) { extern_wdt_togle(); // extern WDT vTaskDelay(500); } } // void init_task(void *params) { (void)params; crm_periph_clock_enable(CRM_CRC_PERIPH_CLOCK, TRUE); init_settings(); settings_load(&settings); mb_init(); for (;;) { vTaskDelay(500); } }