4. 启动流程与初始化
RH850 上电后并不是直接进入 main(),而是经历一条严格受硬件约束的启动链:复位采样、向量取指、启动代码搬运、C 运行时建立、时钟切换、看门狗处理,最后才进入应用。任何一环配置错误,都会表现为“程序不跑”“跑飞”“偶发复位”或“调试器连不上”。理解这条链的先后依赖,是 ECU 集成阶段定位启动类问题的前提。
一、复位向量与启动入口
RH850 复位释放后,内核从固定复位向量地址取指。该地址通常位于 Code Flash 起始区域,向量表中存放的是启动代码入口地址,而不是 main。以 GHS/Multi 工具链为例,复位入口一般由启动汇编文件提供,并通过链接脚本固定在向量区:
/* 链接脚本片段:复位向量定位 */
MEMORY {
VECTORS (rx) : ORIGIN = 0x00000000, LENGTH = 0x1000
TEXT (rx) : ORIGIN = 0x00001000, LENGTH = 0x001F0000
}
SECTIONS {
.reset_vector : { KEEP(*(.reset_vector)) } > VECTORS
.text : { *(.text*) *(.rodata*) } > TEXT
}
复位向量区必须被 KEEP 保护,否则链接器优化可能将其回收,导致复位后取到非法地址。此外,RH850 的部分型号存在多组向量(如异常向量、中断向量),启动阶段至少要保证复位向量与初始异常向量有效。
二、启动代码与 C 运行时初始化
启动代码(Startup Code)承担从“裸机状态”到“可运行 C 环境”的过渡,典型动作顺序如下:
- 关闭全局中断,设置初始栈指针 SP,避免异常发生时无栈可用。
- 初始化必要系统寄存器,如 PSW、EBASE、中断控制相关基址。
- 将
.data段从 Flash 搬运到 RAM,将.bss段清零。 - 完成 C 运行时所需环境后,调用
main()。
其中 .data 搬运与 .bss 清零是“变量初值不对”的高频根因。若搬运源地址、目标地址或长度配置错误,全局变量会呈现随机值。下面是一个典型的启动搬运逻辑示意:
/* 启动代码中的段初始化示意 */
extern uint32 _data_load, _data_start, _data_end;
extern uint32 _bss_start, _bss_end;
void startup_copy(void) {
uint32 *src = &_data_load;
uint32 *dst = &_data_start;
while (dst < &_data_end) { *dst++ = *src++; }
dst = &_bss_start;
while (dst < &_bss_end) { *dst++ = 0u; }
}
三、栈与堆设置
RH850 通常支持多栈结构,至少包括系统栈与用户栈,部分工程还会为中断、任务分配独立栈。栈设置的核心是“位置、大小、对齐、边界保护”。栈顶一般放在 RAM 高端,向下增长;堆则从 RAM 低端向上增长,两者之间必须保留足够余量,防止相互踩踏。
| 对象 | 典型位置 | 关键参数 | 常见问题 |
|---|---|---|---|
| 系统栈 SP | RAM 高端 | 大小、8/16 字节对齐 | 中断嵌套溢出 |
| 用户栈 | RAM 次高端 | 与系统栈隔离 | 任务切换异常 |
| 堆 Heap | RAM 低端 | 起始、结束、增长方向 | 与栈碰撞 |
| 栈保护字 | 栈边界 | 魔术字校验 | 溢出无法及时发现 |
四、时钟初始化与看门狗配置
时钟初始化决定 CPU、外设与总线的运行频率,必须在访问依赖时钟的外设之前完成。典型顺序是:选择时钟源(内部高速/外部晶振/PLL)→ 配置 PLL 倍频 → 等待锁定 → 切换系统时钟 → 配置外设分频。若在 PLL 未锁定时切换,CPU 可能跑飞。
/* 时钟初始化顺序示意 */
CLK_SRC_SEL = EXT_CRYSTAL; /* 选择外部晶振 */
PLL_CTRL = PLL_ENABLE | PLL_MUL_20;
while (!(PLL_STATUS & PLL_LOCKED));
SYS_CLK_SEL = PLL_OUT; /* 切换系统时钟 */
PERIPH_DIV = DIV_2; /* 外设分频 */
看门狗(WDT)在启动阶段尤其敏感:若在启动代码中过早喂狗或未及时喂狗,会导致启动过程中反复复位。正确做法是:启动早期先确认 WDT 的初始状态,必要时在时钟稳定后按窗口要求配置并开启,再进入主循环喂狗。对于安全启动场景,WDT 往往被配置为“超时即复位”,并配合复位原因寄存器区分上电复位、看门狗复位与外部复位。
五、安全启动要点与典型误区
安全启动关注的是“启动链的可信与可诊断”。在 ECU 集成中,至少应做到:复位原因可读、关键段校验可做、看门狗状态可查、启动阶段有最小化日志或标志位。常见误区包括:
- 复位向量未加
KEEP,被链接器优化后取指异常。 .data搬运长度按字节计算却按字搬运,导致末尾数据错位。- 栈顶未对齐,触发 RH850 的对齐异常或性能下降。
- 时钟切换前就访问外设,读回值恒为 0 或总线挂死。
- 看门狗在启动阶段被意外关闭,量产后失去复位保护。
把启动链理解为“有向依赖图”而非简单顺序表,能帮助我们在集成阶段快速判断:某个外设读不到、某个变量初值异常、某次复位无法解释,究竟卡在向量、段初始化、栈、时钟还是看门狗环节。启动代码一旦稳定,后续驱动与 ECU 集成才有可靠的地基。