123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- #include "stm32f4xx.h"
- #include "common_config.h"
- #include "conf.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 "gpio.h"
- #include "crc.h"
- #include "wdg.h"
- #include "tinystdio.h"
- #include "time.h"
- #include "string.h"
- #include "stm32f4x7_eth.h"
- #include "netconf.h"
- #include "rng.h"
- #ifdef SD_ENABLE
- #include "SD_Card/sdio_sd.h"
- #include "FATFS/ff.h"
- #include "FATFS/diskio.h"
- #endif
- #ifdef LCD_ENABLE
- #include "lcd.h"
- #endif
- #ifdef SLAVEBRD_ENABLE
- #include "stm32sprog.h"
- #endif
- #ifdef HARDWARE_BT6711
- #include "spi_flash.h"
- #endif
- /* Секция размещения СRC прошивки */
- #if defined ( __GNUC__ )
- uint32_t crc __attribute__ ((section (".crc"))) = 0xAABBCCDD;
- #endif
- #define FW_FILE_NAME MAIN_FW_NAME
- /*
- * Bootloader verification key section.
- * Use "openssl rand -hex 8" to generate new key.
- * */
- uint64_t bootkey __attribute__ ((section (".bootkey"))) = 0x92dc73b8fef3b041;
- bool IAPviaETH = false;
- bool fDoneReset = false;
- bool fUpload = false;
- bool fInvalidFw = false;
- bool fBootFailed = false;
- volatile uint32_t resetCounter = 0;
- bool UpdateTimeoutFlag = false;
- #ifdef SD_ENABLE
- extern FATFS fs;
- extern FIL fil_obj;
- #endif
- /* 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);
- #ifdef SD_ENABLE
- bool mmc_mount(void)
- {
- if (disk_initialize(0) != RES_OK) return false;
- if (f_mount(&fs, "0:", 1) != FR_OK) return false;
- return true;
- }
- #endif
- bool CheckFWIsValid(void)
- {
- if (((*(__IO uint32_t *)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x2FFE0000 ) == 0x20000000 &&
- *(__IO uint32_t *)USER_FLASH_CRC_ADDRESS != 0xFFFFFFFF) {
- return true;
- }
- printf("\r\nFW empty. Started bootloader\r\n");
- return false;
- }
- #ifdef HARDWARE_BT6711
- void spi_flash_update(void)
- {
- printf("ftp: trying to update the firmware from the SPI flash\r\n");
- const uint32_t spif_firmware_offset = SPI_FLASH_SECTOR_SIZE * FIRMWARE_UPDATE_SECTOR_OFFSET;
- uint32_t fw_begin;
- spi_flash_init();
- spi_flash_read(spif_firmware_offset, &fw_begin, 4, 0);
- const uint32_t crc_offset = USER_FLASH_CRC_ADDRESS - USER_FLASH_FIRST_PAGE_ADDRESS;
- uint32_t expected_crc;
- spi_flash_read(spif_firmware_offset + crc_offset, &expected_crc, 4, 0);
- bool present_firmware = (fw_begin != 0xFFFFFFFF) || (expected_crc != 0xFFFFFFFF);
- if (!present_firmware) {
- printf("ftp: no firmware-like data is present on the SPI flash\r\n");
- return;
- }
- // check CRC
- CRC->CR = 1;
- for (uint32_t offset = 0; offset < crc_offset; offset += 4) {
- uint32_t data;
- spi_flash_read(spif_firmware_offset + offset, &data, sizeof(data), 0);
- CRC->DR = data;
- }
- uint32_t calculated_crc = CRC->DR;
- if (expected_crc != calculated_crc) {
- printf("ftp: calculated CRC (%lx) doesn't match the expected CRC (%lx)!\r\n", calculated_crc, expected_crc);
- return;
- }
- printf("ftp: writing the stm32 flash\r\n");
- FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
- FLASH_If_Init(); // unlock it again
- uint8_t buf[1024];
- for (uint32_t offset = 0; offset < MAIN_FW_SIZE; offset += sizeof(buf)) {
- spi_flash_read(spif_firmware_offset + offset, buf, sizeof(buf), 0);
- uint8_t *addr = USER_FLASH_FIRST_PAGE_ADDRESS + offset;
- FLASH_If_Write(&addr, buf, sizeof(buf) / 4);
- }
- printf("ftp: erasing the SPI flash\r\n");
- for (int sec = 0; sec < FIRMWARE_UPDATE_SECTOR_COUNT; ++sec) {
- spi_flash_erase_sector(SPI_FLASH_SECTOR_SIZE * (FIRMWARE_UPDATE_SECTOR_OFFSET + sec), 0);
- }
- printf("ftp: update successful, rebooting...\r\n");
- SET_FWUPDATED_FLAG();
- CLEAR_FWINVALID_FLAG();
- RTC_WriteBackupRegister(RTC_BKP_DR1, 0); // loadMode
- NVIC_SystemReset();
- }
- #endif // HARDWARE_BT6711
- void main(void)
- {
- uint8_t bootTry;
- uint8_t loadMode;
- gpio_init();
- WDG_Init();
- InitUSART();
- #ifdef PRINTF_STDLIB
- setvbuf(stdin, NULL, _IONBF, 0);
- setvbuf(stdout, NULL, _IONBF, 0);
- setvbuf(stderr, NULL, _IONBF, 0);
- #endif
- /* 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 и ждать обновления ПО */
- loadMode = RTC_ReadBackupRegister(RTC_BKP_DR1);
- bootTry = RTC_ReadBackupRegister(RTC_BKP_DR2);
- fInvalidFw = RTC_ReadBackupRegister(RTC_BKP_DR7);
- printf("\r\nloadMode: %d\r\nbootTry: %d\r\n", loadMode, bootTry);
- printf("fInvalidFw: %s\r\n", fInvalidFw ? "true" : "false");
-
- if (bootTry > 1) {
- bootTry--;
- RTC_WriteBackupRegister(RTC_BKP_DR2, bootTry);
- /* Check if valid stack address (RAM address) then jump to user application */
- if (CheckFWIsValid()) {
- CLEAR_FWINVALID_FLAG();
- /* 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();
- } else {
- /* Флеш пустая, нечего загружать, висим в аварийном режиме */
- SET_FWINVALID_FLAG();
- }
- } else if (bootTry == 1) {
- fBootFailed = 1;
- printf("\r\nFW boot failed. Started bootloader\r\n");
- bootTry = 0;
- loadMode = 1;
- RTC_WriteBackupRegister(RTC_BKP_DR2, bootTry);
- RTC_WriteBackupRegister(RTC_BKP_DR1, loadMode);
- }
- /* Флаг не установлен прыгаем на основную программу */
- if (loadMode == 0) {
- printf("Run main FW\r\n");
- //printf("*(__IO uint32_t*)(USER_FLASH_FIRST_PAGE_ADDRESS) = 0x%X\r\n", *(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS);
- //printf("*(__IO uint32_t*)(USER_FLASH_FIRST_PAGE_ADDRESS + 4) = 0x%X\r\n", *(__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 (CheckFWIsValid()) {
- CLEAR_FWINVALID_FLAG();
- /* 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();
- LED_On(LED_INIT_ERR);
- PRINT_USART("\n\rBootloader starting... \n\r");
- #ifdef LCD_ENABLE
- LCD_Init();
- LCD_PrintAligned(1, alignCENTER, "Обновление ПО");
- #endif
- /* Random number generator */
- RNG_Init();
- ETH_BSP_Config();
- LwIP_Init();
- IAP_httpd_init();
- CRC_Init();
- //Если нажата DEF начинаем обновление с sd
- if (IO_BtnDefaultPressed()) {
- #ifdef SD_ENABLE
- IAPviaETH = false;
- timer_AddFunction(500, &LED_Blinky_Red);
- SD_NVIC_Init();
- #endif
- } 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 && !fInvalidFw) {
- #if UPDATE_TIMEOUT != 0
- timer_AddFunction(1000, &UpdateTimeout_Handler);
- #endif
- } else {
- update_timeout = 0;
- /* Флеш пустая, нечего загружать, висим в аварийном режиме */
- SET_FWINVALID_FLAG();
- #ifdef LCD_ENABLE
- LCD_PrintAligned(5, alignCENTER, "Аварийный режим");
- LCD_PrintAligned(7, alignCENTER, "Ошибка ПО");
- #endif
- }
- if (fBootFailed) {
- #ifdef LCD_ENABLE
- LCD_PrintAligned(5, alignCENTER, "Аварийный режим");
- LCD_ClearRow(7);
- #endif
- }
- #ifdef HARDWARE_BT6711
- spi_flash_update();
- #endif // HARDWARE_BT6711
- while (1)
- {
- timer_Main();
- if (IAPviaETH) { // Обновление по ETH
- /* Handle received packets and periodic timers for LwIP */
- LwIP_Periodic_Handle(0);
- if (fDoneReset) {
- resetCounter++;
- if (resetCounter > 400000) {
- loadMode = 0;
- bootTry = BOOT_TRY;
- RTC_WriteBackupRegister(RTC_BKP_DR1, loadMode);
- RTC_WriteBackupRegister(RTC_BKP_DR2, bootTry);
- SET_FWUPDATED_FLAG();
- CLEAR_FWINVALID_FLAG();
- #ifdef SLAVEBRD_ENABLE
- /* Reboot daughter board */
- stmReboot();
- #endif
- /* Self reboot */
- NVIC_SystemReset();
- }
- }
- } else {
- #ifdef SD_ENABLE
- // Обновление с SD
- // Пробуем смонтировать SD
- if (mmc_mount()) {
- // Пробуем открыть файл с именем FW_FILE_NAME
- timer_Stop(&LED_Blinky_Yellow);
- LED_Off(RED1_INT);
- LED_Off(GREEN_INT);
- if (f_open(&fil_obj, FW_FILE_NAME, FA_READ | FA_OPEN_EXISTING) == FR_OK) { // открываем файл
- LED_On(GREEN_INT);
- if (startFlashing() < 0) {
- Error_Handler();
- }
- f_close(&fil_obj);
- // CRC посчитанная при сборке и записанная в последине 4 байта прошивки
- // Должна сойтись с CRC посчитанной на контроллере
- if (CRC_Read() == CRC_Calculate()) {
- loadMode = 0;
- bootTry = BOOT_TRY;
- RTC_WriteBackupRegister(RTC_BKP_DR1, loadMode);
- RTC_WriteBackupRegister(RTC_BKP_DR2, bootTry);
- #ifdef SLAVEBRD_ENABLE
- /* Reboot daughter board */
- stmReboot();
- #endif
- /* Self reboot */
- NVIC_SystemReset();
- } else {
- Error_Handler();
- }
- } else { // Файл не найден
- LED_On(RED1_INT);
- }
- }
- #endif
- }
- //Если нажата DEF переходим в основную прошивку
- if (IO_BtnDefaultPressed() || UpdateTimeoutFlag) {
- if (!fUpload && ((*(__IO uint32_t *)USER_FLASH_FIRST_PAGE_ADDRESS) != 0xFFFFFFFF)) {
- printf("\r\nUpdate timeout... Return to main FW\r\n");
- loadMode = 0;
- bootTry = BOOT_TRY;
- RTC_WriteBackupRegister(RTC_BKP_DR1, loadMode);
- RTC_WriteBackupRegister(RTC_BKP_DR2, bootTry);
- #ifdef SLAVEBRD_ENABLE
- /* Reboot daughter board */
- stmReboot();
- #endif
- /* Self reboot */
- 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(LED_INIT_ERR);
- LED_Off(LED_INIT_OK);
- timer_AddFunction(500, &LED_Blinky_Red);
- while (1)
- {
- timer_Main();
- }
- }
- /**
- * @brief
- */
- void UpdateTimeout_Handler(void)
- {
- if ((fUpload) || (fInvalidFw) || (fDoneReset)) {
- return;
- }
- if (update_timeout == 0) {
- UpdateTimeoutFlag = true;
- } else {
- #ifdef LCD_ENABLE
- static char lcdbuf[32] = {0};
- sprintf(lcdbuf, "Ожидание (%d) ", update_timeout);
- LCD_ClearRow(7);
- LCD_PrintAligned(7, alignCENTER, lcdbuf);
- #endif
- update_timeout--;
- }
- }
|