篇首
最近突发奇想,Xilinx 的集成开发环境已经很好了,很多必要的代码都直接生成了,这给开发者带来了巨大便利的同时,也让人错过了很多代码的精彩,可能有很多人用了很多年了,都还无法清楚的理解其中过程。博主准备以FSBL为例,与大家深入探讨一番,从而加深对ZYNQ的加载过程的理解,以便大家作出更精彩的设计!
LoadBootImage() 解读
本文以Zynq7000 FSBL工程代码为基础,分析启动流程核心函数LoadBootImage()LoadBootImage()LoadBootImage()的执行逻辑与关键技术细节。
一、函数调用框架
int LoadBootImage(void) {
FsblHookBeforeBitstreamDdr(); // 钩子函数
Status = XFsbl_LoadPartitions(...); // 核心加载
FsblHookBeforeHandoff(); // 移交前预处理
return Status;
}
二、 函数执行全流程分解
** 函数入口与预处理**
int LoadBootImage(void) {
u32 Status = XFSBL_SUCCESS;
XTime tStart, tEnd; // 64位计时器(若启用性能分析)
- 硬件依赖:
- 依赖
psu_init.c完成的PS端基础初始化(时钟、MIO、SLCR锁等) - DDR物理层已通过
Xil_DDRInit()完成训练(psu_ddr_phyinit.c)
- 依赖
** FsblHookBeforeBitstreamDdr()FsblHookBeforeBitstreamDdr()FsblHookBeforeBitstreamDdr() 钩子函数**
#ifdef FSBL_PERF
XTime_GetTime(&tStart); // 记录TSC起始值(AXI Timer 0)
#endif
/* 用户自定义扩展点:可插入DDR重配置代码 */
- 关键寄存器操作:
- DDRC控制:通过
Xil_Out32(0xFD070000, 0x00040010)设置DDRC_ADDRMAP0调整地址映射 - OCM重映射:关闭OCM缓存(
SLCR.OCM_CFG寄存器位3置1)
- DDRC控制:通过
XFsblLoadPartitions()XFsbl_LoadPartitions()XFsblLoadPartitions() 核心加载
阶段1:Boot Header解析
XFsblPs_BootHdr Header;
XFsbl_CheckBootHeader(ImageAddr, &Header); // 从QSPI/NAND读取头部
- 头部结构体(
xfsbl_ps_boothdr.h):typedef struct { u32 ImageID; // 魔数0xAA995566 u32 NumPartitions; // 分区总数(含PL比特流+应用) u32 AuthType; // 加密类型:0=None, 1=RSA-2048 u32 Checksum; // 头部的CRC32校验 // ... 其他字段(分区表偏移、证书偏移等) } XFsblPs_BootHdr;
阶段2:安全认证(以RSA-2048为例)
XSecure_Sha3Init(&Sha3Instance); // 初始化SHA-3引擎
XSecure_Sha3Update(&Sha3Instance, (u8*)ImageAddr, Header.HashLength);
XSecure_Sha3Final(&Sha3Instance, CalculatedHash); // 计算哈希
XSecure_VerifySignature(CalculatedHash, StoredSignature); // RSA验签
- 硬件加速:
- 使用PS内置的CSU模块(Crypto Subsystem)
- RSA密钥存储在eFUSE或BBRAM中(通过
XSecure_GetEfuseKek()读取)
阶段3:分区加载循环
for (u8 i=0; i<Header.NumPartitions; i++)

最低0.47元/天 解锁文章
2474

被折叠的 条评论
为什么被折叠?



