STM32遠程升級基本思路

STM32遠程升級基本思路


  • 開發環境:IAR for ARM 8.30.1
  • MCU:STM32F103RCT6
  • 存儲介質:w25q32

1.實現思路

1.需要一個bootloader程序和APP程序
2.APP程序通過網絡或者串口等方式將要升級的代碼寫到spiFlash中約定的位置,然後重啓
3.bootloader判斷spiFlash中是否有文件需要更新,有就將文件更新到stm32的內部Flash的App區域,然後跳 轉到APP,否則直接跳轉

2.知識儲備

STM32閃存模塊組織

stm32F103RCT6屬於大容量型產品,ROM:256K,RAM:48K,頁大小爲2k,閃存分爲三個塊:

  • 主存儲器:頁大小爲2K,256K也就是128頁
  • 信息塊:分爲兩個部分:
    • 系統存儲器(存放啓動程序代碼,ST出廠固化,不可更改,用於ISP編程)
    • 用戶選項字節(Option Bytes,可以用它設置讀寫保護,硬件看門狗使能啥的)
  • 閃存存儲器接口寄存器:操作stm32內部Flash要用到這些寄存器;

在這裏插入圖片描述

啓動配置

在這裏插入圖片描述
● 從主閃存存儲器啓動:主閃存存儲器被映射到啓動空間(0x0000 0000)
● 從系統存儲器啓動:系統存儲器被映射到啓動空間(0x0000 0000)
● 從內置SRAM啓動:只能在0x2000 0000開始的地址區訪問SRAM

3.Bootloader和App的工程設置

Bootloader和App公用RAM,佔用不同ROM空間,16K給Bootloader,240K給App

  • Bootloader:
    • Vector Table Start:0x0800 0000
    • ROM:0x0800 0000 ~ 0x0800 4000
    • RAM:0x0800 0000 ~ 0x0800 BFFF
    • CSTACK: 0x400
    • Heap: 0x0
  • App:
    • Vector Table Start:0x0800 4000
    • ROM:0x0800 4000 ~ 0x0803 FFFF
    • RAM:0x0800 0000 ~ 0x0800 BFFF
    • CSTACK: 0x400
    • Heap: 0x0
      App程序中還要注意到的地方:修改中斷向量偏移VECT_TAB_OFFSET,偏移量就是bootloader程序大小
      在這裏插入圖片描述

4.Bootloader程序編寫

話不多說,下面就是代碼:

  • 頭文件
#define FLASH_MAX_ADDR                      (0x0803FFFFU)  //MCU的Flash最大地址

#ifndef FLASH_PAGE_SIZE
  #define FLASH_PAGE_SIZE                   (0x800U)       //MCU的Flash的頁大小,大容量的爲2K,其他是1K
#endif

#define APP_BASEADDR                        (0x08004000U)  //升級程序地址


#define APP_PAGE_NUM                        ((FLASH_MAX_ADDR-APP_BASEADDR)/FLASH_PAGE_SIZE+1)

#define SPIFLASHBUF_MAX_LEN                 (0x1000U)  //spi flash最大緩衝4096字節
  • C文件
void JumpToApplication(void)
{
  typedef  void (*pFunction)(void);
  pFunction Jump_To_Application;
  u32 JumpAddress;    
  
  /* Test if user code is programmed starting from address "ApplicationAddress" */
  if (((*(__IO uint32_t*)APP_BASEADDR) & 0x2FFE0000 ) == 0x20000000)
  {
    
    DBG_LOG("----[Boot]Jump to Application!!!\r\n");
    LED_ALL_OFF();
    __disable_irq();
    
    /* Jump to user application */
    JumpAddress = *(__IO uint32_t*) (APP_BASEADDR + 4);
    Jump_To_Application = (pFunction) JumpAddress;
    /* Initialize user application's Stack Pointer */
    __set_MSP(*(__IO uint32_t*) APP_BASEADDR);
    Jump_To_Application();
  }
  else
  {
    DBG_LOG("----[Boot]Application Address is ERROR!!!\r\n");
    LED_ALL_ON();
  }    
}

union {
  u32 stm32[SPIFLASHBUF_MAX_LEN/4];
  u8  spi[SPIFLASHBUF_MAX_LEN];
}Flash;

void Boot_Initializes(void)
{

  u16 i,j;
  
  u32 update_file_mark;
  
  u32 writeFlashData;
 
  HAL_StatusTypeDef status;
  
  FLASH_EraseInitTypeDef f;
  
	f.TypeErase = FLASH_TYPEERASE_PAGES;
	f.PageAddress = APP_BASEADDR;
	f.NbPages = APP_PAGE_NUM;

  //1.判斷spi flash DFU區是否有文件需要升級
  SFlash_Read(SECTOR_ADDR(SECTOR_DFU_START),(u8 *)&update_file_mark,4);
  
  if(update_file_mark == 0xFFFFFFFF){
    DBG_LOG("[Boot] No Firmware Need to Update."); 
    LED_ON(ERR);
    JumpToApplication();
    return;
  }
  //有文件需要升級
  DBG_LOG("[Boot] New Firmware Exist! Update Beginning..."); 
  
  //2.Flash解鎖
  status = HAL_FLASH_Unlock();
  
  if(status != HAL_OK){
    DBG_LOG("[Boot] FLASH Unlock Failed."); 
    LED_ON(ERR);
    return;
  }
  DBG_LOG("[Boot] FLASH Unlock Ok."); 
  
  DBG_LOG("[Boot] Ready to Erase Flash ..."); 
  //3.擦除Flash
  status = HAL_FLASHEx_Erase(&f,&writeFlashData);
  
  if(status != HAL_OK){
    DBG_LOG("[Boot] Flash Erase Failed."); 
    LED_ON(ERR);
    return;
  }
  DBG_LOG("[Boot] Flash Erase OK."); 
  
  
  //4.從SPIFlash中讀出數據然後copy到內部Flash中
  for(i = 0;i < (APP_PAGE_NUM / 2);i++){
    
    SFlash_Read(SECTOR_ADDR(SECTOR_DFU_START) + SPIFLASHBUF_MAX_LEN*i, Flash.spi, SPIFLASHBUF_MAX_LEN);
    
    DBG_LOG("[Boot] Write Flash Progress:%d%%",(i*100/(APP_PAGE_NUM / 2)) ); 
    
    LED_TOGGLE(WIFI);
    
    for(j = 0;j < (SPIFLASHBUF_MAX_LEN/4);j++){
      //注意基地址是在變化的
      HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, APP_BASEADDR+SPIFLASHBUF_MAX_LEN*i+4*j, Flash.stm32[j]);
    }    
  }
  
  DBG_LOG("[Boot] Write Flash Progress:100%%");
  DBG_LOG("[Boot] Program Complete!!!");
  
  //5.Flash上鎖
  HAL_FLASH_Lock();  
  
  //6.跳轉到用戶程序區
  JumpToApplication();
  
}


發佈了36 篇原創文章 · 獲贊 14 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章