3. S32Z 存储与内存架构

S32Z 的存储体系不是“一块 Flash 加一块 RAM”的简单结构,而是围绕实时控制任务做了明确分层:程序长期存放在 Flash,运行期数据放在 SRAM,而最苛刻的实时任务代码与数据则被放进紧耦合内存 TCM。理解这套分层,是后续写链接脚本、配置 MPU 和保护机制的前提。

一、存储层次与访问特性

S32Z 内部主要包含以下几类存储资源。Flash 用于存放启动代码、标定数据和应用程序镜像,容量大、非易失,但访问延迟明显高于片上 RAM,且擦写寿命有限,因此不适合高频写入。SRAM 是通用运行内存,容量较大,可被内核、DMA 和外设共享,适合堆栈、通信缓冲和普通变量。TCM(Tightly Coupled Memory)是紧耦合内存,分为 ITCM(指令 TCM)和 DTCM(数据 TCM),它们直接挂在处理器核的本地总线上,访问延迟确定、不受系统总线争用影响,是实时任务最理想的落脚点。

需要特别区分的是:ITCM 主要承载指令,即实时任务函数本体;DTCM 主要承载数据,即实时任务使用的变量、状态和缓冲区。二者物理独立,可同时被访问,从而避免取指与取数互相阻塞。S32Z 每个核通常配有独立的 ITCM/DTCM 区域,具体容量随型号不同,工程中应以参考手册的 memory map 为准。

S32Z 存储层次与实时任务映射关系 Flash 非易失 · 容量大 · 延迟高 启动镜像 / 标定 / 常量 SRAM 通用运行内存 · 可共享 堆栈 / DMA 缓冲 / 普通变量 ITCM 指令紧耦合 · 低延迟 实时任务函数本体 DTCM 数据紧耦合 · 低延迟 实时变量 / 状态 / 小缓冲 系统总线 / 交叉开关 CPU 内核 取指单元 / 数据单元 实时任务调度 MPU 权限检查 ECC 校验 单比特纠错 / 双比特报错 状态寄存器可读 内存保护 MPU 区域属性 特权 / 只读 / 不可执行 ← 直接本地访问 ← 读写时校验 ← 访问前检查

二、链接脚本:把关键任务放进 TCM

链接脚本决定各段代码和数据最终落在哪个物理区域。以 GCC 风格为例,核心思路是:先声明 TCM 的 MEMORY 区域,再把指定函数和变量通过 section 属性放入对应段,最后在 SECTIONS 中把段定位到 TCM 地址。下面给出一个可参考的示例结构,地址与容量为教学示例,实际应以芯片手册为准。

MEMORY
{
  FLASH  (rx)  : ORIGIN = 0x00400000, LENGTH = 4M
  SRAM   (rwx) : ORIGIN = 0x20400000, LENGTH = 512K
  ITCM   (rx)  : ORIGIN = 0x00000000, LENGTH = 64K
  DTCM   (rw)  : ORIGIN = 0x20000000, LENGTH = 64K
}

SECTIONS
{
  .itcm_text : {
    *(.itcm_code)
    *(.itcm_code.*)
  } > ITCM

  .dtcm_data : {
    *(.dtcm_data)
    *(.dtcm_data.*)
  } > DTCM

  .text : { *(.text*) } > FLASH
  .data : { *(.data*) } > SRAM
  .bss  : { *(.bss*)  } > SRAM
}

在 C 代码中,通过段属性把函数和变量显式放入 TCM:

__attribute__((section(".itcm_code")))
void MotorCtrl_ISR(void) { /* 高频中断服务 */ }

__attribute__((section(".dtcm_data")))
volatile float g_currentRef;

__attribute__((section(".dtcm_data")))
volatile uint32_t g_pwmDuty[3];

这样,MotorCtrl_ISR 的指令从 ITCM 取指,g_currentRef 和 g_pwmDuty 从 DTCM 读写,二者互不争用系统总线,中断响应时间更可预测。需要注意的是,TCM 容量有限,只应放真正高频、对延迟敏感的对象;把大量普通变量塞进 DTCM 会迅速耗尽空间,反而迫使链接器报错或把其他段挤回 SRAM。

三、MPU 配置与内存保护

MPU 负责在每次访问前检查地址是否落在允许的区域、访问类型是否合法。典型配置思路是:为 Flash 设置只读、可执行;为 SRAM 设置可读写、可执行或不可执行;为 ITCM 设置只读、可执行;为 DTCM 设置可读写、不可执行。这样即使某个指针越界写入 ITCM,也会触发异常而不是静默破坏指令。

配置时通常需要指定基地址、区域大小、权限位和属性位。区域大小一般按 2 的幂对齐,例如 32KB、64KB。若某段数据需要被 DMA 访问,还要考虑该区域是否允许外设访问,以及是否需要关闭缓存一致性相关属性。MPU 区域之间不应重叠,重叠会导致行为不确定。

四、ECC 与内存保护机制

S32Z 对 Flash、SRAM 和 TCM 通常都提供 ECC 保护。ECC 能在读取时检测并纠正单比特错误,同时检测双比特错误。工程上应关注两点:一是初始化时对 RAM 区域做完整写入,使 ECC 校验位建立有效状态,否则首次读取未初始化单元可能报错;二是运行中读取 ECC 状态寄存器,区分“已纠正”和“不可纠正”事件。单比特错误可记录并继续运行,双比特错误通常需要触发安全响应,例如复位或进入安全状态。

建议在启动阶段对 DTCM 和 SRAM 的关键区域执行一次写零或写模式初始化,确保 ECC 校验位有效,再进行任务调度。

五、工程检查要点

  • 确认 ITCM/DTCM 的物理地址与容量,避免链接脚本地址写错导致下载后无法启动。
  • 只把高频 ISR、控制环函数和关键状态变量放入 TCM,普通缓冲留在 SRAM。
  • MPU 区域按最小必要权限设置,ITCM 不可写、DTCM 不可执行。
  • 启动时初始化 ECC,运行中周期读取 ECC 状态寄存器并记录错误计数。
  • 用 map 文件核对各段实际落点,确认没有段溢出或被意外放回 Flash。

把上述环节串起来,S32Z 的存储架构就从“容量列表”变成了可执行的实时性保障手段:Flash 负责持久,SRAM 负责通用,TCM 负责确定性,MPU 与 ECC 负责安全边界。链接脚本正是把这些意图落到具体地址上的关键工具。