一、项目需求
通过Can通信功能实现BootLoader的更新;
二、项目背景
芯片 :英飞凌 TC212 ; 刷写实现:基于ISO14229的UDS On Can 刷写
BootLoader起始地址:0x80000000;
App起始地址:0x80020000;
三、更新方案逻辑
- 在原版boot的基础上修改一版可用于更新原boot地址的ReBoot;
- ReBoot的Hex地址更改为原App的地址;
- 通过将ReBoot刷入App地址,实现对原boot的擦除和刷写;
四、具体实现细节
1、Boot软件编译生成的Hex的起始地址的更改
在英飞凌的link .lsl文件中找到对boot预留区域的命令语句,一般为:
section_layout mpe:vtc:liner
{
group Bootloader_Resverd(run_add = 0x80000000,ordered,contiguous) // group name_ (运行地址)
{
resverd"Bootloader_Resverd"(size = 128k,attributes = r); // (大小,只读)
}
}
在boot代码的lsl文件中添加此命令语句后,编译的Hex会预留出起始地址为0x80000000,大小为128k的区域,ReBoot的起始地址为0x80000000 + 0x20000 = 0x80020000 ; (注:0x20000为128 x 1024的16进制)
此时直接编译会报 overlap的error ,这是因为你在boot里定义的一些内容,比如变量的地址在“ Bootloader_Resverd ”的预留区域,此时要对这些变量 ,无用的进行屏蔽,有用的就在原先地址上偏移0x20000; 这些变量常见的有,写在固定地址的版本号,一些flag等;(注:我们最终的目的是把原boot更新掉,ReBoot的功能只需要实现此功能,其他无所谓)
lsl还有一个需要更改的就是代码的reset的地址,保证复位后,代码从此地址开始运行;
2、擦写原Boot地址 功能实现
经过step1之后,你的ReBoot就可以刷写到App的地址上了,接下来就要实现对原boot地址范围的擦写功能。
这一块呢,要看你boot代码里对“ 擦 ”sector 具体逻辑,一般来说,擦的使能使用的是uds中的0x31服务,格式为31 + 01 + did + 擦除地址 + 长度,上位机在发送此命令后,boot代码会将此报文解析并找到对应的sector进行擦除操作;需要更改的是在这之前有没有做其他逻辑操作,比如地址范围判断,屏蔽此类判断以防不能对原boot地址范围的sector进行擦除;
0x34,0x36服务的实现也都和上位机去识别要刷入的Hex,发出的报文有关;
3、扫尾
原boot正常的功能会在刷写完app后,对刷入的内容进行依赖性检查,这块如果嫌麻烦,可以屏蔽掉;接下来要说的是boot在刷完app后,会检测app有效标志位,来判断是否跳转到app去运行,所以要将所有判断app有效和复位到app去运行的地方屏蔽掉,防止在更新掉原boot之后,还去执行此操作;
补充:注意一下app有效标志位擦除和置起的时机,一般在调用擦除flash之前擦除app有效标志,在进行依赖性检查时置起此标志;