评测对象:NUCLEO-H5E5ZJ
测试目标:搭建 TrustZone 安全 / 非安全分区工程,验证分区隔离效果,评估对现有代码改动量与资源开销。
运行效果:绿色LED闪烁

一、分析示例代码
TrustZone工程示例代码的目录位于STM32Cube_FW_H5_V1.7.0\Projects\NUCLEO-H5E5ZJ\Templates\TrustZoneEnabled,里面分别有Secure和None-Secure的代码,支持MDK\IAR和CubeIDE三种构建方式。
1.参考示例工程说明配置OptionBytes
- TZEN=B4
- SECWM1_STRT=0x0 SECWM1_END=0xFF
- SECWM2_STRT=0x1 SECWM2_END=0x0



- 2.存储器布局
H5系列芯片通过IDAU控制地址访问,采用了“别名”的机制,CPU在Secure状态的下看到的flash、ram以及外设地址别从0x0c 0x30 0x50开始。
- 3.Secure代码做的事情
① HAL初始化
② Cache初始化(可选)
③ 设置系统隔离
1)使能GTZC时钟
2)SRAM分块隔离
3)定义并填充MPCBB结构体
4)使用MPCBB结构体设置SRAM3 SRAM4 SRAM5
5)Flash隔离(通过OB进行设置)
④ GTZC外设放行
⑤ TZIC开启中断(清非法访问标志、开中断源、NVIC)
⑥ 开启SecureFault
⑦ 系统时钟初始化(可选)
⑧ 挂起Systick
⑨ 跳转到NS执行代码
⑩ 实现HAL_GTZC_TZIC_Callback
知识点:TZIC 中断处理跨界违规 ,SecureFault异常处理Secure世界内部的非法访问。
- 4.None-Secure代码做的事情
① HAL初始化
② 注册两个重点要的回调函数
③ SecureFault_Callback响应异常
④ SecureError_Callback响应GTZC和TZIC的中断
⑤ 设置系统时钟
⑥ 初始化外设
⑦ 执行用户代码
二、使用CubeMX重建示例代码工程
- 1.创建CubeMX工程
首先启动cubemx创建H5E5板子的工程,选择带有TrustZone的模板,然后保存该工程到一个空文件夹。生成代码类型选择cmake。点击generate生成代码。使用vscode打开工程文件夹,可以看到已经生成了包含S和NS的代码结果,按F7编译工程,正常情况下编译成功并生成S和NS的2个elf文件。
- 2.修改CubeMX配置
通过在 CubeMX 里改配置,使得生成的代码尽量接近示例程序。
(1) 在 CubeMX 中使能S侧的 GTZC,并开启中断,GTZC的参数保持默认即可。
(2) 重要!把PA11 PB8 PB9三个引脚设置为NS。因为GIPO是TZ aware外设,并且每个管脚都能配置安全属性,如果不配置默认是S。
(3) 重要!在BSP中关闭VCOM。因为默认生成的BSP代码,配置VCOM时会触发非法访问中断,然后进到SecureError_Callback函数。UART属于GTZC管理的Seurable外设,无法像GPIO那样能直接把自己设置为NS,配置GTZC稍复杂,此处直接禁用。
如图所示:

- 3.代码移植
(1)关于链接脚本。 通过对比CubeMX生成的代码中的Flash的S和NS连接脚本的存储区域布局,发现与示例代码完全一致,因此链接脚本无需改。
(2)S侧有6 段必须手写的代码,包括:SecureFault 使能、TZIC ClearFlag/EnableIT、HAL_SuspendTick()、HAL_GTZC_TZIC_Callback 转发、SecureFault_Handler 转发等。
(3)NS侧需要手动添加的代码有:SECURE_RegisterCallback + 两个回调实现。
强烈建议代码移植借助AI工具实现!
三、操作经验
由于编译出来的可执行文件有2个,因此必须分2次烧录。通常的顺序是先烧写S程序,再烧写NS程序。这两段程序相互独立,因此如果怀疑其中一个有问题,可以从示例工程中烧写另一个,反复对比进行验证。
需要注意的是,如果想要调试NS代码,启动调试器以后,可能会停留在NS的reset_handler汇编代码处,这时候只要通过调试器重启板子,代码就能正常运行到main函数入口。

四、资源占用
NonSecure部分资源占用情况

Secure部分资源占用情况
