篇首
最近突发奇想,Xilinx 的集成开发环境已经很好了,很多必要的代码都直接生成了,这给开发者带来了巨大便利的同时,也让人错过了很多代码的精彩,可能有很多人用了很多年了,都还无法清楚的理解其中过程。博主准备以FSBL为例,与大家深入探讨一番,从而加深对ZYNQ的加载过程的理解,以便大家作出更精彩的设计!
RegisterHandlers()解读
在Xilinx Zynq 7000系列的FSBL(First Stage Boot Loader)中,SDK 2018.3版本的RegisterHandlers()
函数主要用于注册异常处理函数,确保启动过程中CPU异常或中断能够被正确响应。以下是具体的Handler及其作用:
1. 异常处理Handler
RegisterHandlers()
通过调用Xil_ExceptionRegisterHandler
注册以下异常处理函数,覆盖ARM Cortex-A9的所有标准异常类型:
-
未定义指令异常(Undefined Instruction)
- Handler:
Undef_Handler
- 作用:处理未识别的指令执行错误,记录错误状态或触发回退流程。
- Handler:
-
SVC调用异常(Supervisor Call)
- Handler:
SVCHandler
- 作用:处理软件中断(如系统调用),但在FSBL中通常未使用,仅作占位。
- Handler:
-
预取中止异常(Prefetch Abort)
- Handler:
PrefetchAbortHandler
- 作用:处理指令预取阶段的内存访问错误(如地址越界),可能导致启动终止。
- Handler:
-
数据中止异常(Data Abort)
- Handler:
DataAbortHandler
- 作用:处理数据访问阶段的内存错误(如DDR读写失败),通常与DDR初始化或镜像加载错误相关。
- Handler:
-
中断请求(IRQ)和快速中断(FIQ)
- Handler:
IRQHandler
、FIQHandler
- 作用:处理外部硬件中断,但在FSBL中通常未启用,仅初始化默认处理逻辑。
- Handler:
2. 异常处理机制的实现
-
向量表绑定:在
asm_vectors.S
文件中,异常向量表(如.vectors
段)直接跳转到这些Handler,通过注册,中断向量表中的内容将变成如下:_vector_table: B _boot B Undefined B SVCHandler B PrefetchAbortHandler B DataAbortHandler NOP /* 地址异常占位 */ B IRQHandler B FIQHandler
通过
RegisterHandlers()
将这些Handler与ARM异常ID绑定,确保异常发生时调用对应的函数。 -
默认行为:在FSBL中,这些Handler通常仅记录错误并触发回退流程(如
FsblHookFallback
),而非复杂处理,因为FSBL需保持轻量级。
3. 核心作用
- 异常管理:注册的Handler通过 XExc_VectorTable 异常向量表与硬件关联,确保在启动阶段(如DDR初始化、PL配置)发生硬件异常时,系统能捕获并处理错误,防止崩溃。
- 中断初始化:为后续阶段(如应用程序或U-Boot)提供基础中断框架,例如通过GIC分发PS端外设中断。
- 调试支持:在开发阶段,未定义指令或内存访问错误等异常处理程序可辅助定位硬件配置或代码逻辑问题。
4. 与启动流程的关联
- 错误恢复:若DDR初始化失败(
DDRInitCheck()
)或PL配置出错(InitPcap()
),异常Handler会通过FsblHookFallback
尝试切换到备用启动路径。 - 调试支持:启用
FSBL_DEBUG_INFO
宏后,Handler可通过UART输出错误信息,辅助定位启动失败原因。
总结
在SDK 2018.3的FSBL中,RegisterHandlers()
主要注册的是ARM Cortex-A9的异常处理函数,而非PL配置或镜像加载相关的功能Handler(如比特流加载或AES解密)。这些异常Handler是启动流程的基础保障,确保硬件错误或配置异常时能安全终止或回退。若需扩展功能(如PL加载或加密),需在LoadBootImage()
等函数中实现,而非通过RegisterHandlers()
。