zynq7000 FSBL 源码分析

9 篇文章 0 订阅

最近一直在用赛灵思的zynq7000芯片,是一个ARM核+FPGA的soc,zynq在运行完芯片内固化的bootRom之后运行的是FSBL程序(first stage boot loader),uboot由FSBL调起,官方说法中将uboot叫做SSBL(second stage boot loader).

本文分析fsbl源码;fsbl源码由vivado工具生成,笔者的vivado版本是2019.1.

bootROM阶段

芯片上电之后,cpu从0x0000地址开始运行,此时芯片运行的是bootROM固化代码,这一段代码主要是初始化CPU和一些必要的外设->QSPI、SD卡、NORFlash.初始化这些外设是为了从这些外设中拿到BOOT.BIN(fsbl和uboot通过赛灵思的工具整合在一个文件中,这个文件叫BOOT.BIN)

假设我们使用SD卡作为启动设备,bootROM会初始化SD卡并从SD卡的第一个分区拿到BOOT.BIN,(第一个分区的文件系统只能是FAT格式)然后从BOOT.BIN的文件头中获取fsbl代码的长度,位置,将fsbl复制到256KB的OCM中运行(on chip memory),再跳转到FSBL,至此bootROM的生命周期就结束了。

fsbl阶段

fsbl的工作主要有:

1 初始化DDR,为下面的工作做准备

2 调起uboot,这是fsbl最重要且必要的任务

3 将bitstream配置到fpga,这是可有可无的任务

开始分析:

1 汇编阶段


找到asm_vectors.S文件,这是fsbl最开始运行的汇编.
可以看到如下代码:
_vector_table:
    B    _boot

 跳转到_boot标号处,有如下代码:
cmp r1, #0
beq CheckFUSE

cmp r1, #0:

比较r1寄存器值和立即数0,如果r1等于0,那么ARM的CPSR寄存器的Z bit为1;
beq CheckFUSE:
查看CPSR寄存器的Z bit,如果为1,则跳转到CheckFUSE处;如果为0,不跳转。

现在跳转到CheckFUSE处,有如下代码:
ands r1,r1,#0x80
beq OKToRun

这一段跟上面那一段差不多,不再解释,直接跳到OKToRun:
OKToRun中有四五十行汇编,主要做了关闭MMU,关闭Dcache(CPU的数据缓存,是CPU L1 cache中的Dcache,还有一个Icache是指令缓存;Dcache与Icache合在一起构成了CPU的L1 cache,就是常说的一级缓存)

直到OKToRun的最后面有这样的一句:
b _start

跳转到_start标号处:
bl __cpu_init

跳转到__cpu_init标号处:
这里开始对CPU进行初始化,主要是为C语言运行环境做准备,SP指针指向OCM段的结尾。
直到运行这一句:
bl main
终于,我们可以打印hello world了.
 

2 C语言阶段

1
Status =ps7_init();
初始化 MIO PLL CLK DDR3/2

2
Xil_DCacheFlush();
Xil_DcacheDisable();
清空Dcaches关闭Dcaches;上面已经关过了这里为什么还要关?无他,稳健。

3
Status=InitPcap();
初始化Pcap,Pcap具体是什么我也不清楚,不过看后面的使用发现,应该可能大概是操作AXI总线使用的.

4
GetSiliconVersion();
获取silicon的版本

5
BootModeRegister = Xil_In32(BOOT_MODE_REG);
获取boot模式寄存器,这个寄存器的值取决于你的bootmode管脚是如何设置的。

6
根据BootModeRegister 选择从哪里拿BOOT.BIN
QSPI启动:
                InitQspi();
                MoveImage = QspiAccess;
Nand启动:
                Status = InitNand();
                MoveImage = NandAccess;
NOR启动:
                InitNor();
                MoveImage = NorAccess;
初始化Qspi/nand/nor, flash操作函数MoveImage 指向各自的xxxxAccess函数.

SD卡启动:
                Status = InitSD("BOOT.BIN");
                MoveImage = SDAccess;
挂载SD卡打开BOOT.BIN文件,flash操作函数MoveImage 指向SDAccess函数.

7
HandoffAddress = LoadBootImage();
获取application在DDR中的运行地址(链接地址),这里的application指的就是SSBL,也就是uboot

8
FsblHandoff(HandoffAddress);
fsbl交出控制权,从HandoffAddress地址运行application

到这里,uboot终于出生了,fsbl也宣告生命结束。
接下来就是uboot的事情,拿设备树到DDR,拿kernel到DDR,解压kernel,将kernel从加载地址移动到运行地址,给kernel传递参数并调起kernel....


OK我话终于讲完.

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值