Преглед на файлове

ftp: make ftp firmware update work

Sergey Alirzaev преди 4 години
родител
ревизия
3b884012f3
променени са 3 файла, в които са добавени 85 реда и са изтрити 20 реда
  1. 2 1
      iap/Makefile
  2. 60 0
      iap/User/main.c
  3. 23 19
      modules/ftp.c

+ 2 - 1
iap/Makefile

@@ -24,6 +24,7 @@ INCLUDES += -I../stm32/stm32f4x7_ethernet
 INCLUDES += -IUser
 INCLUDES += -Istm32sprog
 INCLUDES += -I../thirdparty/TinyStdio
+INCLUDES += -I../peripheral_modules/inc/
 #----
 
 CSRC = $(wildcard *.c ../stm32/system/*.c)
@@ -45,7 +46,7 @@ CSRC += $(wildcard ../stm32/stm32f4x7_ethernet/*.c)
 CSRC += $(wildcard User/*.c)
 CSRC += $(wildcard stm32sprog/*.c)
 CSRC += $(wildcard ../thirdparty/TinyStdio/*.c)
-
+CSRC += ../peripheral_modules/src/spi_flash.c
 #---
 
 CSRC += $(wildcard syscalls/syscalls.c)

+ 60 - 0
iap/User/main.c

@@ -29,6 +29,9 @@
 #ifdef SLAVEBRD_ENABLE
 #include "stm32sprog.h"
 #endif
+#ifdef HARDWARE_BT6711
+#include "spi_flash.h"
+#endif
 
 /* Секция размещения СRC прошивки */
 #if defined ( __GNUC__ )
@@ -93,6 +96,60 @@ bool CheckFWIsValid(void)
     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;
@@ -235,6 +292,9 @@ void main(void)
       LCD_ClearRow(7);
 #endif
   }
+#ifdef HARDWARE_BT6711
+  spi_flash_update();
+#endif // HARDWARE_BT6711
 
   while (1)
   {

+ 23 - 19
modules/ftp.c

@@ -1,4 +1,5 @@
 #ifdef HARDWARE_BT6711
+#ifndef BT6702_SERVICE
 /*
  * lwftp.c : a lightweight FTP client using raw API of LWIP
  *
@@ -40,6 +41,7 @@
 #include "stm32f4xx.h"
 #include "common_config.h"
 #include "spi_flash.h"
+#include "web_params_api.h"
 
 /** Enable debugging for LWFTP */
 #ifndef LWFTP_DEBUG
@@ -54,6 +56,7 @@
 #define PTRNLEN(s)  s,(sizeof(s)-1)
 #define min(x,y) ((x)<(y)?(x):(y))
 
+static unsigned received_bytes_count = 0;
 
 /** Close control or data pcb
  * @param pointer to lwftp session data
@@ -123,12 +126,14 @@ static err_t lwftp_data_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, er
     tcp_recved(tpcb, p->tot_len);
     pbuf_free(p);
   } else {
-    // NULL pbuf shall lead to close the pcb. Close is postponed after
-    // the session state machine updates. No need to close right here.
-    // Instead we kindly tell data sink we are done
     if (s->data_sink) {
       s->data_sink(s->data_handle, NULL, 0);
     }
+    // NULL pbuf shall lead to close the pcb.
+    if (s->data_pcb) {
+      lwftp_pcb_close(s->data_pcb);
+      s->data_pcb = NULL;
+    }
   }
   return ERR_OK;
 }
@@ -239,10 +244,6 @@ static err_t lwftp_send_msg(lwftp_session_t *s, const char* msg, size_t len)
  */
 static void lwftp_control_close(lwftp_session_t *s, int result)
 {
-  if (s->data_pcb) {
-    lwftp_pcb_close(s->data_pcb);
-    s->data_pcb = NULL;
-  }
   if (s->control_pcb) {
     lwftp_pcb_close(s->control_pcb);
     s->control_pcb = NULL;
@@ -623,7 +624,7 @@ static bool validate_spif_firmware(uint32_t fw_len)
   CRC->CR = 1;
   for (uint32_t offset = 0; offset < crc_offset; offset += 4) {
     uint32_t data;
-    spi_flash_read(offset, &data, sizeof(data), 0);
+    spi_flash_read(spif_firmware_offset + offset, &data, sizeof(data), 0);
     CRC->DR = data;
   }
   uint32_t calculated_crc = CRC->DR;
@@ -636,6 +637,7 @@ static bool validate_spif_firmware(uint32_t fw_len)
 
 static void erase_spif_firmware()
 {
+  printf("ftp: erasing SPI firmware partition...\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);
   }
@@ -644,30 +646,30 @@ static void erase_spif_firmware()
 static unsigned data_sink(void *arg, const char* ptr, unsigned len)
 {
   (void)arg;
-  static unsigned offset = 0;
 
-  if (ptr) {
+  if (ptr && len) {
     // we received some data from the FTP server
-    if (offset == 0) {
+    if (received_bytes_count == 0) {
       // we need to erase the flash before we can write it
       erase_spif_firmware();
     }
 
-    if (offset + len > MAIN_FW_SIZE) {
-      // the firmware won't fit into the MCU flash
+    if (received_bytes_count + len > MAIN_FW_SIZE) {
+      printf("ftp: the firmware is too big! aborting the download\r\n");
       return 0;
     }
-    spi_flash_write(SPI_FLASH_SECTOR_SIZE * FIRMWARE_UPDATE_SECTOR_OFFSET + offset, ptr, len, 0);
-    offset += len;
+    spi_flash_write(SPI_FLASH_SECTOR_SIZE * FIRMWARE_UPDATE_SECTOR_OFFSET + received_bytes_count, ptr, len, 0);
+    received_bytes_count += len;
   } else {
-    // all the data is in
-    uint32_t fw_size = offset;
+    printf("ftp: the firmware is downloaded, verifying...\r\n");
+    uint32_t fw_size = received_bytes_count;
     // next time it comes, overwrite the existing SPI contents
-    offset = 0;
+    received_bytes_count = 0;
 
     bool good_firmware = validate_spif_firmware(fw_size);
     if (good_firmware) {
-      // TODO reboot
+      printf("ftp: the firmware is valid, rebooting...\r\n");
+      HTTP_StartResetTask(true);
     } else {
       // erase it so the bootloader won't try to verify it every time
       erase_spif_firmware();
@@ -678,10 +680,12 @@ static unsigned data_sink(void *arg, const char* ptr, unsigned len)
 
 void start_ftp_client(lwftp_session_t *s)
 {
+  received_bytes_count = 0;
   s->data_sink = data_sink;
   //s->done_fn = ftp_retr_callback;
   lwftp_retr(s);
   // FTP session will continue with the connection callback
 }
 
+#endif // !BT6702_SERVICE
 #endif // HARDWARE_BT6711