2. AURIX启动流程分析与启动代码修改
任务目标
阅读 AURIX TC3xx 的启动代码,定位复位向量、启动模式判定与时钟初始化流程,并通过修改启动配置调整时钟初始化的执行顺序。本案例以最小可复现的启动代码片段演示:复位入口如何跳转到启动模式判定,再进入时钟初始化,并给出修改顺序后的验证方法。
启动流程结构
复位后 CPU 从复位向量取指,进入启动代码 _Start;启动代码读取启动模式头(BMHD)判定启动模式,随后调用时钟初始化与外设初始化,最终跳转 main()。本案例修改点在于调整时钟初始化与外设初始化的先后顺序。
关键代码
以下为最小可复现的启动代码片段(TC3xx 风格,使用 GCC/Tasking 通用写法)。STARTUP_ORDER 宏控制时钟初始化顺序,修改该宏即可改变执行次序。
/* startup_cfg.h —— 启动配置 */
#ifndef STARTUP_CFG_H
#define STARTUP_CFG_H
/* 启动顺序选择:0 = 先时钟后外设(默认);1 = 先外设后时钟 */
#define STARTUP_ORDER 0
/* 启动模式定义(与 BMHD 对应) */
typedef enum {
BOOT_MODE_INTERNAL = 0, /* 内部 Flash 启动 */
BOOT_MODE_ALT = 1, /* 备用启动 */
BOOT_MODE_UNKNOWN = 2
} BootMode_t;
#endif
/* startup.c —— 复位向量与启动流程 */
#include "startup_cfg.h"
/* 复位向量:链接脚本将 .reset 段定位到 0xA0000000 */
__attribute__((section(".reset")))
void _Start(void);
/* 前向声明 */
static BootMode_t GetBootMode(void);
static void ClockInit(void);
static void PeriphInit(void);
extern int main(void);
/* 复位入口 */
void _Start(void)
{
BootMode_t mode = GetBootMode();
if (mode == BOOT_MODE_UNKNOWN) {
/* 未知启动模式:停在安全循环,等待看门狗复位 */
for (;;) { }
}
#if (STARTUP_ORDER == 0)
ClockInit(); /* 默认:先初始化时钟 */
PeriphInit(); /* 再初始化外设 */
#else
PeriphInit(); /* 修改后:先初始化外设 */
ClockInit(); /* 再初始化时钟 */
#endif
main(); /* 跳转应用入口 */
for (;;) { } /* main 不应返回 */
}
/* 读取启动模式:实际项目中读取 BMHD 或 SCU 寄存器 */
static BootMode_t GetBootMode(void)
{
/* 简化示例:固定返回内部 Flash 启动 */
return BOOT_MODE_INTERNAL;
}
/* 时钟初始化:配置 PLL、分频等 */
static void ClockInit(void)
{
/* 示例:使能 PLL,等待锁定 */
volatile unsigned int *pll_con = (volatile unsigned int *)0xF0036000u;
*pll_con |= 0x1u; /* 使能 PLL */
while ((*pll_con & 0x2u) == 0u) { } /* 等待锁定 */
}
/* 外设初始化:GPIO、UART 等 */
static void PeriphInit(void)
{
volatile unsigned int *gpio_dir = (volatile unsigned int *)0xF003A000u;
*gpio_dir = 0x00000001u; /* 配置 P0.0 为输出 */
}
运行与验证
编译(以 GCC 交叉工具链为例):
tricore-elf-gcc -c startup.c -o startup.o -I.
tricore-elf-gcc -c main.c -o main.o -I.
tricore-elf-gcc startup.o main.o -T tc3xx.ld -o app.elf
验证方法:
- 用
tricore-elf-objdump -d app.elf反汇编,确认_Start位于.reset段且地址为0xA0000000。 - 将
STARTUP_ORDER改为1重新编译,反汇编确认_Start中PeriphInit的调用指令出现在ClockInit之前。 - 通过条件:复位向量地址正确,且修改宏后调用顺序随之改变,即判定启动配置修改生效。
注意:ClockInit 与 PeriphInit 中的寄存器地址为示例值,实际项目需替换为对应 TC3xx 型号的寄存器基址。