下图展示了PC通过适配器与ECU连接。高亮公布部分是ECU和PC共同的。所有平台都是一样的。
bootloader reset/power处理过程解释。在power/reset过程中,通过bootloader检查下述的执行。
下表展示bootloader需要依赖的flag值。
Update APP flag | APP 有效性标识 | 描述 |
---|---|---|
TRUE | N/A | 进入bootloader模式,更新APP固件 |
FALSE | TRUE | 跳转到APP |
FALSE | FALSE | 进入bootloader模式等待更新APP固件 |
从上述信息,bootloader和APP需要交换信息,该信息存储到保留RAM。警告复位可以保存信息,但在冷复位(开/关电源)期间,信息可能丢失。下图展示bootloader reset/power 过程。
MCU有两个内部存储(Flash和RAM)。下述例子划分FLASH和RAM空间给bootloader和APP。
下面是在S32K144划分闪存和RAM空间的示例
S32K144 p-flash(program flash)和RAM空间
bootloader有6个模块,即服务层、传输层、FIFO、硬件通讯驱动(CAN/LIN etc),flash驱动和flash操作。统一bootloader通过下述步骤通讯。
下图展示统一bootloader的系统图。统一bootloader需要一些硬件驱动,如CAN/LIN,watchdog,定时器,flash和debug(I/O,Uart)来移植到新的平台。需要准备所有的硬件驱动。
序号 | 文件名 | 描述 | 移植是否要验真 |
---|---|---|---|
1 | auto_lib | 发布函数如memcpy,memset,rand等等 | NO |
2 | boot | 给其他模块提供启动服务,如boot信息,跳转APP | Yes |
3 | Debug | UART打印,debug I/O,定时器 | Yes/No |
4 | Demo | 使用bootloader堆栈的demo。用户只用添加时钟和CAN/LIN模块到文件中 | YES/No |
5 | FIFO | FIFO模块 | No |
6 | Flash_APP | 提供操作UDS的FLASH服务 | No |
7 | HAL | CRC,FLASH、定时器、UDS算法、看门口 HAL硬件抽象库。使用HAL库API提花底层API | Yes |
8 | public_inc | 公共头文件,如用户配置文件和重定义数据类型。默认是32位MCU。 | Yes |
9 | UDS_stack | TP和UDS堆栈 | Yes |
下面子节中的阴影文本表示在移植引导加载程序堆栈时需要注意或修改它.
包含common_types.h, toolchain.h, autolibc.h and user_config.h
为解决不同平台数据类型冲突(e.g. uint32/16/8).includes.h头文件应该包含其他的头文件。
用户关闭或者打开一些宏。下表描述可以配置的宏
序号 | 宏名 | 描述 |
---|---|---|
1 | CORE_NO | 保留 |
2 | EN_DEBUG_IO | 测试时间或者翻转LED |
3 | EN_DEBUG_TIMER | 保留 |
4 | EN_ASSERT | 是否使能断言 |
5 | EN_UDS_DEBUG、EN_TP_DEBUG、EN_APP_DEBUG、EN_DEBUG_FIFO | 通过串口打印信息 |
6 | DebugBootloader_NOTCRC | 是否使用CRC检测flash驱动和app镜像 |
7 | EN_ALG_SW、EN_ALG_HW、AES_SEED_LEN | 软硬件是否使能UDS算法,默认是使能软件 |
8 | EN_CAN_TP、EN_LIN_TP、EN_ETHERNET_TP、EN_OTHERS_TP | 使能TP类型。 |
9 | RX_FUN_ID、RX_PHY_ID、TX_ID | CAN RX功能ID、CAN RX物理ID、CAN TX消息ID。如果使能TP应该配置这些ID |
10 | RX_BOARD_ID、RX_FUN_ID、RX_PHY_ID、TX_ID | LIN通上 |
11 | EN_CRC_HARDWARE、EN_CRC_SOFTWARE | 软和硬件使能计算CRC。软件CRC必须使能 |
12 | RX_BUS_FIFO、RX_BUS_FIFO_LEN | RX BUS FIFO ID 和 长度 |
13 | TX_BUS_FIFO、TX_BUS_FIFO_LEN | TX 消息 BUS FIFO ID和长度 |
14 | EN_SUPPORT_APP_B、EN_NEWEST_APP_INVALID_JUMP_OLD_APP | 保留给OTA/FOTA |
15 | DisableAllInterrupts()、EnableAllInterrupts() | 使能/关闭所有中断。bootloader堆栈使用API关闭/使能所有中断。 |
16 | MCU_S12Z、MCU_S32K14x、MCU_TYPE | 设置当前MCU类型。使用擦除P-flash区域尺寸和计算擦除P-flash时间 |
17 | EN_DELAY _TIME、DELAY_MAX_TIME_MS | 使能进入bootloader模式最大时间。如果APP要求进入bootloader模式和不发送任何诊断命令,bootloader等待最大延时时间。如果APP有效,将会跳转到APP。 |
18 | EN_TX_CAN_FD | 使不使能TX CAN FD特性。如果使能该宏,发送CAN消息将会基于CAN FD。 |
这个文件都是一些基本数据类型定义。e.g. uint32/16/8.如果基本数据类型与typedef冲突,应该给编译器添加一些条件防止冲突。
重定义一些关键词。e.g. inline,asm,interrupt etc。Bootloader 堆栈不使用这些文件的关键词。
API名字 | 描述 |
---|---|
gs_aCRC16Tab | CRC表格 |
boolean CRC_HAL_Init(void) | 初始化CRC模块。成功返回ture,失败返回false |
void CRC_HAL_CreatHarewareCrc(const uint8 *i_pucDataBuf,const uint32 i_ulDataLen,uint32 *m_CurCrc) | 硬件计算CRC值。i_pucDataBuf:计算CRC数据。i_ulDataLen:消息长度。m_CurCrc:计算出CRC值 |
void CRC_HAL_CreatsoftwareCrc(const uint8 *i_pucDataBuf,const uint32 i_ulDataLen,uint32 *m_CurCrc) | 软件计算CRC值。i_pucDataBuf:计算CRC数据。i_ulDataLen:消息长度。m_CurCrc:计算出CRC值 |
CRC_HAL_Deinit | 保留 |
flash_hal.c应该要移植。
API名字 | 描述 |
---|---|
#define SECTOR_LEN(XXX) #define MAX_ERASE_SECTOR_FLASH_MS(XX) | SECTOR_LEN索引是sector大小(BYTES)。擦错sector最大时间 |
#define APP_VECTOR_TABLE_OFFSET | gs_asrBlockNumA/B头文件的APP向量表偏移。该值配置目标 |
#define RESET_HANDLE_OFFSET | 来自vector表复位 handle/startup偏移 |
#define HANDLER_ADDR_LEN | 复位handle点长度。 |
boolen FLASH_HAL_Init(void) | 初始化flash.可以计算和存储在flash驱动表所有的flash驱动APIs地址。返回初始化flash状态。 |
boolen FLASH_HAL_EraseSector(const uint32 i_startAddr,const uint32 i_noEraseSectors) | 擦除flash扇区。擦除flash N*扇区。i_startAddr:擦出flash开始地址。i_noEraseSectors:擦出扇区的数量。返回擦出flash状态 |
boolen FLASH_HAL_WriteData(const uin32 i_startAddr,cosnt uint8 i_pDataBuf,const uint32 i_dataLen) | flash的program data有一些条件。如程序总是8N bytes data。如果程序数据不等于8N,应该数据长度加到8 *N。i_startAddr:程序数据开始地址。i_pDataBuf:程序数据buf。i_DataLen:程序数据长度 |
boolean FLASH_HAL_ReadData(const uin32 i_startAddr,const uint32 i_readLen,uint8 *o_pDataBuf) | 保留 |
void FLASH_HAL_Deinit(void) | 保留 |
boolean FLASH_HAL_RegisterFlashAPI(tFlashOperateAPI *o_pstFflashOperateAPI) | 寄存器flashAPI.API寄存器操作flash函数。目的为了应hi不需要校验 |
Flash驱动编译独立位置代码。意味着flash驱动能够复制到任何一个RAM地址和完成正常运行。Flash驱动需要表,该表包含了一些API。init/erase/program/read/verity 闪存空间。flash_hal.c 调用APIs可以计算在RAM 的init/erase/program/read/verity闪存地址。
如果将闪存驱动器复制到0x1000 (RAM),则闪存驱动器API表将重新计算API起始地址。api的起始地址可以在Flash_init中重新计算。
API名字 | 描述 |
---|---|
void TIMER_HAL_Init(void) | 初始化定时器。定时器设置tick定时1ms |
void TIMER_HAL_1msPeriod | 1ms调用一次。可以通过ISR或者主函数。 |
UDS诊断是基于AES。如果用户不使用诊断,可以加自己的诊断到该文件。
API名字 | 描述 |
---|---|
gs_aKey | AES key |
gs_UDS_SWTimerTickCnt | 存储软件定时器Tick计数。给AES使用。 |
在bootloader,watchdog模块常常用作检测系统是否工作或者触发bootloader复位。
API名字 | 描述 |
---|---|
void WATCHDOG_HAL_Init(void) | 初始化看门口模块 |
void WATCHDOG_HAL_Fed(void) | 喂狗 |
void WATCHDOG_HAL_SystemReset(void) | Trigger system reset |
void WATCHDOG_HAL_Deinit(void) | 保留 |
UDS堆栈包含UP和UDS层。为了移植bootloader堆栈,你需要验真xx_cfg.c.
API名字 | 描述 |
---|---|
uint32 TP_GetConfigTxMsgID(void) | 获得配置TX消息ID |
uint32 TP_GetConfigRxMsgFUNID(void) | 获取配置RX功能消息ID |
uint32 TP_GetConfigRxMsgPHYID(void) | 获取配置RX物理消息ID |
uint32 TP_GetConfigRxMsgBoardcastID(void) | 获取配置RX抓板NAD |
uint32 TP_GetConfigRxMsgBoardcastID(void) | 获取配置RX抓板NAD |
void TP_RegisterTransmittedAFrmaeMsgCallBack(const tpfUDSTxMsgCallBack i_pfTxMsgCallBack) | 寄存器发送一帧等待回调 |
void TP_DoTransmittedAFrameMsgCallBack(const uint8 i_result) | 发送一帧调用 |
boolean DriverWriteDataInTP(const uint32 i_RxID,const uint32 i_RxDataLen,const uint8 *i_pRxDataBuf) | 当驱动接收到来自总线的消息,驱动调用这个API将消息发送给TP层。 i_RxID:RX消息ID。如CAN ID:0x7DE。i_RxDataLen:RX 消息长度。i_pRxDataBuf:RX 消息buf |
boolen TP_DriverReadDataFromTP(const uint32 i_readDataLen,uint8 *o_pReadDatabuf,uint32 *o_pTxMsgID,uint32 *o_pTxMsgLength) | 调用API获取TP发送驱动消息。i_readDataLen:TX消息长度,o_pReadDatabuf:消息buf o_pTxMsgID:TX消息ID,CANID。o_pTXMsgLength:TX消息长度 |
void TP_RegisterAbortTxMsg(const void (*i_pfAbortTxMsg)(void)) | 当TP发送消息超时,TP调用这个API中止发送。i_pfAbortTxMsg:中止TX消息指针 |
void TP_DoTxMsgSuccesfulCallback(void) | 当驱动发送消息,必须调用该API。作为,xx_TP_cfg.c发送API有一个参数显示TX消息成功,如果你有使用这个指针,这个API不再被调用。 |
TP层提供3个API给驱动。
当驱动接收一个消息,将发送消息给TP层调用TP_DrivierWriteDataInTP。
当消息发送时,需要调用TP_DoTxMsgSuccesfulCallback来通知TP层。
驱动需要检查TP层,如果消息需要在一次发送TP_DriverReadDataFromTP。
下图将显示TP_DriverWriteDataInTP,TP_DriverReadDataFromTP和TP_DoTxMsgSuccesfulCallback的例子。
如果你使能CAN_TP,这个文件配置信息和验证CAN TP层一些APIs.
CAN TP有一些信息需要配置如STmin,N_As,N_Bs等待。大多数时候,你不需要验真这些参数。下图展示参数。
下表格描述这些API
API名字 | 描述 |
---|---|
uint8 CANTP_TxMsg(const tUdsId i_xTXId,const uint16 i_DataLen,const uint8 *i_pDataBuf.const tpfNetTxCallBack i_pfNetTxCallBack,const uint32 txBlockingMaxtime) | CAN TP TX消息。发送消息给硬件API。i_xTxId: TX message ID、i_DataLen: TX message length、i_pDataBuf: message buff、i_pfNetTxCallBack: TX message successful callback、txBlockingMaxtime: reserved |
uint8 CANTP_RxMsg(tUdsld *o_pxRxId,uint8 *o_pRxDataLen,uint8 *o_pRxBuf | CANTP RX接收来自FIFO消息。CAN驱动从总线接收消息和检查ID有效性和些写FIFO消息。o_pxRxI:RX 消息ID,o_pRxDataLen:RX消息数据长度,o_pRxBuf:RX消息buf |
tUdsId CANTP_GetConfigTxMsgID(void) | 获得CAN TP配置TX消息ID |
tUdsId CANTP_GetConfigRxMsgFUNID(void) | Get CAN TP config RX function ID |
boolean CANTP_IsReceivedMsgIDValid(const uint32 i_receiveMsgID) | 检查接收到消息是否有效 |
tUdsId CANTP_GetConfigRxMsgPHYID(void) | Get CAN TP config RX message physical ID |
void CANTP_AbortTxMsg(void) | 等待发送消息超时,TP层中止硬件发送消息。 通过硬件中止发送的消息。 |
void CANTP_RegisterAbortTxMsg(const tpfAbortTxMsg i_pfAbortTxMsg) | Register abort TX message call back |
boolean CANTP_DriverWriteDataInCANTP(const uint32 i_RxID, const uint32 i_dataLen, const uint8 *i_pDataBuf) | 这个API提供给TP_cfg.c.常用作驱动接收和发送消息给TP层 |
boolean CANTP_DriverReadDataFromCANTP(const uint32 i_readDataLen, uint8 *o_pReadDataBuf, tTPTxMsgHeader *o_pstTxMsgHeader) | 这个API提供给TP_cfg.c.常用作驱动读取TP层的消息。 |
void CANTP_DoTxMsgSuccessfulCallBack(void) | This API is provided for TP_cfg.c. It is used by driver to send message successfully and call callback the API |
static boolean CANTP_ClearTXBUSFIFO(void) | This API is used for clear TX BUS FIFO |
boot模块包含了boot.c和boot_cfg.c。boot模块检查APP可用,跳转到APP和管理信息交换。移植时,有两个重点特征
场景1 APP接收更新固件命令。APP按照下述步骤:
常见2 成功成bootloader固件。bootloader按照下述步骤:
给boot提供服务,比如 APP和bootloader交换信息地址配置和值,检查进入bootloader模式。
API | 描述 |
---|---|
不同平台配置不同地址(info StartAddr,requestEnterBootloaderAddr和downloadAppSuccessfulAddr) | infoDataLen // information length 、requestEnterBootloader// request enter bootloader valid value、downloadAPPSuccessful//download APP successful、valid valueinfoStartAddr//information start address、requestEnterBootloaderAddr//request enterbootloader address、downloadAppSuccessfulAddr//download APPsuccessful address |
void SetDownloadAppSuccessful(void) | Set download APP successful |
boolean IsRequestEnterBootloader(void) | Does request enter bootloader mode? Return TRUE/FALSE |
void ClearRequestEnterBootloaderFlag(void) | Clear request enter bootloader mode |
boolean Boot_IsPowerOnTriggerReset(void) | The function is used to check power on trigger reset or not? Return TRUE/FALSE. |
void Boot_PowerONClearAllFlag(void) | When Powered on, clears all exchange information for ECC. |
void Boot_RemapApplication(void) | Reserved |
void Boot_JumpToApp(const uint32 i_AppAddr) | Jump to APP. This function is used to jump to APP.i_AppAddr: jump to APP address |
boolean Boot_IsInfoValid(void) | Check information validity? Return TRUE/FALSE |
uint16 Boot_CalculateInfoCRC(void) | Calculate information CRC. Return CRC value |
Demo文件夹包含了bootloader_main.c 和 bootloader_main.h 。这些文件提供如何调用其他模块的信息。
API | 描述 |
---|---|
void BOOTLOADER_MAIN_Init(void (*pfBSP_Init)(void),void (*pfAbortTxMsg)(void)) | 初始化所有bootloader模块。这个函数可用加入时钟,CAN/LIN初始化。pfBSP_Init:指针函数,包含了BSP初始化。BSP应该包含:clock/BUS(CAN/LIN)/flash init。Flash初始化不太重要,因为flash驱动初始化有多种方法。 pfAboreTxMsg:指针函数常用作中止TX消息和清除一些全局变量。如果没有使用,将这个设置为NULL_PTR; |
void BOOTLOADER_MAIN_Demo(void) | Bootloader主函数。用户调用主函数。e.g. void main(void) |
Debug文件夹包含了bootloader_debug.c,debug_IO.c和debug_timer.c
包含了debugIO,debug timer和debug打印。
API | 描述 |
---|---|
void BOOTLOADER_DEBUG_Init(viod) | 初始化debugIO,定时器和打印。通常移植时,不需要验证 |
void Bottloader_DebugPrintInit(void) | UART硬件初始化 |
void Bootloader_DebugPrint(const char *fmt,…) | 通过串口打印信息。通常移植需要调换硬件发送消息函数 |
API | 描述 |
---|---|
void DEBUG_IO_Init(viod) | 如果使能debug_IO,应该加debugIO初始化 |
void DEBUG_IO_Deinit(void) | 保留 |
void DEBUG_IO_SetDebugIOLow(void) | 设置低位debugIO |
void DEBUG_IO_SetDebugIOHigh(void) | 设置高位debugIO |
viod DEBUG_IO_ToggleDebugIO(void) | 翻转debugIO |
FIFO通常被用作不同层交换信息。FIFO不能被修改。只需要配置FIFO长度或者应用支持最大的FIFO数量。意味着FIFO支持最大存储数据。如果应用长度超过数据长度,长度采用将会失败。
FLS_APP模块使用CRC,UDS和看门口APIs.FLS_APP模块不能被修改。默认程序FLASH存储是128bytes.如果需要改变程序bytes或者配置指针,打印长度。可以在FLS_APP.h能修改。
不同平台和编译器的bootloader堆栈测试代码大小。下图展示代码大小的细节信息。
APP和bootloader有相似的特征,如CRC、定义交换信息和无效值。如果APP支持FOTA,需要额外验证APP信息。