Bootloader升級方式一————擦、寫flash在RAM中運行


在汽車ECU軟件運行中,軟件代碼運行安全性是第一,在代碼中盡可能的不要固化有flash_erase、flash_write操作存在,主要是防止當出現異常情況時,程序跑飛,誤調用erase、write對flash操作,使得原軟件受到破壞,以致ECU不能正常工作。

Bootloader也稱為啟動引導加載程序,這段程序是硬件設備在上電復位之后執行的第一段軟件代碼。

方式一、為了實現在線更新功能,Bootloader程序需要對flash進行操作。一般情況下,我們將FLASH操作程序作為Bootloader組件的一部分固化在存儲器中,在需要執行flash擦除或燒寫操作時,先將該部分代碼復制到RAM中,再做調用。操作代碼的復制工作也可以在Bootloader啟動階段完成。

方式二、兩級Bootloader方案,沒有在flash存儲器中固化flash擦寫代碼,而是通過通訊口將該部分代碼從上位機下載到指定的RAM出,在需要指出flash擦除或燒寫操作時,再調用RAM中的該代碼。

方式三、Bootloader制作下載引導程序,此軟件不固化flash擦寫代碼,通過通訊口下載另外Bootloader(包含flash擦寫操作)到指定的RAM中,跳轉到RAM運行升級流程。

現在我們做簡單的測試,按照方式二測試,Bootloader中沒有擦寫falsh操作代碼,我們把flash_erase和flash_write編譯后生成的bin信息保存在Bootloader軟件的一個數組中(PS:RAM中就是存放全局變量等信息,通過上位機下載也是存放在指定RAM中,我們可以使下載保存在數組中,效果一樣)。

1、新建flash工程;
2、flash.c文件中主要包含:uint32_t flash_erase(uint32_t u32addr)和uint32_t flash_write(uint32_t u32addr, uint32_t u32data),兩個函數,注意:這兩個函數中不能存在調用外部函數、全局變量信息;

3、編譯生成bin文件,通過.map文件查看這兩個函數的位置;

4、在生成的bin文件中提取出這兩個函數信息,重新生成新的bin文件;注意地址是偶數

   或者上位機直接下載此bin文件(原始bin文件),在MCU端需要從0x218地址處提取數據;

5、在boot中開辟擦、寫兩個函數code長度的數組,為下載擦、寫函數的數據存放在RAM中做准備,以數組形式放在ram中;
6、 將數組地址強制類型轉換為函數指針;

7、在調用這個函數的地址,用函數指針來調;

  1.  
    #define FMC_ISPCMD_PROGRAM 0x21 /*!< ISP Command: Program Flash */
  2.  
    #define FMC_ISPCMD_PAGE_ERASE 0x22 /*!< ISP Command: Page Erase Flash */
  3.  
     
  4.  
    uint32_t flash_erase(uint32_t u32addr)
  5.  
    {
  6.  
    FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE; /* Set ISP Command Code */
  7.  
    FMC->ISPADR = u32addr; /* Set Target ROM Address. The address must be page alignment. */
  8.  
    //__set_PRIMASK(1);
  9.  
    __asm( "CPSID I");
  10.  
    FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
  11.  
    __ISB(); /* To make sure ISP/CPU be Synchronized */
  12.  
    while(FMC->ISPTRG); /* Waiting for ISP Done */
  13.  
    //__set_PRIMASK(0);
  14.  
    __asm( "CPSIE I");
  15.  
     
  16.  
    /* Check ISPFF flag to know whether erase OK or fail. */
  17.  
    if(FMC->ISPCON & FMC_ISPCON_ISPFF_Msk) {
  18.  
    FMC->ISPCON |= FMC_ISPCON_ISPFF_Msk;
  19.  
    return 1;
  20.  
    }
  21.  
    return 0;
  22.  
    }
  23.  
    uint32_t flash_write(uint32_t u32addr, uint32_t u32data)
  24.  
    {
  25.  
    FMC->ISPCMD = FMC_ISPCMD_PROGRAM; /* Set ISP Command Code */
  26.  
    FMC->ISPADR = u32addr; /* Set Target ROM Address. The address must be word alignment. */
  27.  
    FMC->ISPDAT = u32data; /* Set Data to Program */
  28.  
    // __set_PRIMASK(1);
  29.  
    __asm( "CPSID I");
  30.  
    FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
  31.  
    __ISB(); /* To make sure ISP/CPU be Synchronized */
  32.  
    while(FMC->ISPTRG); /* Waiting for ISP Done */
  33.  
    //__set_PRIMASK(0);
  34.  
    __asm( "CPSIE I");
  35.  
     
  36.  
    if(FMC->ISPCON & FMC_ISPCON_ISPFF_Msk) {
  37.  
    FMC->ISPCON |= FMC_ISPCON_ISPFF_Msk;
  38.  
    return 1;
  39.  
    }
  40.  
    return 0;
  41.  
    }

下面我們來是測試代碼:

[cpp]  view plain  copy
 
  1. <code class="language-cpp">//編譯生成的擦、寫文件,此處直接加載到數組中,而非通過上位機下載  
  2. //__align(4) :對齊方式  
  3. __align(4) uint8_t flash_erase_buf[]={  
  4. 0x01,0x46,0x22,0x20,0x11,0x4A,0xD0,0x60,0x10,0x46,0x41,0x60,0x72,0xB6,0x01,0x20,  
  5. 0x10,0x61,0x00,0xBF,0x00,0xBF,0x00,0xBF,0xBF,0xF3,0x6F,0x8F,0x00,0xBF,0x00,0xBF,  
  6. 0x00,0xBF,0x00,0xBF,0x09,0x48,0x00,0x69,0x00,0x28,0xFB,0xD1,0x62,0xB6,0x07,0x48,  
  7. 0x00,0x68,0x40,0x22,0x10,0x40,0x00,0x28,0x06,0xD0,0x04,0x48,0x00,0x68,0x10,0x43,  
  8. 0x02,0x4A,0x10,0x60,0x01,0x20,0x70,0x47,0x00,0x20,0xFC,0xE7,0x00,0xC0,0x00,0x50,  
  9. };  
  10.   
  11. __align(4) uint8_t flash_write_buf[]={  
  12. 0x02,0x46,0x21,0x20,0x12,0x4B,0xD8,0x60,0x18,0x46,0x42,0x60,0x81,0x60,0x72,0xB6,  
  13. 0x01,0x20,0x18,0x61,0x00,0xBF,0x00,0xBF,0x00,0xBF,0xBF,0xF3,0x6F,0x8F,0x00,0xBF,  
  14. 0x00,0xBF,0x00,0xBF,0x00,0xBF,0x0A,0x48,0x00,0x69,0x00,0x28,0xFB,0xD1,0x62,0xB6,  
  15. 0x07,0x48,0x00,0x68,0x40,0x23,0x18,0x40,0x00,0x28,0x06,0xD0,0x04,0x48,0x00,0x68,  
  16. 0x18,0x43,0x03,0x4B,0x18,0x60,0x01,0x20,0x70,0x47,0x00,0x20,0xFC,0xE7,0x00,0x00,  
  17. 0x00,0xC0,0x00,0x50  
  18. };  
  19.   
  20. typedef void (*flash_erase_handler)(uint32_t u32addr);  
  21. typedef void (*flash_write_handler)(uint32_t u32addr, uint32_t u32data);  
  22.   
  23. flash_erase_handler flash_erase = (flash_erase_handler)(flash_erase_buf + 1); // cortex-mo 使用thumb指紋,函數地址低位為1  
  24. flash_write_handler flash_write = (flash_write_handler)(flash_write_buf + 1);  
  25.   
  26. int main(void)  
  27. {   
  28.   
  29.     main_powerOnInit();  
  30.     SYS_UnlockReg();  
  31.     DrvFMC_Open();  
  32.     DrvFMC_EnableAPUpdate();  
  33.     DrvFMC_Erase(SPIFLAG_ADDR);  
  34.     DrvFMC_Write(SPIFLAG_ADDR,0x88776655);  
  35.     DrvFMC_DisableAPUpdate();  
  36.     DrvFMC_Close();  
  37.     SYS_LockReg();  
  38.           
  39.     //DisableInterrupts;  
  40.     SYS_UnlockReg();  
  41.     DrvFMC_Open();  
  42.     DrvFMC_EnableAPUpdate();  
  43.     flash_erase(SPIFLAG_ADDR);  
  44.     flash_write(SPIFLAG_ADDR,0xAABBCCDD);  
  45.     DrvFMC_DisableAPUpdate();  
  46.     DrvFMC_Close();  
  47.     SYS_LockReg();  
  48.     //EnableInterrupts;  
  49.     for (;;);  
  50. }</code>  



測試結果顯示,的確能夠寫法flash中。

下面附上車載診斷升級示意流程圖:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM