• 正文
  • 相关推荐
申请入驻 产业图谱

STM32N6 XIP调试技术原理解析

09/29 11:14
263
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

1. STM32N6启动流程与BootROM机制

STM32N6的启动流程从BootROM开始。BootROM是芯片出厂时固化在系统存储器中的一段只读代码,在上电复位后首先执行。BootROM根据启动模式引脚(Boot管脚)的配置决定从何处加载下一步的程序。在外部Flash启动模式下,BootROM会从外部Flash加载FSBL并跳转执行。

DEV模式是STM32N6的一种调试友好模式。在DEV模式下上电时,STM32N6的DBG端口是打开的,调试器可以连接芯片。这是本文方案能够在DEV模式下直接调试的硬件前提。

复位类型对调试端口有直接影响。传统调试方法中使用的reset按钮复位属于系统复位,系统复位不会关闭DBG端口。这意味着在切换到外部Flash启动模式并按reset后,调试器仍然保持连接状态,FSBL执行完成后可以继续进行调试。如果是上电复位(冷复位),DBG端口的状态则取决于启动模式。

启动模式的切换通过Boot管脚实现。传统方法需要在DEV模式与外部Flash启动模式之间切换,这就要求硬件设计时将Boot管脚引出到可操作的位置。本文方法省去了这一步,直接在DEV模式下通过软件手段模拟FSBL的执行流程。

资料获取:实战经验 | LAT1721 使用STM32CubeIDE调试STM32N6 XIP应用的一种方法

2. FSBL的作用与XIP模式设置

FSBL(First Stage Bootloader)是STM32N6启动链中的关键环节。它的主要职责包括:初始化系统时钟、配置XSPI外设、设置外部Flash为memory map模式、最终跳转到外部Flash中的应用程序执行。

在XIP应用的启动流程中,FSBL执行前后外部Flash的可访问性发生本质变化。FSBL执行前,XSPI处于复位默认状态,外部Flash没有被映射到CPU地址空间,CPU无法直接从外部Flash取指。FSBL执行后,XSPI被配置为memory map模式,外部Flash的内容出现在Cortex-M55的地址空间中,CPU可以直接从外部Flash读取指令并执行,这就是XIP(Execute In Place)的工作基础。

FSBL的最后一步是调用JumpToApplication函数跳转到应用程序。该函数的地址在FSBL工程中是固定的,可以通过FSBL的map文件或link文件查到。在Template_FSBL_XIP工程中,JumpToApplication函数的地址为0x34180810。本文方案正是利用这个地址设置断点,在FSBL跳转到应用前暂停调试器,为加载应用符号表创造条件。

3. XSPI memory map模式与外部Flash寻址

XSPI是STM32N6上用于连接外部串行存储器的高速接口,支持SPI、Dual SPI、Quad SPI、Octo SPI等多种协议。XSPI有两种主要工作模式:间接模式(Indirect Mode)和memory map模式。在间接模式下,CPU通过寄存器读写外部Flash,类似于传统的SPI操作;在memory map模式下,外部Flash被映射到CPU的地址空间,CPU可以像访问内部存储器一样直接读写外部Flash。

XIP技术依赖于XSPI的memory map模式。只有当FSBL将XSPI配置为memory map模式后,外部Flash中的应用代码才能被CPU直接取指执行。这也是为什么在FSBL未执行时,调试器无法直接读取外部Flash中的应用代码——此时XSPI还处于间接模式或未初始化状态,外部Flash不在CPU地址空间中。

在Template_FSBL_XIP工程中,Application被烧录到外部Flash的地址0x7010400。这个地址是外部Flash在memory map模式下映射到Cortex-M55地址空间中的偏移地址。FSBL完成memory map配置后,CPU从该地址开始取指执行应用程序。应用程序的链接脚本需要与该烧录地址保持一致,确保函数地址与实际存储位置对应。

4. Cortex-M55向量表重定位技术

Arm Cortex-M内核通过向量表偏移寄存器(Vector Table Offset Register,VTOR)来定位中断向量表。在STM32N6上,该寄存器的地址为0xE000ED08。复位后,向量表默认指向芯片内部的BootROM向量表。通过写入VTOR,可以将向量表重定位到任意地址。

本文方案中,GDB初始化命令的第二条是:

set {uint32_t}0xE000ED08 = 0x34180400

这条命令将Cortex-M55的向量表设置为0x34180400。地址0x34180400是FSBL的首地址,即FSBL的isr_vector(中断向量表)地址。该地址可以从FSBL工程的link文件或map文件中查到。将向量表指向FSBL后,调试器运行时就会从FSBL的向量表获取初始栈指针(MSP)和复位入口地址,从而开始执行FSBL代码。

这一步是整个方案的技术关键。正常启动时,BootROM会完成向量表的设置并跳转到FSBL。在DEV模式直接调试时,BootROM没有执行FSBL的加载,因此需要通过GDB命令手动设置向量表,让调试器“以为”FSBL是正常启动的程序,从而开始执行FSBL代码,完成XSPI的memory map配置。

5. GDB初始化命令脚本逐行解析

本文方案的核心是STM32CubeIDE Debug配置中Startup页的GDB初始化命令脚本。完整脚本如下:

load "../Boot/Debug/Template_XIP_FSBL.elf"
set {uint32_t}0xE000ED08 = 0x34180400
break *0x34180810
continue
break main

下面逐行解析每条命令的作用:

第一行 load “../Boot/Debug/Template_XIP_FSBL.elf”:在加载Template_XIP_AppS.elf符号表之前,先加载FSBL的elf文件。这一步将FSBL的符号信息加载到调试器中,但不会将FSBL代码下载到目标板(FSBL不需要烧录,它在调试过程中由调试器控制执行)。加载FSBL符号表后,调试器能够识别FSBL中的函数与变量,便于后续的断点设置与单步调试。

第二行 set {uint32_t}0xE000ED08 = 0x34180400:将Cortex-M55向量表偏移寄存器设置为0x34180400,即FSBL的isr_vector地址。如2.4节所述,这一步使调试器运行时从FSBL的向量表开始执行。

第三行 break *0x34180810:在地址0x34180810处设置断点。该地址是FSBL中JumpToApplication函数的地址,可以从FSBL源码及Template_XIP_FSBL.map文件中确认。FSBL执行时,在跳转到Application之前会触发这个断点,调试器暂停执行。此时FSBL已经完成了XSPI的memory map配置,外部Flash已经可以正常访问。

第四行 continue:让调试器继续运行。从向量表设置完成后,调试器开始执行FSBL代码,直到命中0x34180810处的断点暂停。在这个过程中,FSBL完成了所有硬件初始化工作,包括XSPI的memory map模式设置。

第五行 break main:在Application的main函数入口处设置断点。当调试器从JumpToApplication断点继续运行后,FSBL跳转到Application执行,最终会进入main函数并触发该断点,调试器停在main函数入口,开发者即可开始正常的应用调试。

在命令脚本执行的间隙,IDE还会加载Application的符号表。具体来说,在continue命令运行至JumpToApplication断点后,IDE加载Template_XIP_AppS.elf的符号表,然后执行break main设置应用入口断点。这样应用程序的函数名、变量名等符号信息就能在调试器中正常显示。

6. 硬断点与软断点:外部Flash断点的特殊处理

ARM Cortex-M架构支持两种断点:软断点(Software Breakpoint)和硬断点(Hardware Breakpoint)。软断点通过在目标代码处插入一条特殊的断点指令(如BKPT)实现,需要修改目标存储器中的代码。硬断点通过内核中的调试比较寄存器实现,不需要修改目标代码,数量有限(通常为4到8个)。

对于存储在内部Flash或RAM中的代码,软断点可以正常工作,因为调试器可以临时修改这些存储器中的指令。但对于存储在外部Flash中的XIP应用代码,软断点无法使用。原因是外部Flash在memory map模式下通常是只读的,调试器无法向外部Flash写入BKPT指令来替换原有指令。如果在外部Flash地址上设置软断点,断点将不会生效。

因此,对于GDB Debug,处于外部Flash上的断点需要改为硬断点。具体操作是:在断点列表子窗口中,右键单击需要设置的断点,选择“Breakpoint Properties”进入断点属性设置窗口,然后在Common选项中将Type改为Hardware或Hardware Temporary即可。硬断点利用Cortex-M55内核的FPB(Flash Patch and Breakpoint)单元实现,不依赖修改目标代码,可以在外部Flash上正常触发。

7. 关键地址与参数详解

本方案涉及多个关键地址与参数,以下逐一说明:

地址/参数 值 含义 来源
Application烧录地址 0x7010400 Application bin文件在外部Flash中的烧录起始地址 Template_FSBL_XIP工程配置
FSBL首地址(isr_vector) 0x34180400 FSBL中断向量表的起始地址,用于设置VTOR FSBL工程link文件/map文件
JumpToApplication函数地址 0x34180810 FSBL中跳转应用函数的地址,用于设置断点 FSBL源码及Template_XIP_FSBL.map文件
向量表偏移寄存器(VTOR) 0xE000ED08 Cortex-M55内核寄存器,写入该地址重定位向量表 Arm Cortex-M55技术参考手册
STM32CubeIDE版本 V1.18.1 本文使用的IDE版本,客户参考时请不要低于该版本 LAT1721小结
固件包版本 STM32Cube_FW_N6_V1.3.0 提供Template_FSBL_XIP工程的固件包版本 LAT1721引言

需要注意的是,FSBL首地址0x34180400和JumpToApplication函数地址0x34180810是基于Template_FSBL_XIP工程的默认配置。如果开发者修改了FSBL的链接脚本或优化等级,这些地址可能发生变化。在实际项目中,应从对应工程的map文件或link文件中获取准确的地址值,不可直接照搬本文中的数值。

8. 技术约束与注意事项

使用本方案时需要注意以下技术约束:

  • STM32CubeIDE版本不得低于V1.18.1。本文中的调试配置与GDB脚本在该版本上验证通过,低版本可能存在兼容性问题。
  • Application固件必须预先烧录到外部Flash。本方案中调试器不下载Application代码(“Load Image and Symbols”选项中不勾选下载),因此需要在调试前通过STM32CubeProgrammer将bin文件烧录到0x7010400。
  • 外部Flash上的断点必须使用硬断点。软断点无法在外部Flash上生效,需要手动将断点类型改为Hardware或Hardware Temporary。
  • Runtime选项中应取消“Set breakpoint at main”。因为GDB初始化脚本中已经通过break main命令设置了main函数断点,重复设置可能导致冲突。
  • “Load Image and Symbols”选项设置中,不需要下载代码(已烧录),但需要加载符号表。符号表的加载使调试器能够识别应用程序中的函数与变量名称。
  • 本方案仅以外部Flash启动模式为例,其他启动模式不在本文讨论范围内。ExtMemLoader子工程也不做讨论。

相关推荐