关于ZYNQ搭载嵌入式操作系统

1、ZYNQ启动流程简介

ZYNQ启动系统流程与传统FPGA有所不同,传统FPGA只需要将bin文件或者mcs文件烧写到FLASH中,上电就能自动运行FPGA程序。ZYNQ需要烧写Boot.bin文件(包含fsbl、PS程序、PL程序)。

如图所示,ZYNQ上有一块固定的只读存储器——BootRom,每次开机时都会自动运行其中代码,通过外围引脚配置BootRom的寄存器,可以实现开机启动模式配置。BootRom从配置的存储设备中加载运行FSBL。之后,FSBL会加载uboot,然后u-boot加载操作系统内核运行,并挂载根文件系统。

图1 ZYNQ启动流程

Bit文件加载可以在FSBL后、u-boot后、或者操作系统后。ZYNQ搭载操作系统时需要准备FSBL、uboot和bit文件,系统镜像,以及应用程序。

2、ZYNQ开发简介

2.1 生成FSBL文件

(准备环境:Procise、IAR)

如果使用XILINX的ZYNQ,使用SDK或者VITIS可以生成FSBL文件。如果使用的是复旦微电子FMQL则使用Procise生成FSBL文件。以复旦微电子的FMQL为例介绍。

新建工程,添加bd文件(block design),新增ZYNQ的ip核,根据硬件关系配置相关参数,如nor flash连接管脚、串口管教、时钟、管脚电压以及与PL连接的总线等等。

图2 ZYNQ 7 ip核

图3 ZYNQ 7相关设置示意图

(注意:虽然Procise支持从vivado直接转入bd文件,但经实测,转换过程中会可能出现意想不到的错误发生,建议直接在procise中配置相关参数。)

配置完相关参数后导出硬件,并在IAR中打开FSBL工程。FSBL程序运行可以初始化硬件,包括不限于NOR FLASH、看门狗等,启动后会通过串口打印相关信息。根据打印信息可以查看硬件状态,并用于排故使用。如果打印中断,则根据打印中断位置查看代码运行停止位置即可确定错误发生位置。

编译工程生成FSBL.out文件。

 

图4 FSBL打印信息

 

图5 FSBL打印部分代码

2.2 生成uboot文件

(准备环境:ubuntu、bsp包、procise)

如果使用XILINX的ZYNQ,bsp包可以使用XILINX提供的petalinux,如果使用复旦微电子的FMQL,则使用FMQL-LINUX-SDK。

这里以FMQL-Linux-SDK-20201022版本bsp介绍。

 

图6 FMQL-Linux-SDK目录

FMQL-Linux-SDK包中包含了设备树文件、uboot源码、linux源码(其他几个文件夹内容未作深入了解)。uboot、linux共有一个设备树文件。

2.2.1 生成设备树文件

在2.1节,我们生成了bd文件,并且导出了FSBL工程,在这里我们选择导出设备树工程,工程目录如图7所示。同样编译后后,可以得到设备树文件dts(device tree source),该文件经过设备编译器编译后可以得到目标文件dtb(device tree blob)。需要注意的是,针对国产芯片,设备树内容可能需要适应性修改,这点具体问题具体讨论。以PHY芯片为例,国产的88E1111芯片,需要将mac改成图8所示(主要延长复位延时)。

图8 设备树中gmac内容

 

所以如果需要更改设备树文件,可以按以下几步进行:

  1. 更改bd文件;
  2. 生成fsbl工程和devicetree工程(更改设备树文件需要通过更改FSBL文件);
  3. 在IAR工程中,rebuild all;
  4. 将新的system-top.dts内容复制到FMQL_SDK/device-tree/hw-platform/system-top.dts中,dts文件经过device tree compiler编译后,生成device tree blob文件;
  5. 生成dtb执行命令方法:在FMQL_SDK目录下,打开终端(建议使用bash,并且已经执行source env.sh配置好环境变量),执行命令 ./build.sh --nofpga dtb;之后在images目录下会生成dtb文件。

2.2.2 生成uboot.elf

紧接上一节,得到dtb文件后,在不修改uboot源码情况下可以直接生成可执行文件,在打开的同一个终端不要再次执行source env.sh,否则再次执行后进行后续步骤:

  1. 进入 ./u-boot-2018.07-fmsh       make fmql_common_defconfig 生成配置文件;
  2. make EXT_DTB=../images/system.dtb –j4 执行编译;
  3. 將生成的uboot文件后缀改为.elf,即可得到我们想要的文件。

复旦微电子提供的bsp包已经包含了绝大多数常使用的各种芯片的驱动。但是因为使用国产芯片、或者非标准化芯片(仿88E1111总线控制器),经常会碰到需要对源码进行修改的情况。接下来简要分析下uboot源码,以便理解为什么修改。

2.2.3 uboot源码简析

Uboot工程目录如下图所示,重点关注drivers文件夹、include文件夹、arch文件夹、u-boot文件。

drivers文件夹:包含驱动文件。

include文件夹:包含库文件,其中./include/configs/fmsh-common.h为该工程中默认配置的参数。

arch文件夹:包含芯片架构相关的文件,./arch/arm/下的start.S为入口函数,也是u-boot的stage 1执行代码,之后将简要介绍。

u-boot文件:为编译后生成的文件,可将该文件重命名为u-boot.elf,然后制作BOOT.bin文件。

 

图9 u-boot目录

U-boot分为stage1和stage2两部分。依赖于CPU体系结构的代码(如设备初始化代码等)通常都放在stage1,用汇编语言来实现,而stage2则用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。

Stage1:start.S文件用汇编语言写成,其主要代码部分如下:

(1)定义入口。由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口。

(2)设置异常向量(Exception Vector)。

(3)设置CPU的速度、时钟频率及终端控制寄存器。

(4)初始化内存控制器。

(5)将ROM中的程序复制到RAM中。

(6)初始化堆栈。

(7)转到RAM中执行,该工作可使用指令ldr pc来完成。

Stage2:C语言代码部分,完成如下操作:

(1)调用一系列的初始化函数。

(2)初始化Flash设备。

(3)初始化系统内存分配函数。

(4)初始化相关网络设备,填写IP、MAC地址等。

(5)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。

u-boot有一个重要的概念是环境变量,环境变量存储了u-boot程序运行的重要参数。比如bootcmd为uboot会自动运行的参数,可以配置系统镜像相关参数;Bootdelay为uboot启动系统镜像的等待时间;Bootargs为uboot为操作系统传入的参数。

通过u-boot控制台,通过printenv可以查看目前的变量,setenv可以设置环境变量,saveenv可以保存目前环境变量。保存的环境变量会存入nor flash中。U-boot每次启动时会先从flash中读出环境变量,并判断CRC校验是否正确,如果正确则将该变量存入内存中,之后使用的环境变量都直接从内存中取数,为了快速从内存中读出所需环境变量,u-boot中使用了哈希表。如果u-boot从flash读出环境变量后判断CRC校验错误,则直接舍弃并取出源码中的默认环境变量,放入内存中。

默认环境变量在./include/configs/fmsh-common.h中,后续提供的u-boot为了简化产品出厂调试流程,将这些环境变量直接编译在源码中,避免生产过程中调试人员忘记设置环境变量,导致系统无法启动的情况发生。

2.2.4 关于nor flash若干问题

ZYNQ 7芯片支持启动方式有NOR FALSH和SD卡。需要注意的是,虽然SD卡和emmc的接口使用的都是mmc接口,但是包括XILINX的ZYNQ 7和复旦微电子的FMQL的都不支持EMMC作为启动芯片(底层原理未作了解)。XILINX的ZYNQ MPSOC系列芯片可以支持EMMC芯片启动。

复旦微电子的FMQL芯片支持的nor flash种类有限,厂家推荐使用复旦微自家的nor flash。复旦微提供的flash芯片有仿winbond的flash和仿镁光的flash。尤其需要注意的是作为启动flash使用时,只能使用winbond的id!!!

并且需要修改u-boot中drivers/mtd/spi/spi_flash_ids.c 里的:

 

图11 flash驱动修改部分

即把w25q256的flash擦除块4K大小删除,这样实际使用的擦除块大小为64K大小,猜测应该是该国产flash不支持4K擦除块。

如果有id不识别的情况,则需要使能winbond的id。具体方法如下:

在uboot目录下,输入make menuconfig命令,得到如下图所示的界面。

 

图12 U-Boot Configuration界面

选择Device Drivers--SPI Flash support中选择对应的FLash型号并保存,重新执行配置,并生成u-boot文件,如图13所示。

 

图13 Flash驱动选择

2.2.5 关于PHY驱动

ZYNQ和PHY芯片通信接口包含了mdio接口和RGMII接口,mdio是PHY芯片的管理接口,可以实现对PHY芯片的寄存器进行读和写操作。RGMII接口则是通信数据接口。

  1. boot提供了对PHY芯片寄存器操作接口。如输入mdio list可以查看当前的mdio上的phy芯片,mdio read ADDR 0-1f可以从查看当前PHY芯片的寄存器值。mdio可以实现对PHY芯片的寄存器进行写操作,当然前提是该寄存器是可写寄存器。如图是88E1111芯片在网络连接状态下的寄存器值。

可以看到寄存器0是控制寄存器,值为0x3100;寄存器1是状态寄存器,值为0x796d(注意每次上电第一次读出的寄存器值可能不准确,需重复读一次)。对应88E1111芯片datasheet,如下图所示,可以看出当前状态是100Mbps,并且网络连接状态。

 

图15 88E1111芯片寄存器0部分解析

图16 88E1111芯片寄存器1部分解析

 

如果使用的PHY芯片是非标PHY芯片,如401所的仿88E1111总线控制器,该总线控制器对原有PHY芯片进行了简化,如速度上是不可配置的千兆网,状态寄存器也进行了简化,只保留了几个主要的状态寄存器。所以如果按原有设备驱动,会将所有的状态寄存器都判断正确才认为网络正常的做法肯定是不行的,需要修改,修改驱动路径为./drivers/net/phy/Marvell.c,内容如下图所示。

 

图17 phy驱动修改部分代码

2.2.6 生成BOOT.bin文件

在前面几步已经得到了FSBL文件和u-boot.elf文件,而实际通过JTAG下载到nor flash中的文件是BOOT.bin文件,接下来介绍下生成BOOT.bin文件方法。

对于复旦微电子的FMQL,需要利用procise软件,选择create boot image,然后分别添加FSBL文件和u-boot.elf文件就可以得到BOOT.bin文件。

注意:BOOT.bin文件是可以包含bit文件,但是不建议这么做,因为这样每次修改bit文件都需要重新制作BOOT.bin文件,并且通过JTAG烧写,非常不灵活。并且bit文件一般都在十几兆,通过JTAG烧写时,速度也很慢。

 

图18 BOOT.bin生成截图

2.3 生成bit文件

(准备环境:vivado)

在vivado中生成bd文件,添加ZYNQ7 ip核,并按procise的配置在vivado中重新配置好相关参数。并编写PL端程序,规划好PL与PS采用通信接口。具体关于FPGA的设计,这里不再介绍。需要注意的是,如果使用了AXI通信接口,最好PL端使用PS端输出的时钟,这样能保证PL端主时钟和AXI总线时钟在一个时钟域下。

 

图19 vivado中Bd框图

2.3.1 PL和PS的高速通信接口

从图20可以看出,PL和PS之间的接口包括了EMIO(Extended MIO)、CLK、AXI GP接口、AXI HP接口、AXI ACP接口、DMA接口。

 

图20 ZYNQ原理框图

ZYNQ中有支持三种AXI总线协议,分别为:

AXI4:主要面向高性能地址映射通信的需求,是面向地址映射的接口,允许最大256轮的数据突发传输;

AXI4-Lite:是一个轻量级的地址映射单次传输接口,占用很少的逻辑单元。

AXI4-Stream:面向高速流数据传输;去掉了地址项,允许无限制的数据突发传输规模。

如果进行大数据量通信时,为了降低ARM端的负载,可以使用DMA传输。通过DMA可以实现PL端和DDR3的直接通信,而无需处理器干预。不过需要注意的是,DMA传输时,PS端应用程序需及时刷新L2 cache,防止读出的数据不准确。

2.3.2 关于bit加载的3种方式

ZYNQ 7芯片加载bit文件的方式有3种,分别是fsbl加载bit、u-boot加载bit、操作系统加载bit。

fsbl加载bit的方法是在生成BOOT.bin时,除了包含fsbl和u-boot之外,再将bit文件一并包含在BOOT.bin文件,并通过JTAG将BOOT.bin烧写到flash中。每次开机启动后,fsbl会加载bit和uboot。但是这种方法会导致每次更改bit文件都得重新更新BOOT.bin文件,并通过JTAG烧写,耗时并且繁琐,不推荐这种方法。

u-boot加载bit的方法是在u-boot运行起来后,由u-boot从存储空间中加载bit文件到内存中,然后配置到PL端的过程。该方法可以实现u-boot下使用TFTP传输bit文件,具有速度快的优点,是目前使用的方案。

操作系统加载bit是在操作系统运行起来后,由操作系统加载bit的方法。如果使用的是XILINX的ZYNQ和LINUX系统可以使用xdevcfg驱动实现。如果使用的国产操作系统,则由厂家实现相关功能。该方法最大的好处是可以实现动态加载bit,灵活性极高。

2.3.3 前期快速验证PL和PS接口方法

调试工作前期,在未具备应用程序的情况下,如何快速验证PL端和PS端的通信对验证FPGA程序是否正常工作非常关键。因为AXI总线通信对于PS端来讲只是对应内存数据的更新,所以不管在u-boot环境下还是操作系统环境下,只有能访问内存就可以查看PL端运行状态。

直接在u-boot中查看内存,就可以确认PL发送至PS的数据是否正确;并且修改内存值,观察PL端响应是否是预期效果。U-boot下查看内存命令是md 内存地址,如下图所示,默认使用大端排序,修改内存命令是nm 内存地址。

  • 4
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值