天天看點

[AUTOSAR][Fls子產品] Flash Driver Module一、 簡介二、 措施使用Demo

Flash Driver Module--jianqiang.xue

  • 一、 簡介
  • 二、 措施
    • 方式一:将FLASH操作程式作為Bootloader元件的一部分固化在存儲器中
    • 方式二:通過通訊口将該部分代碼從上位機下載下傳到指定的RAM
    • 方式三:将Flash功能函數作為資料運作(推薦!!!)
  • 使用Demo

一、 簡介

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

Flash通路代碼(Access Code)不能存儲在被操作的Flash實體塊中,例如我要擦除一個Flash中某一個扇區内容,這個擦除動作的代碼不能存在這個Flash實體塊中(Flash中代碼運作時,相當于讀操作,此時不能擦寫)

PFlash的通路代碼在Fls_17_Dmu_ac.c檔案中,而該檔案的代碼又被燒寫進PFlash中,是以,PFlash不能直接進行Write/Erase操作

解決方案就是PFlash進行Write/Erase操作前,将Write/Erase通路代碼存儲到RAM中,函數實際上是在RAM中執行

在AUTOSAR的負責範圍内,DF0_EEPROM不會存放任何通路代碼。

二、 措施

方式一:将FLASH操作程式作為Bootloader元件的一部分固化在存儲器中

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

方式二:通過通訊口将該部分代碼從上位機下載下傳到指定的RAM

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

jianqiang.xue

方式三:将Flash功能函數作為資料運作(推薦!!!)

  1. 根據MCU建立Flash Driver工程
  2. 編寫flash_erase和flash_write兩個函數
  3. 編譯生成bin檔案,通過.map檔案檢視這兩個函數的位置
  4. 在生成的bin檔案中提取出這兩個函數資訊,注意位址是偶數。

    func_addr = (map_addr-1)

    func_size = (map_size+4)

const uint8_t McuFlashErasePageBuf[] = {
    0xB0, 0xB5, 0x11, 0x4A, 0x30, 0x21, 0x11, 0x70, 0x14, 0x1F, 0x00, 0x23, 0x23, 0x70, 0x0A, 0x25,
    0x15, 0x71, 0x05, 0x0C, 0xD5, 0x70, 0x01, 0x25, 0x25, 0x70, 0xFC, 0x24, 0x04, 0x40, 0xD4, 0x70,
    0x00, 0x0A, 0x10, 0x71, 0x85, 0xF3, 0x10, 0x88, 0x80, 0x20, 0x10, 0x70, 0x10, 0x78, 0x40, 0xB2,
    0x00, 0x28, 0xFB, 0xD5, 0x10, 0x78, 0x00, 0x07, 0xFC, 0xD4, 0x12, 0x78, 0x83, 0xF3, 0x10, 0x88,
    0x0A, 0x40, 0x50, 0x42, 0x50, 0x41, 0xB0, 0xBD, 0x05, 0x00, 0x02, 0x40, 0x10, 0xB5, 0x8C, 0xB0,
};

const uint8_t McuFlashWritePageBuf[] = {
    0xF8, 0xB5, 0x14, 0x46, 0x04, 0x43, 0x01, 0x23, 0xA4, 0x07, 0x4D, 0xD1, 0x00, 0x29, 0x4B, 0xD0,
    0x00, 0x2A, 0x49, 0xD0, 0x00, 0x23, 0x25, 0x4C, 0x00, 0x93, 0x30, 0x26, 0x26, 0x71, 0x00, 0x9D,
    0x25, 0x70, 0x06, 0x25, 0x25, 0x72, 0x05, 0x0C, 0xE5, 0x71, 0x01, 0x27, 0x27, 0x70, 0x05, 0x0A,
    0x25, 0x72, 0xFC, 0x25, 0x05, 0x40, 0xE5, 0x71, 0x02, 0x25, 0x25, 0x70, 0x4D, 0x78, 0x25, 0x72,
    0x0D, 0x78, 0xE5, 0x71, 0x03, 0x25, 0x25, 0x70, 0xCD, 0x78, 0x25, 0x72, 0x8D, 0x78, 0xE5, 0x71,
    0x1D, 0x1D, 0x95, 0x42, 0x0F, 0xD2, 0x04, 0x25, 0x25, 0x70, 0x4D, 0x79, 0x25, 0x72, 0x0D, 0x79,
    0xE5, 0x71, 0x05, 0x25, 0x25, 0x70, 0xCD, 0x79, 0x25, 0x72, 0x8D, 0x79, 0xE5, 0x71, 0x08, 0x30,
    0x08, 0x33, 0x08, 0x31, 0x02, 0xE0, 0x00, 0x1D, 0x09, 0x1D, 0x2B, 0x46, 0x87, 0xF3, 0x10, 0x88,
    0x80, 0x25, 0x25, 0x71, 0x04, 0x25, 0x65, 0x57, 0x00, 0x2D, 0xFB, 0xD5, 0x25, 0x79, 0x2D, 0x07,
    0xFC, 0xD4, 0x27, 0x79, 0x00, 0x25, 0x85, 0xF3, 0x10, 0x88, 0x37, 0x40, 0x93, 0x42, 0x01, 0xD2,
    0x00, 0x2F, 0xBA, 0xD0, 0x7B, 0x42, 0x7B, 0x41, 0x18, 0x46, 0xF8, 0xBD, 0x01, 0x00, 0x02, 0x40,
};
           
  1. 提取資料并存放數組,這些資料不能直接使用,因為無法到達AUTOSAR初衷。

    處理資料:

    (1) 數組資料全部取反,這樣程式炮灰也不會誤觸發。

    (2) 使用flash_erase和flash_write時,需要取反資料,再使用,使用結束後,再清除資料。

// 這裡的資料全部取反才是真正函數,防止指針跑飛誤執行。
#pragma pack (4)
const uint8_t gc_McuFlashErasePageBuf[] = {
    0x73, 0x4f, 0xfe, 0x57, 0x00, 0x08, 0xa6, 0x00, 0xfb, 0x67,
    0xf3, 0xb6, 0x77, 0xbd, 0xee, 0x2c, 0xea, 0xb3, 0xfd, 0xde,
    0x9e, 0xa9, 0xff, 0xd6, 0x04, 0x2a, 0xf7, 0xb6, 0x00, 0x08,
    0xe4, 0x00, 0xbe, 0xe1, 0xc0, 0xdf, 0xf7, 0xbf, 0xdf, 0x8f,
    0xde, 0x87, 0xb6, 0x4d, 0xff, 0xd6, 0x05, 0x2a, 0xf3, 0x4f,
    0xef, 0x42, 0xfc, 0x5f, 0xf7, 0x5e, 0xd6, 0xdd, 0xff, 0x0f,
    0x41, 0x07, 0xbf, 0xbd, 0xf0, 0xff, 0x9c, 0x93, 0x94, 0xd1,
    0x99, 0x8d, 0x8e, 0xa0, 0x9d, 0x8a, 0x8c, 0xdf, 0xc1, 0x4f
};
const uint8_t gc_McuFlashWritePageBuf[] = {
    0x07, 0x4a, 0xeb, 0xb9, 0xfb, 0xbc, 0xfe, 0xdc, 0x5b, 0xf8,
    0xb2, 0x2e, 0xff, 0xd6, 0xb4, 0x2f, 0xff, 0xd5, 0xb6, 0x2f,
    0xff, 0xdc, 0xda, 0xb3, 0xff, 0x6c, 0xcf, 0xd9, 0xd9, 0x8e,
    0xff, 0x62, 0xda, 0x8f, 0xf9, 0xda, 0xda, 0x8d, 0xfa, 0xf3,
    0x1a, 0x8e, 0xfe, 0xd8, 0xd8, 0x8f, 0xfa, 0xf5, 0xda, 0x8d,
    0x03, 0xda, 0xfa, 0xbf, 0x1a, 0x8e, 0xfd, 0xda, 0xda, 0x8f,
    0xb2, 0x87, 0xda, 0x8d, 0xf2, 0x87, 0x1a, 0x8e, 0xfc, 0xda,
    0xda, 0x8f, 0x32, 0x87, 0xda, 0x8d, 0x72, 0x87, 0x1a, 0x8e,
    0xe2, 0xe2, 0x6a, 0xbd, 0xf0, 0x2d, 0xfb, 0xda, 0xda, 0x8f,
    0xb2, 0x86, 0xda, 0x8d, 0xf2, 0x86, 0x1a, 0x8e, 0xfa, 0xda,
    0xda, 0x8f, 0x32, 0x86, 0xda, 0x8d, 0x72, 0x86, 0x1a, 0x8e,
    0xf7, 0xcf, 0xf7, 0xcc, 0xf7, 0xce, 0xfd, 0x1f, 0xff, 0xe2,
    0xf6, 0xe2, 0xd4, 0xb9, 0x78, 0x0c, 0xef, 0x77, 0x7f, 0xda,
    0xda, 0x8e, 0xfb, 0xda, 0x9a, 0xa8, 0xff, 0xd2, 0x04, 0x2a,
    0xda, 0x86, 0xd2, 0xf8, 0x03, 0x2b, 0xd8, 0x86, 0xff, 0xda,
    0x7a, 0x0c, 0xef, 0x77, 0xc8, 0xbf, 0x6c, 0xbd, 0xfe, 0x2d,
    0xff, 0xd0, 0x45, 0x2f, 0x84, 0xbd, 0x84, 0xbe, 0xe7, 0xb9,
    0x07, 0x42, 0xfe, 0xff, 0xfd, 0xbf
};

uint8_t McuFlashErasePageBuf[80] = {0};
uint8_t McuFlashWritePageBuf[176] = {0};
#pragma pack ()
/****************************變量定義******************************/
typedef uint8_t (*McuFlashWritePageHandler)(uint32_t addr, uint8_t* buff, uint32_t len);
typedef uint8_t (*McuFlashErasePageHandler)(uint32_t addr);
/****************************常量定義******************************/
/****************************函數原型******************************/
static void Retrieval(uint8_t *s_buf, uint8_t *l_buf, uint32_t size) {
    for(uint32_t i = 0; i < size; i++) {
        l_buf[i] = ~s_buf[i];
    }
}
void McuFlashInstall(void) {
    // 裝載FlashDriver驅動函數
    Retrieval((uint8_t *)gc_McuFlashErasePageBuf, McuFlashErasePageBuf, 80);
    Retrieval((uint8_t *)gc_McuFlashWritePageBuf, McuFlashWritePageBuf, 176);
}

void McuFlashUnInstall(void) {
    // 解除安裝FlashDriver驅動函數
    memset(McuFlashErasePageBuf, 0, 80);
    memset(McuFlashWritePageBuf, 0, 176);
}

/******************************************************************
 * 函數名稱:McuFlashWritePage
 * 入口參數:addr 寫位址;buff 資料緩存;len 資料長度
 * 出口參數:0 指令操作失敗,1 指令操作成功
 * 函數說明:向指定位址寫入一定長度的資料
 * 位址必須4位元組對齊且在有效操作範圍内;buff本身不能低于len
 * 設定的長度;len必須為4的整數倍;寫入的空間必須已經擦除
 ******************************************************************/
McuFlashWritePageHandler McuFlashWritePage = (McuFlashWritePageHandler)(McuFlashWritePageBuf + 1);

/******************************************************************
 * 函數名稱:McuFlashErasePage
 * 入口參數:addr 頁所在位址
 * 出口參數:0 指令操作失敗,1 指令操作成功
 * 函數說明:擦除頁所在位址的一頁内容
 ******************************************************************/
McuFlashErasePageHandler McuFlashErasePage = (McuFlashErasePageHandler)(McuFlashErasePageBuf + 1);


/******************************變量聲明*****************************/
typedef uint8_t (*McuFlashWritePageHandler)(uint32_t addr, uint8_t* buff, uint32_t len);
typedef uint8_t (*McuFlashErasePageHandler)(uint32_t addr);

// 未安裝flash驅動,調用下面函數會直接跑飛
extern McuFlashWritePageHandler McuFlashWritePage;
extern McuFlashErasePageHandler McuFlashErasePage;
           

LiSun–xuejianqiang

[AUTOSAR][Fls子產品] Flash Driver Module一、 簡介二、 措施使用Demo

使用Demo

// 寫入
    McuFlashInstall();
    McuFlashWritePage(LS_ADDR, data, len);
    McuFlashUnInstall();
// 擦除
    McuFlashInstall();
    McuFlashErasePage(LS_ADDR);
    McuFlashUnInstall();
           

繼續閱讀