2. RH850硬件平台与启动流程
Bootloader能否被正确唤醒,取决于三件事:芯片复位后从哪里取第一条指令、这段代码被映射到哪块物理存储、以及应用是否满足跳转条件。RH850的启动过程不是“上电就跑main”,而是由复位向量、启动模式引脚、选项字节和内存映射共同决定的一条确定性路径。理解这条路径,是后续刷写逻辑设计的基础。
内核架构与地址空间
RH850基于32位RISC架构,采用统一编址的线性地址空间。以RH850/F1x系列为例,CPU可寻址4GB空间,但实际可用的物理存储被划分成若干区域:Code Flash通常位于0x0000_0000起始的本地Flash区,Data Flash位于独立区域,RAM位于0xFEDE_0000附近,外设寄存器集中在0xFFF8_0000以上的Peripheral区。这种“代码、数据、外设各占一段”的布局,决定了Bootloader必须清楚自己运行在哪个区域、跳转目标落在哪个区域。
需要特别注意的是RH850的向量表机制。复位向量、异常向量和中断向量并不都放在同一张表里,复位向量位于固定的硬件入口地址,而中断向量则通过EBASE寄存器指定的基址加偏移来定位。Bootloader如果重定位了中断向量,就必须在跳转应用前把EBASE恢复为应用期望的值,否则应用的中断会跳到Bootloader的向量表里,表现为“程序能跑但一进中断就死”。
启动模式与复位向量
RH850上电或复位后,CPU首先采样启动模式引脚(如MODE0、MODE1等),决定从哪个启动源取复位向量。常见模式包括:从Code Flash启动(正常量产模式)、从串行接口启动(如CSI/UART引导模式,用于工厂烧录)、以及从外部总线启动。Bootloader开发中最关心的是Flash启动模式,因为整车刷写场景下ECU最终必须能自主从Flash启动。
复位向量的内容是一个跳转目标地址。CPU取出该地址后跳转执行,这段被跳转到的代码就是启动代码。对于带Bootloader的系统,复位向量通常指向Bootloader的入口,而不是应用的入口。也就是说,Bootloader是“第一个被执行的用户代码”,它负责判断是否进入刷写流程,还是把控制权交给应用。
Bootloader入口条件
Bootloader入口条件可以归纳为三类判断,它们共同决定“这次复位后是刷写还是跳应用”。
- 刷写请求标志:通常存放在Data Flash或备份RAM中,由诊断仪通过UDS
0x10 0x02(编程会话)或特定例程设置。Bootloader启动后先读该标志,若有效则停留在Bootloader等待刷写。 - 应用有效性标志:应用区头部通常有一个校验字段(如CRC32或魔术字)。Bootloader计算应用区CRC并与存储值比对,若不一致说明应用损坏或不完整,应停留在Bootloader。
- 超时窗口:即使没有刷写请求,Bootloader也可开放一个短暂时窗(例如500ms~2s),在此期间监听诊断请求。若收到有效的编程会话请求则进入刷写,否则超时后跳转应用。
这三类条件不是并列关系,而是有优先级的判断链。下面这张图展示了RH850从复位到最终去向的完整判断路径,包含启动模式采样、向量取址、条件判断和两条出口。
跳转应用前的关键处理
从图中可以看到,跳转应用不是简单的一条jmp。Bootloader在移交控制权前必须完成一系列“清理”动作,否则应用即使代码正确也可能运行异常。典型处理包括:关闭Bootloader自己开启的看门狗;把EBASE恢复为应用向量表基址;将外设(如CAN、定时器)恢复到复位默认状态,避免应用初始化时状态冲突;从应用向量表的第一个字取出初始栈指针并写入SP,第二个字取出复位处理函数地址并跳转。
下面是一段示意性的跳转代码结构,用于说明“取栈指针—取入口—跳转”的顺序。实际地址需根据链接脚本确定,此处仅为示例。
/* 应用向量表位于 APP_BASE,前两个字分别为初始SP和复位入口 */
#define APP_BASE 0x00010000UL
#define APP_SP (*(volatile uint32_t*)(APP_BASE))
#define APP_ENTRY (*(volatile uint32_t*)(APP_BASE + 4U))
void jump_to_app(void)
{
uint32_t sp = APP_SP;
uint32_t entry = APP_ENTRY;
/* 关闭看门狗、恢复EBASE等清理动作 */
WDT_DISABLE();
EBASE = APP_BASE;
__asm volatile ("mov %0, sp" : : "r"(sp));
((void (*)(void))entry)();
}
内存映射对Bootloader布局的约束
Bootloader和应用共享同一片Code Flash,因此链接脚本必须明确划分边界。常见做法是把Bootloader放在Flash起始段(如0x0000_0000~0x0000_FFFF,64KB),应用从0x0001_0000开始。复位向量指向Bootloader入口,应用向量表则位于应用区起始处。刷写时,Bootloader只擦写应用区,绝不触碰自身所在扇区,否则一旦刷写中断,整个ECU将无法再次启动。
此外,Data Flash中应保留一块“刷写控制区”,用于存放刷写请求标志、应用CRC、刷写次数等元数据。这块区域在应用运行时也可被诊断服务读写,是Bootloader与应用之间的共享状态区。设计时要明确各字段的偏移和默认值,避免双方对同一地址的解释不一致。