Bootloader 介紹
大多數(shù)Bootloader 包含兩種操作模式。
- 啟動加載模式
- 下載模式
對于大多數(shù)汽車軟件開發(fā)者來說,從客戶需求的角度,他們更多關(guān)心Bootloader的下載模式。下面我們將從CAN Bootloader的一般需求入手,來介紹一下CAN Bootloader 的整個實現(xiàn)過程。
CAN Bootloader 簡述
通過CAN網(wǎng)絡(luò)升級一般需要考慮下面幾個方向。
01 針對單一節(jié)點
CAN網(wǎng)絡(luò)是串行結(jié)構(gòu),在對節(jié)點升級的時候,不能被別的節(jié)點影響,也不能影響到別的節(jié)點。這里就需要進(jìn)行點對點升級。在OEM 的規(guī)范中會對每一個ECU 都有自己的診斷ID。一般情況下針對CAN網(wǎng)絡(luò)的ECU有。
兩個接收ID
- 功能尋址ID
- 物理尋址ID
一個發(fā)送ID
- 診斷發(fā)送ID
這樣可以確保點對點的操作,和其他節(jié)點互相不干擾。
02 節(jié)點的智能設(shè)計
在CAN網(wǎng)絡(luò)中實現(xiàn)數(shù)據(jù)更新,最進(jìn)本的就是master ECU 把數(shù)據(jù)有效的傳輸給Slave ECU, 這樣Slave ECU 對自身的flash 進(jìn)行操作。在這個過程中需要對數(shù)據(jù)進(jìn)行一定要求。
- 保證數(shù)據(jù)傳遞的有效性-->傳輸過程沒有錯誤
- 保證數(shù)據(jù)本身的真實性--> 未被篡改
- 保證數(shù)據(jù)發(fā)送方的可靠性-->被授權(quán)的ECU
- 保證數(shù)據(jù)本身的正確性--> 是否與Bootloader 兼容
- 等等需求
這里對傳輸過程的保證,汽車OEM 一般通過UDS 讓Master ECU 和 Slave 進(jìn)行交互。通過握手協(xié)議,以及一些routine 來對上面需求進(jìn)行一一實現(xiàn)。
針對UDS 這里不一一介紹,可以翻閱14229 自行查詢。
注意這里缺少新版的 0x29 服務(wù)。
UDS診斷29認(rèn)證服務(wù)-Authentication Service
03 進(jìn)入Bootloader 模式
一般來說這里有一下幾種方式
- APP 主動跳轉(zhuǎn)至 Bootloader 模式
- 上電啟動由于Bootloader 檢測APP 失效,主動停留在Bootloader
- APP 軟件異常,自動復(fù)位到Bootloader 模式下。
這里針對OEM 的升級需求,一般是 第一種, APP 主動跳轉(zhuǎn)至Bootloader 模式。因為Bootloader 不一定都是需要依賴UDS的,這里統(tǒng)一叫Bootloader 模式,OEM 的 UDS 的規(guī)范里面的名稱叫做programming session。
一般來說OEM 會在APP 里面先進(jìn)行session 跳轉(zhuǎn),身份驗證。
最后通過 10 02 命令讓APP 跳轉(zhuǎn)到Bootloader 模式下。
在我們進(jìn)行bootloader設(shè)計的時候,可以通過任何特定方式,注意這里的特定方式不能是隨隨便便就可以觸發(fā) 的,防止誤觸進(jìn)入bootloader 模式。
因為跳轉(zhuǎn)的邏輯是 APP 檢測到一定的條件,然后 對某些寄存器,或者某些Bootloader 可讀的內(nèi)存空間進(jìn)行寫flag. 隨后進(jìn)行reset. 這樣在reset完成之后, bootloader 會檢測到,這次不需要跳轉(zhuǎn)至APP 了。
04 對bootloader的要求
從實際的研發(fā)需求出發(fā),這里列出了一些常用的需求。實際OEM 的bootloader 可能會細(xì)化需求,但是最終都是為了下面的目的提出來的需求。
- 多次數(shù)據(jù)更新
- 刷寫速度,傳輸速度
- 差分更新
- 身份驗證
- 數(shù)據(jù)格式的標(biāo)準(zhǔn)化
- 對數(shù)據(jù)的完整性,有效性等進(jìn)行校驗
- 對APP 的有效性進(jìn)行校驗
- 上位機方便友好
OEM 對Bootloader 的基本要求
在OEM 的需求里,在刷寫過程一般分為三個步驟。
- 前處理
- 刷寫
- 后處理
分別是做什么的呢?
前處理
需求各不相同,但是目的基本都一致。
- 避免其他節(jié)點對升級過程的影響
- 避免自身節(jié)點對升級過程的影響
- 避免自身節(jié)點對其他節(jié)點的影響
刷寫
通過一系列的UDS 命令進(jìn)行 點對點 交互。其目的和前面提到的一致。
- 發(fā)送數(shù)據(jù)的ECU 可靠
- 數(shù)據(jù)傳輸過程可靠
- 數(shù)據(jù)有效性(識別有沒有被篡改)
- 數(shù)據(jù)加密解密數(shù)據(jù)安全
- 等等
后處理
解除自身的特殊狀態(tài)。更新配置參數(shù)等等。
這里面 ECU 需要做好和APP 的相互校驗。需要達(dá)到
- APP 是否有效,Bootloader 需要能判斷出
- APP 運行時無效,需要能有效進(jìn)入Bootloader模式。
- APP 無效, Bootloader 不應(yīng)該跳入
- 等等
Bootloader的設(shè)計與實現(xiàn)
總結(jié)一句話
最基本的Bootloader通過傳輸協(xié)議把數(shù)據(jù)可靠的寫入指定的內(nèi)存空間
通過上面的分析,總結(jié)一下我們需要實現(xiàn)哪些功能。
01 控制器最小系統(tǒng)
單純運行Bootloader的軟件,這里是不需要os的。只需要一個while(1) + 中斷系統(tǒng)順序執(zhí)行即可。
本文以Aurix Tricore芯片示例代碼介紹。
啟動代碼
static void __StartUpSoftware(void);
static void __StartUpSoftware_Phase2(void);
static void __StartUpSoftware_Phase3ApplicationResetPath(void);
static void __StartUpSoftware_Phase3PowerOnResetPath(void);
static void __StartUpSoftware_Phase4(void);
static void __StartUpSoftware_Phase5(void);
static void __StartUpSoftware_Phase6(void);
static void __Core0_start(void);
main 函數(shù)
這里面實現(xiàn)很簡單,只需要判斷是否進(jìn)入app. 如果不進(jìn)入app. 就只需要監(jiān)聽通訊接口的數(shù)據(jù),進(jìn)行相對應(yīng)的操作即可。
int main(void)
{
if(*((uint32_t *)APP_EXE_FLAG_START_ADDR)==0x80001000){
CAN_BOOT_JumpToApplication(APP_START_ADDR);
}
__set_PRIMASK(0);//開啟總中斷
CAN_Configuration(1000000);
while (1)
{
if(CAN1_CanRxMsgFlag){
CAN_BOOT_ExecutiveCommand(&CAN1_RxMessage);
CAN1_CanRxMsgFlag = 0;
}
}
}
02 通訊驅(qū)動
這里面采用的是比較簡單的CAN 通訊。
一般來說因為上位機在傳輸數(shù)據(jù)的時候,速度是很快的。我們bootloader里面的CAN 接收需要采用中斷的模式進(jìn)行收發(fā)。
對于CAN 的參數(shù)配置。
波特率
typedef struct {
unsigned char SJW;
unsigned char BS1;
unsigned char BS2;
unsigned short PreScale;
} tCAN_BaudRate;
可以根據(jù)芯片手冊的原理進(jìn)行配置。
這里面對于Bootloader來說,比較重要的就是波特率和收發(fā)報文ID 以及中斷模式。
因為這些是需要和上位機進(jìn)行配合的。
這里給出以下Mcal 代碼初始化CAN時候的形參。可以大概看出需要初始化的內(nèi)容
/*******************************************************************************
** Traceability : [cover parentID={196A1432-EAB1-461a-BD6C-259784BF6397}] **
** **
** Syntax : void Can_17_McmCan_Init **
** ( **
** const Can_17_McmCan_ConfigType* const Config **
** ) **
** **
** Description : Driver Module Initialization function **
** * This function initializes: **
** * Static variables, including flags **
** * CAN HW Unit global hardware settings **
** * Controller specific settings for each CAN Controller **
** All CAN Controllers will be in state CANIF_CS_STOPPED after initialization**
** [/cover] **
** **
** Service ID : 0x00 **
** **
** Sync/Async : Synchronous **
** **
** Reentrancy : Non-Reentrant **
** **
** Parameters(in) : Config - Pointer to all cores CAN driver configuration **
** **
** Parameters (out) : none **
** **
** Return value : none **
** **
*******************************************************************************/
對于bootloader來說,這里只需要三個接口
初始 化,收,發(fā)
void CAN_Configuration_init(uint32_t BaudRate);
uint8_t CAN_WriteData(CanTxMsg *TxMessage);
uint16_t Read_CAN_Address(void);
03 內(nèi)存驅(qū)動
首先看一下內(nèi)存分配
PFLASH
DFLASH
一般來說 被刷的軟件格式是Hex 或S19. 針對這兩種格式就不說了。
code 和 data 可以根據(jù)主機廠需求分為兩個或多個Hex.
所以這里需要對Pflash 和 DFlash 都進(jìn)行操作。
需要注意的是兩個不同的flash 操作的 扇區(qū)大小是不一樣的。Mcal提供的接口已經(jīng)做了相對應(yīng)的處理。
對于bootloader來說,需要的接口 擦除 和 寫入。
/*******************************************************************************
** Syntax : FlsLoader_ReturnType FlsLoader_Write( **
** const FlsLoader_AddressType TargetAddress, **
** const FlsLoader_LengthType Length, **
** const uint8* const SourceAddressPtr) **
** **
** Service ID : 0x31 **
** **
** Sync/Async : Synchronous **
** **
** Reentrancy : Non Reentrant **
** **
** Parameters(in) : Length: Number of bytes to be written. It should be **
** multiple of the following page sizes of the **
** selected Flash for write. **
** PFlash: 32 Bytes **
** DFlash: 8 Bytes **
** SourceAddressPtr: Pointer to source data buffer **
** TargetAddress: Target address in Flash memory. **
** It should be aligned to the following page sizes **
** of the selected Flash for write. **
** PFlash: 32 Bytes **
** DFlash: 8 Bytes **
** **
** Parameters (out) : None **
** **
** Return value : FLSLOADER_E_OK: Successful execution. **
** FLSLOADER_E_BUSY: Flash is busy with erase/write **
** operation. **
** FLSLOADER_E_NOT_OK: Returned when DET, Sequence error, **
** Program/Erase verify errors occur, SourceAddressPtr is**
** null pointer. **
** FLSLOADER_E_LOCKED: Programming a locked sector. **
** **
** Description : This function is used to program a page of internal **
** Flash. Sectors of PFlash and DFlash can be programmed. **
*******************************************************************************/
/*******************************************************************************
** Syntax : FlsLoader_ReturnType FlsLoader_Erase( **
** const FlsLoader_AddressType TargetAddress, **
** const FlsLoader_LengthType Length **
** ) **
** **
** Service ID : 0x32 **
** **
** Sync/Async : Synchronous **
** **
** Reentrancy : Non Reentrant **
** **
** Parameters(in) : Length: Number of Flash (PFlash or DFlash) sectors to **
** be erased. Note: Number of sectors should lie within **
** single Flash bank. Erase operation across the Flash **
** banks is not supported. **
** TargetAddress: Target address in Flash memory. It **
** should be aligned to the following sector sizes of the **
** selected Flash for erase. **
** PFlash: 16 Kbyte **
** DFlash: 4 Kbyte **
** **
** Parameters (out) : None **
** **
** Return value : FLSLOADER_E_OK: Successful completion. **
** FLSLOADER_E_BUSY: Flash is busy with erase/write **
** operation. **
** FLSLOADER_E_NOT_OK: Returned when DET, Sequence error, **
** Erase verify errors occur. **
** FLSLOADER_E_LOCKED: Sector is protected. **
** **
** Description : This function erases the logical sectors of the **
internal Flash. The completion of this operation is **
denoted by clearing of busy status flag or error. **
04 額外需求庫
這里比如需要對數(shù)據(jù)進(jìn)行CRC 校驗
需要對數(shù)據(jù)包進(jìn)行數(shù)據(jù)解密用到的加密算法
等等
05 交互邏輯 上層應(yīng)用
根據(jù)具體的OEM 需求實現(xiàn)的功能。比如說。配置參數(shù)的交換,與APP軟件的有效位相互校驗,等等需求。這里無法給出對應(yīng)代碼。
總結(jié) 一張圖
評論
查看更多