4. 启动流程与初始化

AURIX TC3xx 从上电到应用主循环运行,并不是一条“跳转到 main 就结束”的直线,而是一条由硬件复位逻辑、Boot ROM、用户启动代码、时钟与看门狗配置、内存初始化以及多核同步共同构成的启动链。理解这条链的先后依赖关系,是排查“程序不跑”“跑飞”“多核不同步”“看门狗误复位”等问题的前提。

一、复位向量与启动入口

AURIX 的复位分为上电复位、系统复位、看门狗复位、软件复位等多种类型。无论哪种复位,CPU 都会从固定的复位向量地址取指。TC3xx 的复位入口通常位于 Boot ROM 区域,由芯片固件完成最基础的初始化,再根据启动模式(Boot Mode)决定后续行为。

启动模式由启动模式选择引脚(如 HWCFG 引脚)在上电复位释放瞬间采样决定,常见模式包括:

  • 内部 Flash 启动:从 PFlash 的启动代码开始执行,是最常用的量产模式。
  • Bootloader 模式:进入串口/CAN 等引导加载流程,用于刷写程序。
  • 调试模式:配合调试器直接接管 CPU,常用于开发阶段。
  • 备用启动:从特定内存或外部接口启动,用于恢复或特殊场景。

用户启动代码的入口地址由链接脚本和启动配置共同决定,通常放在 PFlash 起始区域,并通过向量表或启动头(Boot Header)告知 Boot ROM 跳转目标。

二、启动代码的执行顺序

用户启动代码(Startup Code)一般由汇编与 C 混合编写,核心任务是“把 C 运行环境准备好”。典型顺序如下:

  1. 关闭全局中断,设置栈指针(SP),为各核准备独立栈区。
  2. 初始化时钟系统,把 CPU 从复位默认时钟切换到目标 PLL 频率。
  3. 配置看门狗,先“喂狗”或临时关闭,避免初始化超时被复位。
  4. 初始化内存:清零 .bss、搬运 .data、配置必要 RAM 区域。
  5. 初始化 MPU/内存保护、缓存与必要外设。
  6. 多核启动:主核唤醒从核,从核完成自身初始化后进入同步点。
  7. 跳转到 main(),进入应用层。
启动代码中最容易出错的不是“功能”,而是“顺序”:时钟没切好就访问高速外设、看门狗没处理就做长耗时内存初始化、从核未同步就访问共享数据,都会导致启动失败或随机异常。

三、时钟系统初始化

AURIX 复位后默认使用内部备份时钟,频率较低且精度有限。应用通常需要切换到外部晶振驱动的 PLL,以获得更高主频和稳定时钟。时钟初始化一般包括:使能外部晶振、等待晶振稳定、配置 PLL 分频/倍频参数、切换系统时钟源、更新时钟分频树。

/* 伪代码:时钟切换关键步骤 */
Enable_XTAL();
Wait_XTAL_Stable();
Config_PLL(K1, K2, N);
Wait_PLL_Locked();
Switch_SystemClock_To_PLL();
Update_Peripheral_Divider();

切换过程中必须等待 PLL 锁定标志,否则 CPU 可能在时钟未稳定时取指,造成不可预期的行为。同时要注意外设时钟分频,例如 CAN、ADC、SPI 的时钟源是否已按目标频率重新计算。

四、看门狗与内存初始化

AURIX 的看门狗(Watchdog)在复位后通常处于激活状态,且默认超时时间较短。启动代码必须在超时前完成“喂狗”或按安全流程关闭/重配看门狗。量产代码中不建议长期关闭看门狗,而应尽早配置为符合系统节拍的窗口看门狗模式。

内存初始化主要包括:

  • .bss 段清零:未初始化全局变量必须为 0。
  • .data 段搬运:已初始化变量从 Flash 拷贝到 RAM。
  • 栈区设置:每个核独立栈,避免多核踩踏。
  • RAM 初始化:部分安全相关 RAM 需要 ECC 初始化或自检。
如果 .bss 未清零,全局变量初值可能是随机值;如果 .data 未搬运,已初始化变量会保持 Flash 中的原始值而非运行值。这类问题往往在调试时表现为“变量莫名奇妙不对”。

五、多核启动与同步

TC3xx 是多核架构,通常由一个主核(如 CPU0)负责启动流程,其他从核处于等待状态。主核完成基础初始化后,通过写从核的启动地址寄存器并释放从核,从核从指定入口开始执行自己的启动代码。多核启动的关键是“同步点”:所有核必须完成各自初始化后,才能进入共享资源访问阶段。

常见同步方式包括:主核设置标志位、从核轮询等待;或使用核间中断(IPI)通知。同步点之前,从核不应访问主核尚未初始化完成的外设或共享内存。

AURIX TC3xx 启动流程与初始化链路 复位事件 上电/看门狗/软件 Boot ROM 采样启动模式 启动模式选择 Flash / Bootloader / 调试 用户启动代码 Startup Code 入口 启动代码内部初始化顺序 ① 关中断 设置栈指针 各核独立栈 ② 时钟系统 晶振→PLL 等待锁定 ③ 看门狗 喂狗/重配 避免超时复位 ④ 内存初始化 .bss 清零 .data 搬运 ⑤ 多核启动 主核释放从核 同步点等待 多核启动与同步关系 主核 CPU0 完成全局初始化 从核 CPU1/CPU2 等待释放信号 同步点 全部就绪后进入 main 释放从核 就绪标志 关键原则:时钟稳定 → 看门狗安全 → 内存就绪 → 多核同步 → 进入应用

六、典型误区与复盘

误区现象 根本原因 排查方向
程序停在启动阶段 PLL 未锁定就切换时钟 检查晶振起振与锁定标志
反复复位 看门狗超时未喂狗 确认看门狗配置与喂狗周期
全局变量初值异常 .bss 未清零或 .data 未搬运 检查链接脚本与启动拷贝逻辑
从核不运行 未释放从核或入口地址错误 检查从核启动寄存器与同步标志
多核访问共享资源冲突 同步点之前访问未初始化外设 确认同步顺序与资源初始化时机
调试启动问题时,建议在启动代码的关键节点翻转 GPIO 或写入调试变量,用示波器或调试器观察执行到哪一步。比“单步跟踪”更高效,尤其适合多核和看门狗场景。

总结来说,AURIX 的启动流程是一条严格的依赖链:复位向量决定入口,Boot ROM 决定启动模式,启动代码按顺序完成时钟、看门狗、内存和多核初始化,最终进入 main。任何一步顺序错误或等待缺失,都会在后续阶段以“看似无关”的故障形式暴露出来。掌握这条链,才能把启动问题定位在正确的环节。