4. 多核启动与核间同步

AURIX TC3xx 上电后并非所有核同时开始执行用户代码。芯片复位释放后,CPU0 作为主核(Master)从 Boot ROM 开始运行,其余 CPU1、CPU2 等从核(Slave)默认停留在停止状态,等待主核显式唤醒。理解这一非对称启动过程,是构建多核实时系统的第一步。本节围绕三个核心问题展开:主核如何把从核"拉起来"、核间如何用中断传递事件、以及多核如何通过共享内存安全地交换数据。

一、主核启动从核的完整流程

从核的启动本质上是一次"地址投递 + 释放"操作。每个从核都有独立的复位控制寄存器,主核需要完成以下动作:

  1. 准备从核入口地址:在链接脚本中为每个核分配独立的代码段(如 .text.cpu1),并定义从核入口函数 Core1_Main()。该函数的地址就是投递给从核的启动向量。
  2. 写入启动地址:通过 CPU1_PC(Program Counter 寄存器)写入入口地址。TC3xx 中该寄存器位于 SCU(System Control Unit)模块,写操作需要先解锁 SCU_WDTCPU1CON 相关的保护位。
  3. 释放从核:清除 CPU1_KRST 中的复位保持位,从核脱离复位状态,从写入的 PC 值开始取指执行。
  4. 等待从核就绪:主核通过一个共享内存标志位或核间中断确认从核已完成基本初始化(时钟、看门狗、栈指针),再继续后续任务。

以下是一段典型的主核启动从核代码(示例参数,非实测):

/* 主核 CPU0 中执行 */
#define CPU1_START_ADDR  ((uint32)Core1_Main)

void StartCore1(void)
{
    /* 1. 解锁 CPU1 复位控制 */
    IfxScuWdt_clearCpuEndinit(IfxScuWdt_getCpuWatchdogPassword());

    /* 2. 写入 CPU1 启动地址 */
    SCU_CPU1_PC = CPU1_START_ADDR;

    /* 3. 释放 CPU1 复位 */
    SCU_CPU1_KRSTCLR.B.KRSTCLR = 1;

    /* 4. 等待 CPU1 就绪标志 */
    while (g_core1_ready == 0) { }
}

/* 从核 CPU1 入口 */
void Core1_Main(void)
{
    /* 初始化本核时钟、看门狗、栈 */
    IfxScuWdt_clearCpuEndinit(IfxScuWdt_getCpuWatchdogPassword());
    /* 置位就绪标志,通知主核 */
    g_core1_ready = 1;
    /* 进入本核主循环 */
    while (1) { Core1_Task(); }
}

关键点在于:从核入口函数必须自行完成本核的看门狗初始化和栈指针设置,不能依赖主核代劳。若从核在入口处未及时喂狗,会触发看门狗复位,表现为"从核启动后立即重启"的典型故障。

二、核间中断(IPI)机制

核间中断(Inter-Processor Interrupt,IPI)是 AURIX 多核通信的硬件基础。TC3xx 通过 SCU 中的 CPU_ICR(Interrupt Control Register)实现核间中断触发。主核向目标核写入中断请求位,目标核的中断控制器收到后跳转到对应的 ISR。

IPI 的典型用途包括:

  • 事件通知:主核完成数据准备后,通过 IPI 通知从核"数据已就绪"。
  • 任务调度:主核向从核分发周期性任务,从核在 ISR 中置位任务标志。
  • 同步屏障:多核在某个汇合点等待,最后一个到达的核通过 IPI 唤醒其他核。

配置 IPI 时需要注意:目标核必须在 ISR 中清除中断标志,否则会反复触发。同时,IPI 的优先级应低于关键实时中断,避免核间通信干扰控制环路。

三、共享内存同步机制

多核共享内存(如 LMU、DSPR 的共享区域)是数据交换的主要通道,但多核同时读写会引发竞态。AURIX 提供了硬件信号量(SRI Semaphore)和软件原子操作两种同步手段。

硬件信号量:TC3xx 的 SRI 总线支持 64 个硬件信号量,通过 SMU 模块的 SEM 寄存器组访问。获取信号量时,硬件保证原子性,返回 0 表示成功,非 0 表示已被占用。释放时写入对应位即可。

软件原子操作:使用 __cmpswapw() 内建函数实现比较交换,适合轻量级标志位同步。例如:

/* 尝试获取锁 */
uint32 lock = 0;
uint32 expected = 0;
if (__cmpswapw(&g_lock, 1, expected) == 0) {
    /* 获取成功,进入临界区 */
    g_shared_data = new_value;
    g_lock = 0;  /* 释放锁 */
}

共享内存同步的核心原则是:任何跨核共享的变量都必须有明确的访问协议。要么用信号量保护,要么用原子操作,要么用"单写多读"的无锁设计。切忌两个核同时写同一变量而不加保护。

AURIX 多核启动与核间同步机制 主核 CPU0 Boot ROM → 用户代码 写 CPU1_PC 启动地址 清 CPU1_KRST 释放复位 等待就绪标志 从核 CPU1 复位保持 → 释放 从 PC 值取指执行 初始化时钟/看门狗/栈 置位 g_core1_ready ① 写 PC + 释放复位 ② 就绪标志 / IPI 通知 核间中断 IPI(SCU_CPU_ICR) 主核写目标核中断请求位 → 目标核跳转 ISR → ISR 中清除标志 用途:事件通知 · 任务分发 · 同步屏障 共享内存同步(LMU / DSPR 共享区) 硬件信号量 SRI SEM 寄存器组 原子获取/释放 软件原子操作 __cmpswapw() 比较交换 轻量级标志位同步 单写多读无锁 一个核写,其余核读 配合内存屏障 核心原则:任何跨核共享变量必须有明确的访问协议(信号量 / 原子操作 / 无锁设计)

四、工程实践中的常见问题与判断依据

在实际调试中,多核启动与同步问题往往表现为间歇性故障,难以复现。以下是几个典型现象及其判断依据:

现象可能原因排查方法
从核启动后立即复位 从核入口未及时喂狗 在 Core1_Main 开头立即调用 IfxScuWdt_clearCpuEndinit
主核等待就绪标志超时 从核 PC 地址错误或未释放复位 用调试器查看 CPU1_PC 值和 KRST 状态位
共享数据偶发错误 缺少信号量保护或内存屏障 检查所有跨核写操作是否在临界区内
IPI 触发后 ISR 不执行 目标核中断未使能或优先级被屏蔽 检查 ICR 配置和当前 CPU 优先级掩码

判断多核同步是否正确的最终依据是:在长时间运行和边界条件下,共享数据的一致性不被破坏。建议在开发阶段加入断言检查,例如在从核写入共享数据后,主核读取时校验数据完整性标志。

实践建议:多核启动顺序应遵循"先初始化共享资源,再启动从核"的原则。主核在释放从核之前,应完成共享内存区域、信号量、中断控制器的初始化,避免从核启动后访问未初始化的资源。
注意:TC3xx 的看门狗默认在复位后处于激活状态。从核入口函数的第一条语句就应该是清除看门狗 ENDINIT 保护并喂狗,否则从核可能在启动后几毫秒内被看门狗复位,表现为"从核启动后无响应"。

总结来说,AURIX 多核启动与同步的核心链路是:主核写 PC → 释放复位 → 从核自初始化 → 就绪通知 → IPI 事件驱动 → 共享内存受控访问。掌握这条链路中每个环节的硬件寄存器和软件协议,才能构建稳定可靠的多核实时系统。