#include "stm32f4xx.h" #include "common_config.h" #include "main.h" #include "led.h" #include "systick.h" #include "usart.h" #include "httpserver.h" #include "flash_if.h" #include "settings_api.h" #include "gpio_io.h" #include "crc.h" #include "wdg.h" #include "tinystdio.h" #include "string.h" #include "stm32f4x7_eth.h" #include "netconf.h" /* Секция размещения СRC прошивки */ #if defined ( __GNUC__ ) uint32_t crc __attribute__ ((section (".crc"))) = 0xAABBCCDD; #endif bool IAPviaETH = false; uint8_t fDoneReset = 0; uint8_t fErrorReset = 0; uint8_t fUpload = 0; uint8_t fInvalidFw = 0; uint8_t fBootFailed = 0; uint32_t resetCounter = 0; bool UpdateTimeoutFlag = false; /* this variable is used to create a time reference incremented by 10ms */ __IO uint32_t LocalTime = 0; pFunction Jump_To_App; uint32_t JumpAdd; /** * @brief Общая структура настроек */ extern SETTINGS_t sSettings; void UpdateTimeout_Handler(void); void main(void) { uint8_t bootTry; uint8_t loadMode; WDG_Init(); IO_Init(); InitUSART(); /* Enable PWR peripheral clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); /* Allow access to BKP Domain */ PWR_BackupAccessCmd(ENABLE); /* Включаем тактирование модуля CRC */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE); /* Проверка флага, определяющего состояние устройства. */ /* Флаг установлен - работает Bootloader */ /* Флаг сброшен - запускается основная программа */ SETTINGS_Load(); /* Проверка флага bootTry. Если флаг установлен, значит произошел сбой в основной прошивке. Нужно загружать bootloader и ждать обновления ПО */ /* TODO remove if tested */ //bootTry = sSettings.bootParams.bootTry; loadMode = RTC_ReadBackupRegister(RTC_BKP_DR1); bootTry = RTC_ReadBackupRegister(RTC_BKP_DR2); printf("loadMode: %d\r\nbootTry: %d\r\n", loadMode, bootTry); if (bootTry > 1) { bootTry--; RTC_WriteBackupRegister(RTC_BKP_DR2, bootTry); /* Check if valid stack address (RAM address) then jump to user application */ if (((*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x2FFE0000 ) == 0x20000000) { JumpAdd = *(__IO uint32_t*) (USER_FLASH_FIRST_PAGE_ADDRESS + 4); Jump_To_App = (pFunction) JumpAdd; __set_MSP(*(__IO uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS); Jump_To_App(); } else { /* Флеш пустая, нечего загружать, висим в аварийном режиме */ fInvalidFw = 1; PRINT_USART("\n\rFW empty. Started bootloader\n\r"); } } else if (bootTry == 1) { fBootFailed = 1; PRINT_USART("\n\rFW boot failed. Started bootloader\n\r"); bootTry = 0; loadMode = 1; RTC_WriteBackupRegister(RTC_BKP_DR2, bootTry); RTC_WriteBackupRegister(RTC_BKP_DR1, loadMode); } /* Флаг не установлен прыгаем на основную программу */ if (loadMode == 0) { printf("Run main FW\n\r"); //printf("*(__IO uint32_t*)(USER_FLASH_FIRST_PAGE_ADDRESS) = 0x%X\n\r", *(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS); //printf("*(__IO uint32_t*)(USER_FLASH_FIRST_PAGE_ADDRESS + 4) = 0x%X\n\r", *(__IO uint32_t*)(USER_FLASH_FIRST_PAGE_ADDRESS + 4)); /* Set bootTry flag every time to ensure that * IAP will starts again if FW is corrupted */ bootTry = BOOT_TRY; RTC_WriteBackupRegister(RTC_BKP_DR2, bootTry); /* Check if valid stack address (RAM address) then jump to user application */ if (((*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x2FFE0000 ) == 0x20000000) { /* Jump to user application */ JumpAdd = *(__IO uint32_t*) (USER_FLASH_FIRST_PAGE_ADDRESS + 4); Jump_To_App = (pFunction) JumpAdd; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS); Jump_To_App(); } } /* Загружается Bootloader... */ SysTick_Config(168000);//120000 LED_Init(); PRINT_USART("\n\rBootloader starting... \n\r"); LED_On(RED_STATUS); ETH_BSP_Config(); LwIP_Init(); IAP_httpd_init(); CRC_Init(); //Если нажата DEF начинаем обновление с sd if (IO_BtnDefaultPressed()) { // IAPviaETH = false; // timer_AddFunction(500, &LED_Blinky_Yellow); // SD_NVIC_Init(); } else { IAPviaETH = true; timer_AddFunction(500, &LED_Blinky_Red); } /* Check if valid stack address (RAM address) */ if (((*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x2FFE0000 ) == 0x20000000) { timer_AddFunction(1000, &UpdateTimeout_Handler); } else { /* Флеш пустая, нечего загружать, висим в аварийном режиме */ fInvalidFw = 1; } while (1) { timer_Main(); if (IAPviaETH) { // Обновление по ETH /* check if any packet received */ if (ETH_CheckFrameReceived()) { /* process received ethernet packet */ LwIP_Pkt_Handle(); } /* handle periodic timers for LwIP */ LwIP_Periodic_Handle(LocalTime); if (fDoneReset) { resetCounter++; if (resetCounter > 100000) { loadMode = 0; bootTry = BOOT_TRY; RTC_WriteBackupRegister(RTC_BKP_DR1, loadMode); RTC_WriteBackupRegister(RTC_BKP_DR2, bootTry); /* Set FW update flag */ RTC_WriteBackupRegister(RTC_BKP_DR3, 1); NVIC_SystemReset(); } } if (fErrorReset) { resetCounter++; if (resetCounter > 100000) { NVIC_SystemReset(); } } } //Если нажата DEF переходим в основную прошивку if (IO_BtnDefaultPressed() || UpdateTimeoutFlag) { if (!fUpload && ((*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS) != 0xFFFFFFFF)) { PRINT_USART("\n\rUpdate timeout... Return to main FW\n\r"); loadMode = 0; bootTry = BOOT_TRY; RTC_WriteBackupRegister(RTC_BKP_DR1, loadMode); RTC_WriteBackupRegister(RTC_BKP_DR2, bootTry); NVIC_SystemReset(); } } } } /** * @brief Updates the system local time * @param None * @retval None */ void Time_Update(void) { LocalTime += SYSTEMTICK_PERIOD_MS; } /** * @brief */ u32_t sys_now(void) { return LocalTime; } /** * @brief Error handler * @param None * @retval None */ void Error_Handler(void) { LED_Off(RED_STATUS); LED_Off(GREEN_STATUS); timer_AddFunction(500, &LED_Blinky_Red); while (1) { timer_Main(); } } /** * @brief */ void UpdateTimeout_Handler(void) { static char lcdbuf[32] = {0}; static uint8_t time = UPDATE_TIMEOUT; if ((fUpload) || (fInvalidFw)) return; if (time == 0) { UpdateTimeoutFlag = true; } else { time--; } }