在汽車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、在調用這個函數的地址,用函數指針來調;
-
-
-
-
uint32_t flash_erase(uint32_t u32addr)
-
{
-
FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE; /* Set ISP Command Code */
-
FMC->ISPADR = u32addr; /* Set Target ROM Address. The address must be page alignment. */
-
//__set_PRIMASK(1);
-
__asm( "CPSID I");
-
FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
-
__ISB(); /* To make sure ISP/CPU be Synchronized */
-
while(FMC->ISPTRG); /* Waiting for ISP Done */
-
//__set_PRIMASK(0);
-
__asm( "CPSIE I");
-
-
/* Check ISPFF flag to know whether erase OK or fail. */
-
if(FMC->ISPCON & FMC_ISPCON_ISPFF_Msk) {
-
FMC->ISPCON |= FMC_ISPCON_ISPFF_Msk;
-
return 1;
-
}
-
return 0;
-
}
-
uint32_t flash_write(uint32_t u32addr, uint32_t u32data)
-
{
-
FMC->ISPCMD = FMC_ISPCMD_PROGRAM; /* Set ISP Command Code */
-
FMC->ISPADR = u32addr; /* Set Target ROM Address. The address must be word alignment. */
-
FMC->ISPDAT = u32data; /* Set Data to Program */
-
// __set_PRIMASK(1);
-
__asm( "CPSID I");
-
FMC->ISPTRG = 0x1; /* Trigger to start ISP procedure */
-
__ISB(); /* To make sure ISP/CPU be Synchronized */
-
while(FMC->ISPTRG); /* Waiting for ISP Done */
-
//__set_PRIMASK(0);
-
__asm( "CPSIE I");
-
-
if(FMC->ISPCON & FMC_ISPCON_ISPFF_Msk) {
-
FMC->ISPCON |= FMC_ISPCON_ISPFF_Msk;
-
return 1;
-
}
-
return 0;
-
}
下面我們來是測試代碼:
- <code class="language-cpp">//編譯生成的擦、寫文件,此處直接加載到數組中,而非通過上位機下載
- //__align(4) :對齊方式
- __align(4) uint8_t flash_erase_buf[]={
- 0x01,0x46,0x22,0x20,0x11,0x4A,0xD0,0x60,0x10,0x46,0x41,0x60,0x72,0xB6,0x01,0x20,
- 0x10,0x61,0x00,0xBF,0x00,0xBF,0x00,0xBF,0xBF,0xF3,0x6F,0x8F,0x00,0xBF,0x00,0xBF,
- 0x00,0xBF,0x00,0xBF,0x09,0x48,0x00,0x69,0x00,0x28,0xFB,0xD1,0x62,0xB6,0x07,0x48,
- 0x00,0x68,0x40,0x22,0x10,0x40,0x00,0x28,0x06,0xD0,0x04,0x48,0x00,0x68,0x10,0x43,
- 0x02,0x4A,0x10,0x60,0x01,0x20,0x70,0x47,0x00,0x20,0xFC,0xE7,0x00,0xC0,0x00,0x50,
- };
- __align(4) uint8_t flash_write_buf[]={
- 0x02,0x46,0x21,0x20,0x12,0x4B,0xD8,0x60,0x18,0x46,0x42,0x60,0x81,0x60,0x72,0xB6,
- 0x01,0x20,0x18,0x61,0x00,0xBF,0x00,0xBF,0x00,0xBF,0xBF,0xF3,0x6F,0x8F,0x00,0xBF,
- 0x00,0xBF,0x00,0xBF,0x00,0xBF,0x0A,0x48,0x00,0x69,0x00,0x28,0xFB,0xD1,0x62,0xB6,
- 0x07,0x48,0x00,0x68,0x40,0x23,0x18,0x40,0x00,0x28,0x06,0xD0,0x04,0x48,0x00,0x68,
- 0x18,0x43,0x03,0x4B,0x18,0x60,0x01,0x20,0x70,0x47,0x00,0x20,0xFC,0xE7,0x00,0x00,
- 0x00,0xC0,0x00,0x50
- };
- typedef void (*flash_erase_handler)(uint32_t u32addr);
- typedef void (*flash_write_handler)(uint32_t u32addr, uint32_t u32data);
- flash_erase_handler flash_erase = (flash_erase_handler)(flash_erase_buf + 1); // cortex-mo 使用thumb指紋,函數地址低位為1
- flash_write_handler flash_write = (flash_write_handler)(flash_write_buf + 1);
- int main(void)
- {
- main_powerOnInit();
- SYS_UnlockReg();
- DrvFMC_Open();
- DrvFMC_EnableAPUpdate();
- DrvFMC_Erase(SPIFLAG_ADDR);
- DrvFMC_Write(SPIFLAG_ADDR,0x88776655);
- DrvFMC_DisableAPUpdate();
- DrvFMC_Close();
- SYS_LockReg();
- //DisableInterrupts;
- SYS_UnlockReg();
- DrvFMC_Open();
- DrvFMC_EnableAPUpdate();
- flash_erase(SPIFLAG_ADDR);
- flash_write(SPIFLAG_ADDR,0xAABBCCDD);
- DrvFMC_DisableAPUpdate();
- DrvFMC_Close();
- SYS_LockReg();
- //EnableInterrupts;
- for (;;);
- }</code>
測試結果顯示,的確能夠寫法flash中。
下面附上車載診斷升級示意流程圖: