Bootloader 介绍
大多数Bootloader 包含两种操作模式。
-
启动加载模式
-
下载模式
对于大多数汽车软件开发者来说,从客户需求的角度,他们更多关心Bootloader的下载模式。下面我们将从CAN Bootloader的一般需求入手,来介绍一下CAN Bootloader 的整个实现过程。
CAN Bootloader 简述
通过CAN网络升级一般需要考虑下面几个方向。
针对单一节点
CAN网络是串行结构,在对节点升级的时候,不能被别的节点影响,也不能影响到别的节点。这里就需要进行点对点升级。在OEM 的规范中会对每一个ECU 都有自己的诊断ID。一般情况下针对CAN网络的ECU有。
两个接收ID
-
功能寻址ID
-
物理寻址ID
一个发送ID
-
诊断发送ID
这样可以确保点对点的操作,和其他节点互相不干扰。
节点的智能设计
在CAN网络中实现数据更新,最进本的就是master ECU 把数据有效的传输给Slave ECU, 这样Slave ECU 对自身的flash 进行操作。在这个过程中需要对数据进行一定要求。
-
保证数据传递的有效性-->传输过程没有错误
-
保证数据本身的真实性--> 未被篡改
-
保证数据发送方的可靠性-->被授权的ECU
-
保证数据本身的正确性--> 是否与Bootloader 兼容
-
等等需求
-
这里对传输过程的保证,汽车OEM 一般通过UDS 让Master ECU 和 Slave 进行交互。通过握手协议,以及一些routine 来对上面需求进行一一实现。
针对UDS 这里不一一介绍,可以翻阅14229 自行查询。
注意这里缺少新版的 0x29 服务。
UDS诊断29认证服务-Authentication Service
进入Bootloader 模式
一般来说这里有一下几种方式
-
APP 主动跳转至 Bootloader 模式
-
上电启动由于Bootloader 检测APP 失效,主动停留在Bootloader
-
APP 软件异常,自动复位到Bootloader 模式下。
这里针对OEM 的升级需求,一般是 第一种, APP 主动跳转至Bootloader 模式。因为Bootloader 不一定都是需要依赖UDS的,这里统一叫Bootloader 模式,OEM 的 UDS 的规范里面的名称叫做programming session。
一般来说OEM 会在APP 里面先进行session 跳转,身份验证。
最后通过 10 02 命令让APP 跳转到Bootloader 模式下。
在我们进行bootloader设计的时候,可以通过任何特定方式,注意这里的特定方式不能是随随便便就可以触发 的,防止误触进入bootloader 模式。
因为跳转的逻辑是 APP 检测到一定的条件,然后 对某些寄存器,或者某些Bootloader 可读的内存空间进行写flag. 随后进行reset. 这样在reset完成之后, bootloader 会检测到,这次不需要跳转至APP 了。
对bootloader的要求
从实际的研发需求出发,这里列出了一些常用的需求。实际OEM 的bootloader 可能会细化需求,但是最终都是为了下面的目的提出来的需求。
-
多次数据更新
-
刷写速度,传输速度
-
差分更新
-
身份验证
-
数据格式的标准化
-
对数据的完整性,有效性等进行校验
-
对APP 的有效性进行校验
-
上位机方便友好
OEM 对Bootloader 的基本要求
在OEM 的需求里,在刷写过程一般分为三个步骤。
-
前处理
-
刷写
-
后处理
分别是做什么的呢?
前处理
需求各不相同,但是目的基本都一致。
-
避免其他节点对升级过程的影响
-
避免自身节点对升级过程的影响
-
避免自身节点对其他节点的影响
刷写
通过一系列的UDS 命令进行 点对点 交互。其目的和前面提到的一致。
-
发送数据的ECU 可靠
-
数据传输过程可靠
-
数据有效性(识别有没有被篡改)
-
数据加密解密数据安全
-
等等
后处理
解除自身的特殊状态。更新配置参数等等。
这里面 ECU 需要做好和APP 的相互校验。需要达到
-
APP 是否有效,Bootloader 需要能判断出
-
APP 运行时无效,需要能有效进入Bootloader模式。
-
APP 无效, Bootloader 不应该跳入
-
等等
Bootloader的设计与实现
总结一句话
最基本的Bootloader通过传输协议把数据可靠的写入指定的内存空间
通过上面的分析,总结一下我们需要实现哪些功能。
控制器最小系统
单纯运行Bootloader的软件,这里是不需要os的。只需要一个while(1) + 中断系统顺序执行即可。
本文以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 函数
这里面实现很简单,只需要判断是否进入app. 如果不进入app. 就只需要监听通讯接口的数据,进行相对应的操作即可。
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;
}
}
}
通讯驱动
这里面采用的是比较简单的CAN 通讯。
一般来说因为上位机在传输数据的时候,速度是很快的。我们bootloader里面的CAN 接收需要采用中断的模式进行收发。
对于CAN 的参数配置。
波特率
typedef struct {
unsigned char SJW;
unsigned char BS1;
unsigned char BS2;
unsigned short PreScale;
} tCAN_BaudRate;
可以根据芯片手册的原理进行配置。
这里面对于Bootloader来说,比较重要的就是波特率和收发报文ID 以及中断模式。
因为这些是需要和上位机进行配合的。
这里给出以下Mcal 代码初始化CAN时候的形参。可以大概看出需要初始化的内容
/*******************************************************************************
** 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来说,这里只需要三个接口
初始化,收,发
void CAN_Configuration_init(uint32_t BaudRate);
uint8_t CAN_WriteData(CanTxMsg *TxMessage);
uint16_t Read_CAN_Address(void);
内存驱动
首先看一下内存分配
PFLASH
DFLASH
一般来说 被刷的软件格式是Hex 或S19. 针对这两种格式就不说了。
code 和 data 可以根据主机厂需求分为两个或多个Hex.
所以这里需要对Pflash 和 DFlash 都进行操作。
需要注意的是两个不同的flash 操作的 扇区大小是不一样的。Mcal提供的接口已经做了相对应的处理。
对于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. **
额外需求库
这里比如需要对数据进行CRC 校验
需要对数据包进行数据解密用到的加密算法
等等
交互逻辑 上层应用
根据具体的OEM 需求实现的功能。比如说。配置参数的交换,与APP软件的有
效位相互校验,等等需求。这里无法给出对应代码。
总结 一张图
码上报名
AutoSec 2023 第七届中国汽车网络安全周暨第四届智能汽车数据安全展,9月13-15日,上海
更多文章
华为蔡建永:智能网联汽车的数字安全和功能安全挑战与思考
汽车数据合规要点
车载以太网技术发展与测试方法
车载以太网防火墙设计
SOA:整车架构下一代的升级方向
会员权益: (点击可进入)谈思实验室VIP会员
END
微信入群
谈思实验室专注智能汽车信息安全、预期功能安全、自动驾驶、以太网等汽车创新技术,为汽车行业提供最优质的学习交流服务,并依托强大的产业及专家资源,致力于打造汽车产业一流高效的商务平台。
每年谈思实验室举办数十场线上线下品牌活动,拥有数十个智能汽车创新技术的精品专题社群,覆盖BMW、Daimler、PSA、Audi、Volvo、Nissan、广汽、一汽、上汽、蔚来等近百家国内国际领先的汽车厂商专家,已经服务上万名智能汽车行业上下游产业链从业者。专属社群有:信息安全、功能安全、自动驾驶、TARA、渗透测试、SOTIF、WP.29、以太网、物联网安全等,现专题社群仍然开放,入满即止。
扫描二维码添加微信,根据提示,可以进入有意向的专题交流群,享受最新资讯及与业内专家互动机会。
谈思实验室,为汽车科技赋能,推动产业创新发展!
原文始发于微信公众号(谈思实验室):一文了解 -- bootloader
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论