篇首
最近突发奇想,Xilinx 的集成开发环境已经很好了,很多必要的代码都直接生成了,这给开发者带来了巨大便利的同时,也让人错过了很多代码的精彩,可能有很多人用了很多年了,都还无法清楚的理解其中过程。博主准备以FSBL为例,与大家深入探讨一番,从而加深对ZYNQ的加载过程的理解,以便大家作出更精彩的设计!
Zynq 7000启动流程详解
Zynq 7000的启动流程是一个多阶段协作过程,从硬件上电到操作系统运行,涉及BootROM、FSBL、SSBL(如U-Boot)和最终应用。以下是各阶段的核心逻辑与关键操作:
一、BootROM阶段:硬件初始化的起点
-
触发条件
- Zynq芯片上电或复位后,BootROM(固化在芯片内部的只读代码)自动执行。
-
关键操作
- 硬件初始化:
- 配置PS(处理器系统)基础时钟、MIO引脚、安全模块(如AES和SHA引擎)。
- 启动模式检测:
- 根据MIO引脚电平(Boot Mode Pins)确定启动设备(QSPI、SD卡、NAND等)。
- 支持的启动模式通过
SLCR.BOOT_MODE
寄存器配置。
- 加载FSBL:
- 从选定的启动设备读取FSBL镜像到OCM(On-Chip Memory,默认地址
0x0
)。 - 校验FSBL头部(验证签名,若启用安全启动)。
- 从选定的启动设备读取FSBL镜像到OCM(On-Chip Memory,默认地址
- 权限移交:
- 跳转到FSBL的入口地址(通常为
0x0
),结束BootROM阶段。
- 跳转到FSBL的入口地址(通常为
- 硬件初始化:
二、FSBL阶段:系统启动的核心枢纽
-
硬件初始化(
ps7_init()
)- DDR配置:
- 初始化DDR控制器,设置时序参数(
ps7_ddr_init()
),确保后续镜像可加载到外部内存。
- 初始化DDR控制器,设置时序参数(
- 时钟树配置:
- 配置PLL生成CPU、外设、PL时钟(
ps7_clock_init()
)。
- 配置PLL生成CPU、外设、PL时钟(
- 外设初始化:
- 使能UART、QSPI、SD控制器等(
ps7_peripherals_init()
),支持调试与镜像加载。
- 使能UART、QSPI、SD控制器等(
- DDR配置:
-
异常处理注册
- 绑定异常向量表:
- 通过
Xil_ExceptionRegisterHandler()
注册数据中止、未定义指令等异常处理函数。
- 通过
- 调试支持:
- 若启用
FSBL_DEBUG_INFO
,初始化UART输出启动日志。
- 若启用
- 绑定异常向量表:
-
镜像加载与处理
- 解析
BOOT.BIN
:- 读取镜像头(
ImageHeader
),识别分区类型(FSBL、SSBL、PL比特流、设备树等)。 - 示例镜像结构:
如果是裸机运行,或者是freeRTOS等轻量级系统,不需要使用U-Boot,则SSBL直接用SDK编译的APP镜像替换。BOOT.BIN ├── FSBL(自身镜像,已由BootROM加载) ├── PL比特流(.bit文件) └── SSBL(如U-Boot)
- 读取镜像头(
- 安全处理:
- 若镜像加密,调用AES引擎解密(使用eFUSE或BBRAM中的密钥)。
- 若启用认证,验证RSA签名或HMAC哈希。
- 解析
-
PL配置(可选)
- PCAP接口传输:
- 通过PS的PCAP(Processor Configuration Access Port)将比特流写入PL。
- 检查PL配置状态寄存器(
DEVICE_STATUS
),确认配置完成。
- PCAP接口传输:
-
移交控制权
- 跳转到SSBL:
- 关闭FSBL使用的外设(如QSPI控制器),禁用缓存和MMU。
- 将SSBL(如U-Boot)的入口地址强制转换为函数指针并执行跳转:
void (*SSBL_Entry)(void) = (void (*)(void))0x100000; // U-Boot默认加载地址 SSBL_Entry();
- 跳转到SSBL:
三、SSBL阶段:操作系统加载的桥梁
-
U-Boot的核心任务
- 环境变量初始化:
- 从Flash或环境分区读取
uEnv.txt
,设置启动参数(内核地址、设备树路径等)。
- 从Flash或环境分区读取
- 加载操作系统镜像:
- 从存储设备读取Linux内核(
uImage
或Image
)、设备树(.dtb
)、根文件系统(rootfs
)到DDR。
- 从存储设备读取Linux内核(
- 启动内核:
- 调用
bootm
命令,传递内核入口地址、设备树地址等参数,跳转到内核执行。
- 调用
- 环境变量初始化:
-
PL重配置(动态可选项)
- U-Boot支持通过
fpga load
命令在运行时重新配置PL,实现硬件动态切换。
- U-Boot支持通过
四、操作系统阶段:最终用户环境
-
Linux内核初始化
- 硬件探测:
- 初始化CPU、内存、中断控制器(GIC)、外设驱动(如以太网、USB)。
- 挂载根文件系统:
- 从eMMC、SD卡或网络(NFS)加载
rootfs
,切换至用户空间。
- 从eMMC、SD卡或网络(NFS)加载
- 硬件探测:
-
用户应用启动
- 执行
/sbin/init
或用户指定程序,启动完整系统服务。
- 执行
五、启动流程中的关键注意点
-
镜像格式与兼容性
BOOT.BIN
必须包含Xilinx格式的镜像头,否则BootROM无法识别。- PL比特流需为Zynq 7000专用的
.bit
文件,包含头部同步字(0xAA995566
)。
-
调试与错误排查
- BootROM阶段失败:检查启动模式引脚、Flash连接、镜像签名。
- FSBL阶段卡死:通过UART日志定位DDR初始化或PL配置错误。
- SSBL无法加载内核:检查U-Boot环境变量与文件系统路径。
-
安全启动流程
- 密钥烧录:将公钥哈希写入eFUSE,防止未签名镜像执行。
- 安全隔离:启用TrustZone,隔离安全与非安全世界代码。
六、流程图解
上电 → BootROM → 加载FSBL → FSBL初始化 → 加载SSBL/PL → 跳转至U-Boot → 加载内核 → 启动系统
通过深入理解Zynq 7000的启动链条,开发者可精准优化启动速度、增强系统可靠性,并实现定制化安全策略。