篇首
最近突发奇想,Xilinx 的集成开发环境已经很好了,很多必要的代码都直接生成了,这给开发者带来了巨大便利的同时,也让人错过了很多代码的精彩,可能有很多人用了很多年了,都还无法清楚的理解其中过程。博主准备以FSBL为例,与大家深入探讨一番,从而加深对ZYNQ的加载过程的理解,以便大家作出更精彩的设计!
FsblHandoff()函数解析
FsblHandoff()
是ZYNQ7000 FSBL(第一阶段引导程序)的最后一步,负责将执行权限从FSBL移交给用户程序(如u-boot或裸机程序)。其核心逻辑如下:
-
关闭中断与缓存
- 在跳转前关闭所有中断,避免移交过程中发生异常。
- 禁用MMU(内存管理单元)和D-Cache(数据缓存),确保跳转后的程序在干净的内存环境中运行。
-
设置跳转地址
- 通过
LoadBootImage()
函数获取用户程序的入口地址(通常存储在DDR中)。 - 该地址被写入链接寄存器(LR)或直接传递给汇编代码。
- 通过
-
汇编级跳转
- 在
fsbl_handoff.S
文件中,通过汇编指令BX LR
实现跳转。例如:ldr lr, =HandoffAddress // 加载用户程序入口地址到LR bx lr // 跳转执行
- 此操作直接切换程序计数器(PC),不再返回FSBL,完成控制权移交。
- 在
-
关键设计细节
- 无栈操作:跳转前不保存上下文,因FSBL任务已终结。
- 地址验证:需确保用户程序入口地址有效,否则可能导致系统崩溃。
-
思维导图
这个函数比较简单,用一个思维导读做为结束吧。
到这里,Xilinx ZYNQ FSBL解读就告一段落了,下面总结一下。
FSBL工作流程总结
FSBL的执行流程可分为以下阶段:
-
BootROM阶段
- 上电后执行固化代码,根据MIO引脚确定启动模式(如QSPI/SD),加载FSBL到OCM(片上内存)。
-
硬件初始化
- 调用
ps7_init()
初始化PS端外设,包括MIO、PLL、时钟、DDR控制器等。 - 解锁SLCR寄存器,刷新并关闭D-Cache,注册异常处理函数。
- 调用
-
启动介质处理
- 根据启动模式(如QSPI/SD)初始化存储设备,加载镜像文件(BOOT.BIN)。
- 解析镜像头信息,验证分区合法性,并拷贝Bitstream(PL配置)和应用程序到DDR。
-
PL配置与程序移交
- 通过PCAP接口加载Bitstream配置FPGA。
- 调用
FsblHandoff()
跳转至用户程序,结束FSBL使命。
整个FSBL其实非常简单,主题流程就是初始化硬件、从指定存储器中找到需要加载的数据,然后搬移到指定内存区间,如果存在FPGA,则通过PCAP加载FPGA。中间大部分代码都是验证,验证各种参数的合法性,因为任何一个参数的错误,就会导致系统崩溃。
专栏总结
Xilinx ZYNQ FSBL解读作为一个专栏系列文章,也是本人偷懒。本来一篇文章即可描述清楚,但是作者工作压力很大,职业程序员大抵如此,个人时间零碎,没有办法,就只能一点一点进行。
本专栏一方面作为自己工作学习经验总结,一方面希望能给大家一点微小帮助,但凡能做到如此,所有付出便有所值了,谢谢大家。
最后附上作者在进行本专栏写作时,所用到的思维导图,作为专栏结尾。