ZYNQMP FSBL启动流程

1 FSBL介绍

1.1 背景

最近由于在工作中需要做一些底层备份的工作,用的芯片属于ZYNQ UltraScale+ MPSoC系列的,大致看了网上的一些资料,基本都是讲ZYNQ 7000系列,涉及ZYNQMP系列比较少,所以自己也是去了解了一下ZYNQMP系列的FSBL流程。与ZYNQ7000系列FSBL流程基本差别不大,涉及的一些流程可以借鉴。这里主要看的是米联客介绍的FSBL启动流程。

1.2 ZYNQMP启动流程

  • ZYNQMP的启动步骤,可以大致分为BootRom、FSBL、Uboot、Linux系统几个环节,这四个环节流程图如下:
    在这里插入图片描述
    1.首先, 电源管理单元(PMU)执行 PMU ROM 固化程序来初始化系统,重置和唤醒相关的进程。
    2.接着,根据拨码开关从相应内存位置将引导加载程序(PS 的 FSBL 代码)加载到芯片 RAM (OCM)中并执行。
    3.然后,运行 ATF 之后启动 uboot 第一阶段引导程序初始化内存等基础硬件,将 uboot 第二阶段和kernel 加载到 DDR 中。
    4.最后,从内存 DDR 中加载运行 uboot 第二阶段初始化相关设备,配置 kernel 启动的环境并引导kernel 从而启动 rootfs。
  • BootRom是固化在芯片内部的一段代码,我们不可以进行修改,而通过上图我们知道BootRom主要是用来加载FSBL到OCM中运行,并且将执行权限交给FSBL,关于BootRom怎么找到FSBL,主要是我们利用petalinux-package打包BOON.BIN时,存在一个BOOT.BIN的头部,里面包括了FSBL的大小,偏移地址等等,通过BOOT.BIN头找到FSBL,将执行权限交给FSBL,有兴趣的可以去Xilinx官网下载相关的文档查看,里面对Boot Header,image header table,partition header等介绍的很清楚。
  • 我们主要来看看FSBL启动流程

2 FSBL启动流程

2.1 工程

因为我这边用到的工程主要是在Linux系统下利用Petalinux搭建的,具体xilinx的Vavido或者vitis我不会用,用的是FPGA那边给的配置好的xsa或者hdf文件,在ubuntu环境下搭建的工程,工程搭建完毕后直接利用petalinux-config -c u-boot/kernel/fsbl,就可以在工程中生成FSBL,U-BOOT和kernel的源码,这里我们以工程中生成的FSBL源码进行大致的分析。

2.2 流程

  • FSBL 的全名为 First Stage Boot Loader,即第一阶段引导加载程序。 FSBL 的任务比较重要,它需要完成以下的工作:

    a. 初始化PS端
    b. 使用 bit 文件配置 PL 端。
    c. 加载 Uboot 到内存中。
    d. 移交执行权限给 Uboot。

  • 以下为 fsbl 的启动流程:
    在这里插入图片描述这个阶段需要完成一系列的初始化操作,首先会初始化 PS 端的内存与 MIO 接口等,然后读取 bit文件配置好 PL 端, 值得注意的是 PL 端需要在 FSBL 的阶段配置好,否则是无法直接配置的。接着加载 Uboot 到内存中,最后 ARM 会跳转到内存中执行 Uboot 程序。

2.3 代码分析

  • 因为 FSBL 的作用是引导 SSBL,所以引导裸机和引导 Uboot 的 FSBL 没有什么区别,因此我们直接从petalinux创建的工程 查看 FSBL 的相关源码。
  • 首先我们的平台是ZYNQMP,所以我们需要到***fsbl\lib\sw_apps\zynqmp_fsbl\src***下,里面存在链接脚本文件lscript_a53.ld和lscript.ld,打开如下:在这里插入图片描述
    可以看到ENTRY函数,进入初始化向量表_vector_table,这里进行一些初始化操作。
  • 而*_vector_table定义在源码*fsbl\lib\bsp\standalone\src\arm\ARMv8\64bit\gcc\asm_vectors.S里面。
    在这里插入图片描述
    在向量表中可以看到,启动程序会跳转到
    _boot
    , 为了查看其源码,我们需要找到_boot 的实现, _boot的实现在 boot.S 文件中, 打开同目录下的 boot.S 文件: 找到_boot,可以看到其首先在初始化处理器的各种模式,初始化 C 语言的执行环境:
    在这里插入图片描述
    这里会使能 I cache、 SP 堆栈、 caches、 MMU,然后跳转至_startup 函数启动
    在这里插入图片描述
    同样的方法,我们需要找到_startup 的实现,这个函数在同目录下的 xil-crt0.S 中,打开 xil-crt0.S文件并找到
    _startup

    在这里插入图片描述
    在_startup 函数中,对 bss 进行了一系列的操作,然后清 bss,构造全局结构体,重启定时器之后跳转到 main 函数开始执行。
  • 这里进入main函数,main函数路径:fsbl\lib\sw_apps\zynqmp_fsbl\src\xfsbl_main.c
    在这里插入图片描述
    main 函数会经历以下四个主要阶段:
    a.各种初始化。
    b.引导设备安装和 image 验证。
    c. 加载并验证分区
    d. 执行完FSBL,转到uboot,即第二阶段。
    各种初始化:在这里插入图片描述
    这个函数包括了诸多软硬件的初始化操作,非常清楚地看到在 switch 中属于 XFSBL_STAGE1 也就是 第 一 阶 段 , 在 其 运 行 成 功 后 , 才 会 跳 转 到 第 二 阶 段 继 续 执 行 , 其 位 置 为fsbl\lib\sw_apps\zynqmp_fsbl\xfsbl_initialization.c在这里插入图片描述
    这个函数的第一步便是获取复位的原因。
    紧接着是系统初始化:在这里插入图片描述
    在这个函数的注释中,调用了 psu_init()这个函数, 该函数根据 PS 的类型进行 MIO,PLL,CLOCK,DDR一系列参数的设定。
    在这里插入图片描述
    处理器初始化:
    在这里插入图片描述
    DDR 初始化:在这里插入图片描述
    板卡初始化:在这里插入图片描述
    重置验证:
    在这里插入图片描述
  • 如果这些初始化操作均成功了,到这里整个初始化工作便可以告一段落了,接下来要运行第二阶段,也就是引导设备安装和 image 验证。
  • 引导设备安装和 image 验证
    在这里插入图片描述
    这一段代码比较有趣,逻辑也比较清晰: 首先运行初始化函数,然后根据返回参数来判断启动方式,分为错误、 JTAG 和普通启动模式。其中如果引导发现是 JTAG 模式就会直接跳转到第四步,这是因为第三步的任务是加载分区,而 JTAG 模式是不需要的。了解的初始化函数的返回值,我们再去查看其实现,同样还是在 xfsbl_initialization.c 文件中:
    在这里插入图片描述
    第一步为获取模式开关的参数,查看 XFsbl_PrimaryBootDeviceInit 函数:在这里插入图片描述
    其中一段就展示了获取模式开关的代码,注意此处不是读取模式开关,因为读取是由 BootROM完成的, FSBL 只是 获取了 BootROM 的参数。 这里以 NAND 启动方式为例, 在读取到为XFSBL_NAND_BOOT_MODE 这个参数后,会进行如下的操作:在这里插入图片描述
    先是初始化设备(这里是 NAND),再从设备中读取 BOOT.bin 文件,最后关闭文件。
    上一步完成后,紧接着就是读取验证头:在这里插入图片描述
    最后是设置第二启动设备,如果有第二启动设备,还要对其进行初始化操作:在这里插入图片描述
  • 加载并验证分区
    部分启动方式可以跳过此部分,比如 JTAG 模式。
    在这里插入图片描述
    第三部分也是如出一辙,先加载分区,分为成功与失败两个情况,成功的情况下会继续验证分区。我们先来看 XFsbl_PartitionLoad 这个函数,它的定义在同目录 xfsbl_partition_load.c 这个文件里:在这里插入图片描述
    以上为 XFsbl_PartitionLoad 的核心代码,分为三步,先验证分区头,查验是不是对应的型号,如果是对应的型号则复制分区内容,最后是分区的验证。
    回到 xfsbl_main.c 文件中,第三步还会对所有分区进行一次验证,保证所有分区均已加载完成:在这里插入图片描述
    这一步完成后,便会跳转至下个阶段。
  • 转移执行权限
    在第四阶段中, 同样也是先运行移交权限的 XFsbl_Handoff 函数,然后处理各种返回的情况:分为三种情况,为:分区未加载完全,会跳转到第三步继续执行。继续移交权限,主要出现在一个应用执行完,需要运行下一个应用时。失败的情况,移交权限失败。还有一种情况就如同注释写的那样,应该永远也不会被执行。在这里插入图片描述
    看完整体的构架,接下来要看看 XFsbl_Handoff 的定义,了解一下移交执行权限究竟经过了哪些步骤,这个函数的定义位于 xfsbl_handoff.c 文件中:
    恢复 SD 卡检测信号:
    在这里插入图片描述 解除PS-PL 隔离以允许 u-boot 和 linux 访问 PL:在这里插入图片描述
    刷新 L1 和 L2 数据缓存,禁用数据缓存:在这里插入图片描述
    PM 初始化:在这里插入图片描述
    保护配置:在这里插入图片描述
    切换到 CPU 运行:在这里插入图片描述
  • 到这里, FSBL 阶段的工作全部完成,接下来就由 Uboot 来继续操作。

3 总结

  • 相信大家看了上面的分析以及源代码后,大致可以了解FSBL的启动流程,对于FSBL,汇编阶段我们可以不必过于关注,如果我们需要修改FSBL,也只是修改FSBL的C语言阶段。
  • 当然,如果真的分析了源码,我们可以发现在主函数中的starge3中,会依次加载BOOT.BIN中的几个分区,有几个分区就分别加载几个,但是,在***XFsbl_PartitionLoad***函数中,调用了三个函数,我仔细看了这三个函数,只是在验证每个分区的头部,对于uboot实体,并没有进行验证,如果我们在nand启动时由于bit位翻转,那系统将无法启动,所以后面我增加了对整个uboot实体的crc校验以及增加了备份分区,主分区加载失败,FSBL启动备份分区uboot镜像。
  • 将在下一篇博客分析,后面也还会在uboot中增加kernel备份镜像功能。
  • 15
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值