ZYNQ - 嵌入式Linux开发 -10- ZYNQ启动流程分析

简介: ZYNQ - 嵌入式Linux开发 -10- ZYNQ启动流程分析

FSBL启动准备工作


在静态情况下,Boot.BIN启动文件存放在SD卡或QSPI等存储介质中,然后Boot.BIN文件中已经包含了FSBL代码,也就是说FSBL代码已经集成在了Boot.BIN文件中,所以FSBL代码也是存放在Boot .BIN文件中。

如果要启动FSBL代码,就需要完成以下几件事情:

  1. 找到BOOT.BIN文件所在的位置。
  2. 从BOOT . BIN文件中找到FSBL代码。
  3. 找到之后将其拷贝到内存当中( ZYNQ片 内RAM 256K字节大小)。
  4. 运行FSBL代码。

而以上这些事情由BootROM来去做。

BootROM


何为BootROM?


BootROM它是一个程序/代码,并且已经固话在ZYNQ芯片内部,用于启动的BOOT程序。BootROM代码存放片内ROM当中,所以叫做BootROM。因为ZYNQ内部包含256K RAM 以及128K ROM。所以BootROM代码可以固化在ROM当中,并且在掉电情况下不会丢失。

一般情况下,芯片内部的ROM都是Nor Flash。

NOR Flash 的特点是芯片内执行(XIP ,eXecute In Place),这样应用程序可以直接在Flash闪存内运行,不必再把代码读到系统RAM中。

BootROM的作用与功能


BootROM的主要作用用于引导、启动FSBL代码。

它要完成引导、启动FSBL代码的这个任务需要完成以下几件事情(也就是前文提到的FSBL的启动准备工作):

  1. 找到BOOT.BIN文件所在的位置。
  2. 从BOOT . BIN文件中找到FSBL代码.
  3. 找到之后将其拷贝到内存当中(ZYNQ片内RAM 256K字节大小)
  4. 运行FSBL代码。

为了支持上述的操作,所以BootROM程序需要支持以下功能。

  1. 包含了SD卡或者QSPI等存储设置的驱动程序。
  2. BootROM代码支持文件系统操作,至少支持Fat 32这个文件系统。

对于ZYNQ平台的嵌入式Linux系统来说,Linux内核由U-Boot引导、启动;U-Boot由FSBL引导、启动;FSBL由ZYNQ片内BootROM引导、启动。

SD卡加载方式启动流程


在Sd卡启动方式下,BootROM代码的运行流程:

  1. 初始化MI0引脚,主要配置MIO引脚的物理特性配置寄存器;重点是将MIO40~MIO45复用为SD0外设所对应的CLK/CMD/DATA引脚。
  2. 初始化SD卡外设,驱动SD卡,可以实现sD卡读写操作。
  3. 对SD卡读写进行测试。
  4. 从SD卡文件系统当中读取BOOT. BIN文件,并对BootROM头进行解析。在BOOT.BIN文件前面有一段头部信息,这个头部信息是按照一-定的格式组组织在一起,在这个头部信息当中就包括了fsbl的加载地址、fsbl的 大小以及fsbl在BOOT. BIN文件中的位置偏移量。BootROM代码能够解析这个头部信息
  5. 得到fsbl代码的大小和位置偏移量以及加载地址之后,BootROM代码就会从BOOT.BIN文件中。将fsbl代码拷贝到RAM内存中,并且跳转到fsbl代码的运行地址去启动fsbl。

自此,BootROM就成功启动了FSBL代码了。

QSPI加载方式启动流程


在QSPI启动方式下,BootROM代码的运行流程:

  1. 初始化MIO引脚,将相关的MIO引脚复用为QSPI外设所需的引脚功能。
  2. 初始化QSPI外设,驱动QSPI Flash设备,可以实现QSPI读写操作。
  3. 对QSPI进行读写测试。
  4. 从QSPI存储介质中读取BOOT. BIN文件,并对Boot ROM头进行解析。
  5. 得到fsbl代码的大小和位置偏移量以及加载地址之后,BootROM代码就会从BOOT.BIN文件中。将fsbl代码拷贝到RAM内存中,并且跳转到fsbl代码的运行地址去启动fsbl。

不同于SD卡的文件系统的搜索方式,在QSPI启动方式下,BootROM代码首先会从QSPI的0x000000地址去找BOOT . BIN文件,如果找不到那么就去下一个地址0x008000,如果还找不到他又会跳转到下一个地址0x10000,但是搜索范围不能超出QSPI的前面16MB地址空间。

image.png

BOOT.BIN头


BOOT.BIN头是BOOT.BIN文件前面的一段头部数据,并且这个头部数据是按照一定格式组织在一起的, 并且该头部数据能够并BootROM代码所解析。

image.png

image.png

在BOOT.bin文件中从地址0-0x8FF可以分成17个部分,每个部分都有一定的含义。

  1. 0x000:中断向量表。
  2. 0x020:固定值0xaa995566(小端)。
  3. 0x024:固定值0x584c4e58 ASCII: XLNX。
  4. 0x028:如果是0xa5c3c5a3或者0x3a5c3c5a为加密的。
  5. 0x02C:BootROM头版本号,不用管。
  6. 0x030:此参数包含从有效bootrom头开始到fslb/用户代码映像所在位置的字节数,也就是 FSBL/用户代码的地址偏移量。该地址偏移量必须要大于等于0x8C0。
  7. 0x034:记录fsbl的长度,用于指导BootROM代码拷贝 fsbl 长度。
  8. 0x038:将FSBL拷贝到OCM的什么位置一般为0x0,加载地址,指导BootROM代码拷贝FSBL到RAM的哪个位置。
  9. 0x03C:FSBL在OCM中的运行地址一般定义为0x0,运行地址,指导BootROM代码跳转到RAM哪个地址去运行。
  10. 0x040:记录FSBL的长度。
  11. 0x044:为固定值0x01。
  12. 0x048:校验和(将Ox020-0x047之间的数据按32bit长度进行相加,并取反即可!若相加之后的数据大小超过32bit,则取低32bit 数据进行取反)。
  13. 0x04C-0x097:fsbl/用户代码自定义,不需要的话可以全部填充为0。
  14. 0x098:image header table位置偏移量。
  15. 0x09C:partition header table 的所在位置。
  16. 0x0A0-0x89F:寄存器初始化的参数。
  1. 0x8C0:FSBL、用户代码必须要等于或高于此地址。

简述通过BOOT.BIN头如何找到FSBL


BOOT.BIN头部信息当中记录了FSBL代码的位置、大小以及fsbl代码它在RAM内存中的加载地址。0x30地址记录了fsbl代码在BOOT.BIN文件中的位置偏移量,0x34记录了fsbl代码的长度,0x38记录了fsbl代码在SRAM中的加载地址,BootROM代码解析到这些信息之后,就会从FSBL代码的位置偏移量去读取0x34地址中记录的大小,然后把它拷贝到FSBL代码的加载地址中。最后跳转到0x3C地址中记录的FSBL的运行地址中去启动FSBL。

简述通过BOOT.BIN如何找到U-Boot和


bitstream


BOOT.BIN文件当中包含了FSBL镜像、u-boot镜像以及bitstream 文件。

BootROM代码需要通过解析BOOT.BIN头部信息去找到FSBL。BootROM代码去启动FSBL。

FSBL代码运行之后,要负责从 BOOT.BIN文件中找到U-Boot镜像和 bitstream文件,然后把 bitstream文件加载到ZYNQ PL端,然后要启动U-Boot。

这里需要涉及到三个数据表:

  • image headelr table;
  • partition header table;
  • image header。

Image Headelr Table


image header table 只有一个,partition header table和 image header是成对出现的。BOOT.BIN 文件中包含了多少个镜像,那么就有多少对partition header table 和 imageheader。

image.png

  • 0x00:image header table 的版本号;
  • ox04:image header的数量;
  • 0x08:第一个Partition Header table的位置偏移量。这里是以word为单位计算的,所以实际的偏移量需要乘上一个4;
  • 0x0C:第一个Image Header的位置偏移量。采用了word 度量单位;
  • 0x10:header authentication 的偏移量。采用了word为度量单位;
  • 0x1C:使用0xFFFFFFFF进行填充,直到整个image header table的大小为64字节。

Image Header


image.png

  • 0x0:下一个limage header 的地址偏移量,如果这里填充为0,则表示这是最后一个image header;
  • 0x4:与之相关联的partition header table 的位置偏移量;
  • 0x8:该地址总是0;
  • 0xC:实际分区计数的值;
  • 0x10-N:记录镜像名称。
  • varies:用于填充。

Partition Header Table


image.png

image.png

  • 0x0:加密分区的数据长度;单位是字计算时必须要乘上4;
  • 0x4:未加密分区的数据长度,如该分区是u-boot,则指示了u-boot的长度,计算同上;
  • 0x8:加密+填充+扩展+身份验证的数据总长度;
  • 0xC:该分区数据的加载地址,指的是该分区数据需要拷贝到内存的什么位置;
  • 0x10:该分区数据的运行地址,指运行该分区代码时需要跳转到那个内存地址;
  • 0x14:该分区数据在BOOT.BIN文件中的位置偏移量,拷贝的时候就是从该地址进行拷贝的;
  • 0x18:属性位;
  • 0x1C: Section计数;
  • 0x20:校验和字段的位置;
  • 0x24:该partition header table所对应的 image header所在位置。以 word字为单位;
  • 0x28:加密相关的字段;
  • 0x2C-0x38:未定义;
  • 0x3C:校验和。

references


  1. UG585
  2. UG821


目录
相关文章
|
17天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
18天前
|
Unix Linux Shell
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
在Linux环境下交叉编译Android所需的FFmpeg so库,首先下载`android-ndk-r21e`,然后解压。接着,上传FFmpeg及相关库(如x264、freetype、lame)源码,修改相关sh文件,将`SYSTEM=windows-x86_64`改为`SYSTEM=linux-x86_64`并删除回车符。对x264的configure文件进行修改,然后编译x264。同样编译其他第三方库。设置环境变量`PKG_CONFIG_PATH`,最后在FFmpeg源码目录执行配置、编译和安装命令,生成的so文件复制到App工程指定目录。
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
|
3天前
|
安全 Linux Android开发
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
该文介绍了如何在Linux服务器上交叉编译Android的FFmpeg库以支持HTTPS视频播放。首先,从GitHub下载openssl源码,解压后通过编译脚本`build_openssl.sh`生成64位静态库。接着,更新环境变量加载openssl,并编辑FFmpeg配置脚本`config_ffmpeg_openssl.sh`启用openssl支持。然后,编译安装FFmpeg。最后,将编译好的库文件导入App工程的相应目录,修改视频链接为HTTPS,App即可播放HTTPS在线视频。
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
|
3天前
|
缓存 Linux
linux性能分析之内存分析(free,vmstat,top,ps,pmap等工具使用介绍)
这些工具可以帮助你监视系统的内存使用情况、识别内存泄漏、找到高内存消耗的进程等。根据具体的问题和需求,你可以选择使用其中一个或多个工具来进行内存性能分析。注意,内存分析通常需要综合考虑多个指标和工具的输出,以便更好地理解系统的行为并采取相应的优化措施。
21 6
|
8天前
|
Ubuntu 算法 Linux
嵌入式Linux的学习误区
该文指出了学习嵌入式Linux开发的两个常见误区。一是过分专注于学习桌面或服务器版Linux,而非关注嵌入式开发本身,实际上只需熟悉基本操作即可。二是试图在没有基础的情况下直接阅读Linux内核源代码,这是不切实际的,应先建立基础知识再进行源码学习。文章还提到了在嵌入式系统中获取和处理屏幕数据的示例,包括使用gsnap工具将framebuffer数据转为图像,以及涉及的交叉编译过程。
11 0
|
8天前
|
前端开发 Linux iOS开发
【Flutter前端技术开发专栏】Flutter在桌面应用(Windows/macOS/Linux)的开发实践
【4月更文挑战第30天】Flutter扩展至桌面应用开发,允许开发者用同一代码库构建Windows、macOS和Linux应用,提高效率并保持平台一致性。创建桌面应用需指定目标平台,如`flutter create -t windows my_desktop_app`。开发中注意UI适配、性能优化、系统交互及测试部署。UI适配利用布局组件和`MediaQuery`,性能优化借助`PerformanceLogging`、`Isolate`和`compute`。
【Flutter前端技术开发专栏】Flutter在桌面应用(Windows/macOS/Linux)的开发实践
|
11天前
|
编解码 Linux
FFmpeg开发笔记(十二)Linux环境给FFmpeg集成libopus和libvpx
在《FFmpeg开发实战》一书中,介绍了如何在Linux环境下为FFmpeg集成libopus和libvpx,以支持WebM格式的Opus和VP8/VP9编码。首先,下载并安装libopus。接着,下载并安装libvpx。最后,在FFmpeg源码目录下,重新配置FFmpeg,启用libopus和libvpx,编译并安装。通过`ffmpeg -version`检查版本信息,确认libopus和libvpx已启用。
FFmpeg开发笔记(十二)Linux环境给FFmpeg集成libopus和libvpx
|
11天前
|
编解码 Linux
FFmpeg开发笔记(十)Linux环境给FFmpeg集成vorbis和amr
在Linux环境下,为FFmpeg添加对AAC、MP3、OGG和AMR音频格式的支持,需安装libogg、libvorbis和opencore-amr库。首先,从官方源下载各库的最新源码,如libogg-1.3.5、libvorbis-1.3.7和opencore-amr-0.1.6,然后解压并依次执行`./configure`、`make`和`make install`进行编译安装。接着,在FFmpeg源码目录中,使用`./configure`命令重新配置,并重新编译安装FFmpeg。最后,验证FFmpeg版本信息确认已启用ogg和amr支持。
FFmpeg开发笔记(十)Linux环境给FFmpeg集成vorbis和amr
|
16天前
|
监控 Linux 测试技术
性能分析之Linux系统平均负载案例分析
【4月更文挑战第20天】在上文性能基础之理解Linux系统平均负载和CPU使用率中,我们详细介绍了 Linux 系统平均负载的相关概念,本文我们来做几个案例分析,以达到加深理解。
40 2
性能分析之Linux系统平均负载案例分析