| 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 FTP_ENABLE#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_ENABLEextern 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_ENABLEbool mmc_mount(void){    if (disk_initialize(0) != RES_OK) return false;    if (f_mount(&fs, "0:", 1) != FR_OK) return false;    return true;}#endifbool 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 FTP_ENABLEvoid  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 // FTP_ENABLEvoid 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 FTP_ENABLE  spi_flash_update();#endif // FTP_ENABLE  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--;    }}
 |