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从复位到最终去向的完整判断路径,包含启动模式采样、向量取址、条件判断和两条出口。

RH850 复位启动与 Bootloader 入口判断路径 上电 / 复位 采样启动模式引脚 MODE0/MODE1 Flash启动 / 串行引导 / 外部总线 从复位向量取跳转地址 跳转至 Bootloader 入口 判断1:刷写请求标志有效? Data Flash / 备份RAM 中的请求位 是 停留在 Bootloader 等待诊断刷写 否 判断2:应用区 CRC 校验通过? 应用头部魔术字 + CRC32 比对 否 应用无效 停留等待刷写 是 判断3:超时窗口内收到编程会话? UDS 0x10 0x02 / 例程请求 是 进入刷写流程 擦写 / 传输 / 校验 否 恢复 EBASE / 栈指针 跳转至应用入口 关键硬件要素 • 启动模式引脚 • 复位向量入口 • EBASE 向量基址 • Data Flash 标志区 跳转前必做 • 关闭看门狗 • 恢复中断向量 • 复位外设状态 • 设置应用栈指针

跳转应用前的关键处理

从图中可以看到,跳转应用不是简单的一条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)();
}
跳转前务必确认应用区CRC有效且栈指针对齐。若应用区被擦除一半或CRC错误,直接跳转会导致取指异常或HardFault,表现为反复复位。此时应停留在Bootloader等待重新刷写,而不是盲目跳转。

内存映射对Bootloader布局的约束

Bootloader和应用共享同一片Code Flash,因此链接脚本必须明确划分边界。常见做法是把Bootloader放在Flash起始段(如0x0000_0000~0x0000_FFFF,64KB),应用从0x0001_0000开始。复位向量指向Bootloader入口,应用向量表则位于应用区起始处。刷写时,Bootloader只擦写应用区,绝不触碰自身所在扇区,否则一旦刷写中断,整个ECU将无法再次启动。

此外,Data Flash中应保留一块“刷写控制区”,用于存放刷写请求标志、应用CRC、刷写次数等元数据。这块区域在应用运行时也可被诊断服务读写,是Bootloader与应用之间的共享状态区。设计时要明确各字段的偏移和默认值,避免双方对同一地址的解释不一致。

调试启动问题时,可先用调试器在复位向量处下断点,单步确认:启动模式采样结果是否正确、复位向量指向的地址是否落在Bootloader范围内、EBASE初值是否符合预期。这三步能快速定位大多数“上电不启动”问题。