Zynq-7000 AMP运行模式下的软件切换及多版本固化运行

Zynq平台AMP运行模式下的软件切换及多版本固化运行

1. Zynq双裸核AMP运行环境构建 1

1.1 Zynq架构概要 1

1.2 Zynq启动与配置 2

1.2.1 启动流程概述 3

1.2.2 PS硬件启动阶段 3

1.2.3 PS软件启动阶段 4

1.2.4 启动文件构成 4

1.2.5 启动模式 4

1.2.6 BootROM的执行 5

1.2.7 FSBL或用户代码执行 5

1.2.8 PL启动处理 6

1.2.9 PL配置路径 6

1.2.10 Device Configuration Interface 7

1.2.11 CPU1启动方式 7

1.3 官方FSBL流程 8

1.3.1 FSBL函数说明 8

1.3.2 FSBL流程分析 8

1.4 Zynq双核运行实现 10

1.4.1 AMP基础环境构建 10

1.4.2 代码设计及双核启动 11

2. Zynq复位子系统 14

2.1 Zynq复位系统概述 14

2.2 Zynq软件复位实现多位置启动 16

2.3 Zynq外设复位实现在线程序更新 17

2.3.1 APU复位及重启 17

2.3.2 DDR程序写入 19

Zynq双裸核AMP运行环境构建

Zynq架构概要

同构多核架构 和 异构多核架构

同构多核处理器是指系统中的处理器在结构上是相同的.异构处理器是指系统中的处理器在结构上是不同的,处理器可以是通用处理器也可以是特定专用硬核

Zynq SoC融合两种架构, 两个Crotex-A9的同构多核,
在此基础上存在可编程逻辑单元(PL)组成异构多核系统.

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第1张图片

图 1-1

Zynq-7000 SoC 概览

Application Processor Unit (应用处理单元)中:

  • FPU & NEON Engine : 浮点预算单元 & 矢量加速器;

  • MMU : 内存管理单元;

  • I-Cache & D-Cache : 指令一级缓存 & 数据一级缓存 (各核独立各32KB);

  • L2Cache : 二级缓存 (512KB);

  • OCM : 静态存储器 (区别DDR动态存储器) 片内高速存储器;

    • PS对其访问时间延迟固定且很小,但大于Cache,作为片内唯一高速存储器可以用作处理器的加速算法;

    • OCM空间大小256KB,分192KB +
      64KB两部分,其中192KB部分存在寻址空间底部,编址从0开始,即0x0000_0000 ~
      0x0002_FFFF, 64KB放在最高的寻址空间编址为0xFFFF_0000 ~ 0xFFFF_FFFF;

    • 192KB的空间一般用来运行FSBL,由BOOTROM拷贝FSBL至OCM,同时FSBL可替换为用户程序,这也就是Zynq的无DDR启动的实现方式,可实现低功耗;

    • 64KB的空间一般作为系统特殊编址,例如0xFFFF_FFF0是作为存储CPU1的程序启动地址来使用;

  • System level control regs:
    系统级别控制器,功能多样,多用于外设的状态控制模式控制,在本例程中将使用CPU复位寄存器等功能;

Memery interface:
DDR接口,在本例程中DDR除了作为运行空间外,也可在当双核需要较大的数据交换是作为共享内存使用,即共享内存并不局限与OCM.

Zynq启动与配置

总来讲,Zynq的启动主要分为3个阶段:

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第2张图片

图 1-2 Zynq启动三阶段

启动流程概述

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第3张图片

图 1-3 PS\PL Boot Process for handware anf Software

  1. BootRom and Header Parameters

    BootRom header包含引导BootRom执行流的一系列参数.

    注:头部包含定义BootRom装载进OCM的FSBL用户代码镜像长度参数,代码长度必须限制在192KB之间,因为OCM
    = 256KB = 192KB + 64KB.

  2. PL Initialization and Configuration

    阐述PL启动和PS之间的关系,
    PL在配置bit流和初始化之前必须上电,PL上电和初启阶段独立于PS运行,但是PL上电需要维持同PS上电复位信号之间的一个定时关系;

    PL受控于FSBL/USER使用GPIO或者连续的外部接口驱动,
    BootRom和FSBL\User代码可以决定PL的上电状态,FSBL\User代码在PL状态改变时可以接收一个中断;

    PL Boot 包含4个阶段: 启动,初始化,配置,使能.

PS硬件启动阶段

Ps硬件启动阶段包括电源上升,时钟,复位,引脚约束采样以及PLL(锁相环)

  1. External PS Control Pins

    这一步是对启动模式的采样,决定PS以哪种方式进行启动,上电复位信号产生等等,

  2. PS PLL Initialization

    6号MIO使能PLL.

    使能PLL后,BoorRom执行流需要延迟至PLL输出时钟.

    如未使能PLL,PS_CLK参考时钟输入引脚绕过PLL.时钟子系统工作在PS_CLK的输入频率.

PS软件启动阶段

PS软件启动受控于BootRom之后是FSBL\User代码. BootROM代码受启动约束引脚, BootROM
头部,以及系统内BootROMdiamante检测影响.

  1. Stage 0(BootROM:BootROM Header)

    BootROM在上电复位\系统级复位(PS_SRST_B,debug,看门狗,软件)之后由主CPU(CPU0)执行.
    BootROM从固化装置读取BootROM头部程序去决定boot流和跳转stage1;

    在硬件引导之后, 两个CPU开始从本地地址0x0(BootROM的初始位置)
    执行相同的BootROM代码来确认自己的身份;

    注意: 单核设备包含一个处理器.
    双核设备包含两个,CPU1执行到WFE命令时进入WFE模式等待触发启动,
    CPU0继续执行BootROM

  2. Stage 1(FSBL \ User Code)

    参考[ug821](file:///F:\资料\zynq\技术手册\官方文档\ug821-zynq-7000-swdev.pdf),这个阶段很灵活.
    可以使用官方的fsbl工程,也可以是自己的用户代码;

  3. Stage 2(U-Boot \ System \ Application)

系统软件,也可称之为SsBL,这一阶段同样受控于用户,具体设计参考[ug821](file:///F:\资料\zynq\技术手册\官方文档\ug821-zynq-7000-swdev.pdf),

启动文件构成

Boot Device可以存储多个组件和多个版本的组件:

  • BootROM header(BootROM需要)

  • FSBL\User 代码 elf 文件 (BootROM需要)

  • PL bitstraem(BootROM不访问)

  • System / Application elf 文件(BootROM不访问)

启动模式

启动模式包括四种主启动模式和两种JTAG从启动模式

  1. Flash设备 (主启动模式)

    当从flash存储器启动一个系统boots,这种方式成为主模式启动.主要有以下几种方式:

  • Quad-SPI (就地执行模式)

  • SD 卡

  • NAND flash

  • NOR flash(可选的就地执行模式)

  1. JTAG(从启动模式)

    JTAG模式被称为从模式启动,同时TJAG模式是非安全的引导模式.

    JTAG链可以级联配置,也可以单独配置.

    顺序启动期间,根据MIO[2]启动引脚的设置来设置链,正常情况下系统配置为级联模式.
    当TRM指向JTAG启动模式时,无特殊说明的情况下都是级联模式,同时JTAG接口在非安全启动模式中都是使能的.

  • 级联 JTAG链 (最受欢迎)

    • 通过PL JTAG访问DAP和TAP控制器
  • 独立 JTAG链(通用):

    • 通过PL JTAG访问TAP控制器

    • 在配置PL完成后通过EMIO JTAG经由 SelectIO 引脚访问DAP控制器

  • 独立 JTAG链(很少用)

    • 通过PL JTAG访问TAP控制器

    • 通过MIO PJTAG访问DAP控制器

BootROM的执行

BootROM在POR或者non-POR复位之后很快开始执行,
一个POR复位会触发硬件启动阶段然后BootROM会开始执行,
一个non-reset会跳过硬件启动阶段立即执行BootROM.

BootROM执行片上内存代码用来执行系统引导过程.当执行转移FSBL\User代码完毕之前BooROM禁止一切接入ROM代码.

初始BootROM执行时,会启动APU并进行一些自检.它会读取Boot启动模式信息,如果非JTAG启动,BootROM会配置相应的启动模式控制器.之后进一步读取BootROM头部配置系统以满足所需的启动过程.

除了BootRom 头部 之外,boot device 还提供FSBL和(or)
用户代码用来在BootROM执行完毕之后接管系统控制.

  1. Secure Boot

    启动运行BootROM
    Header的配置决定BootROM运行在安全模式或者非安全模式.在安全模式下,FSBL/
    User代码会从flash搬运,解密并写入OCM,然后CPU从OCM执行代码.

    如果系统是从安全模式下启动而随后BootROM
    Header的复位信号不是来自POR复位这就表明这是非安全启动,整个系统会进行安全锁止并抛出0x201A错误码.

  2. BootROM Header Search

    当BootORM没有探测到一个有效的BootROM
    Header,此时BootROM会执行一个搜索函数去寻找另一个BootROM
    Header,BootROM头搜索支持 Q-SPI,NAND和NOR引导模式.

    BootROM Header从不加密,搜索函数同加密的(不加密)FSBL \ User
    代码镜像一起工作.

  3. BootROM Execution Influencers

    影响BootROm的主要有以下几个情况:

  • 引脚约束

  • 复位引脚

  • 有效的BootROM(头寻找的和校验)

  • BootROM Header 启动模式以及锁止码原因的冲突.

  1. Error Detction,Device Lockdown and Erroe Codes

    当BootROM
    Header执行过程中,BootROM探测到一个错误,就会对系统进行锁止并生成一个错误码,
    通常有两种锁止类型:

  • 安全锁止(不能访问设备, 需要一个POR重启整个系统)

  • 非安全锁止 (JTAG可能是使能的,并且任何系统复位都能使BootROM继续运行

    当发生系统锁止,错误码会被写进 SCLR.REBOOT_STATUS 寄存器

FSBL或用户代码执行

用户代码可以根据需求重配置PS或者随意配置PL.在就地执行选项未使能的情况下BootROM默认会将FSBL\User
代码装载进OCM.

Fsbl \ User代码执行如下:

  • 使用Vivado 工具生成的PS7 初始化数据 初始化PS (MIO,DDR, etc.)

  • 使用bit流文件配置PL

  • 装载第二阶段启动bootloader 或者在DDR裸跑应用程序

  • 第二阶段启动bootloader 或 裸跑应用程序获取系统控制权

  1. FSBL Image FallBack and Multiboot

    如果FSBL检测到一个错误或者想使用一个不同的FSBL镜像,可以devcfg.MULTIBOOT_ADDR
    [MULTIBOOT_ADDR] 域写
    boot域地址并执行一次软件系统复位.可以参考[ug821](file:///F:\资料\zynq\技术手册\官方文档\ug821-zynq-7000-swdev.pdf).

PL启动处理

PL引导进程包括 启动,初始化, 配置, 使能

  • 启动(对PL进行上电)

  • 初始化(使用 PS软件 或者 INIT\PROGRAM 控制引脚)

  • 配置 (途径有PS PACP, JTAG, PL ICAP)

  • 使能PS-PL接口 (使用PS软件)

PL配置路径

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第4张图片

图 1-4 PL Configuratin paths

PL在安全或非安全模式下可以通过PS软件来实现配置或者重配置.

PCAP方式是最常用的部署方式,因为它不需要使用bit文件对PL进行预编程.

PL同样可以由JTAG链上的TAP控制器配置为非安全模式.

在PL配置模块中数据路径的多路复用使用devc.CTRL [PCAP_MODE] and [PCAP_PR]
比特位完成.

  • 使用TAP控制器(开发常用)

    • 非安全模式

    • 通过TAP控制器初始化和配置PL

  • PS PCAP路径 (部署常用)

    • 安全模式或者非安全模式

    • 由device configuration interface (Devc) 初始化和配置PL

  • ICAP 路径 (不常用)

    • 安全或非安全模式

    • 仅通过PL中实例化的逻辑进行重新配置

Device Configuration Interface

此模块简称 DEVC

包括3个逻辑初始化模块,在PS软件模式下配置PL控制器
(PCAP路径),管理设备安全性,访问XADC.同时为这3个主要功能模块提供一系列控制\状态寄存器.

  • PS软件使用带有DMA的PCAP桥来配置PL和解密镜像,它提供了PS软件到PL配置模块的路径:

    • 解密一个安全的FSBL\User代码

    • 处理一个安全或者非安全的 PL比特流; 同时下载或者上传

    • 根据需要处理PL比特流压缩命令

  • 安全管理模块监控系统活动,维护安全的运行环境

    • 基本的设备安全管理

    • 加强系统级安全性,包括调试控制

  • XADC接口为PS软件访问模数转换器提供途径

    • 串行接口(serial interface)

    • 报警或过热中断

图 1-Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第5张图片
5 Devc Block Digram

CPU1启动方式

WFE状态 (wait for event)是CPU1的一个重要状态,AMP模式下.CPU
0的职责在于在CPU1上启动任务.在CPU 0引导启动过程中,BootRom 会将CPU1置为WFE模式,
此时CPU1没有使能任何进程,只对少数几个通用寄存器进行了修改.

CPU0需要少量协议才能在CPU1上启动应用程序,当CPU1接收系统事件,会立即读0xFFFFFFF0并跳转至其内容中的地址以运行程序.如果系统触发事件在更新目的地址之前发出则CPU1会继续保持在WFE模式,因为0xFFFFFFF0有WFE指定的地址作为安全网络.如果写入0xFFFFFFF0的地址为无效的或者未初始化地址,这将是未定义行为.

只有ARM-32 ISA代码支持CPU1内的初始化跳转,在跳转目标地址不支持Thumb 和Thumb
-Ⅱ代码.这就意味着目标地址必须是32bit位并且必须是一个有效的ARM-32指令.否则为未定义行为.

CPU0 在 CPU1 上启动应用程序的步骤如下:

  1. 向0xFFFFFFF0写入应用启动程序地址

  2. 执行SEV命令已触发启动CPU1并且跳转至应用程序.

0xFFFFFF00 ~
0xFFFFFFF0地址范围是保留的,在第一阶段启动和以上应用程序未完全执行前不能使用,在CPU1成功启动之前访问这个区域的任何行为都可能导致未定义行为

官方FSBL流程

FSBL函数说明

表 11 Xilinx官方FSBL函数

函数 功能 备注
ps7_init() 初始化必要的通用寄存器以及外设\时钟等 (PCW initialization for MIO,PLL,CLK and DDR)
SlcrUnlock(); Unlock SLCR for SLCR register write (system level control register)
Xil_DCacheFlush(); 把cache里的数据压入相应存储器 Xil_DCacheInvalidate() 从OCM等更新Cache
Xil_DCacheDisable(); 关闭数据cache 哈佛架构,存在指令cache和数据cache
RegisterHandlers(); 注册异常处理函数 N\A
DDRInitCheck(); DDR检测 最基础最简单的测试
InitPcap(); PACP桥初始化 N\A
XDcfg_GetControlRegister(); 设置PACP控制寄存器 之后会检查AES的源秘钥
MarkFSBLIn(); This function sets FSBL is running mask in reboot status register Store FSBL run state in Reboot Status Register
Xil_In32(BOOT_MODE_REG); 读取启动模式寄存器 对取值进行判断确定启动模式

上表列出了官方FSBL的几个主要的功能函数, 如图
16所示,Xilinx的FSBL执行流程,从其中可以看到官方FSBL会对芯片功能进行一个简单的检测,初始化,以及启动镜像的装载等工作.

FSBL流程分析

在Zynq启动的启动章节谈到FSBL阶段可以修改Xilinx的模板,理论上甚至可以完全替换为用户程序,但是这种操作方式经过试验,是对用户代码有一定要求的.首先用户代码肯定要限定在192KB大小,这个大小可以在SDK的编译完成后的Console窗口查看.其次,必须存在初始化以及装载等必要的函数调用,这个根据工程特性而变,必须满足运行的一切硬件条件,就本例程而言,将FSBL程序替换为hello
world程序后会出现不能顺利固化的情况.所以说最好的建议是在官方FSBL的基础上做功能性的修改或功能添加,比如官方的DDR检测就是很简单可以说毫无作用的检测,工程中可以替换为更加高效的DDR检测方式.

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第6张图片

图 1-6: Xilinx FSBL 函数执行流程

Zynq双核运行实现

AMP基础环境构建

AMP双核工程基于70Z45核心板平台实现,在完成相应的硬件设计后启动SDK开始实现软件设计.

Step1:如图 17创建两个不同processor的empty
application,命名以cpu0_controller和cpu1_slaver为例.
Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第7张图片

图 17 AMP模式step 1

Step2: 如图
18修改两个工程的运行内存空间,即修改lscript.ld中ps_ddr_0的内存地址,可以自由设置运行空间,只需要不超出物理内存大小且两工程不存在重叠即可.

同时默认共享内存空间为ps7_ram_1,代码设计时只需对这个地址按需命名即可.
如果需要大量数据交互的情况需要自行add memory,在之后的代码设计时做好约定即可.
Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第8张图片

图 18 AMP模式step 2

Step3: 如图 19在cpu1_slaver工程的 bsp
中要增加编译选项“-DUSE_AMP=1”,该编译选项将影响到
cpu1_slaver工程代码里中断控制器 SCUGIC 的初始化函数以及 Cache 操作函数的编译,
若不增加该选项,可能会出现 cpu0_controller 和 cpu1_slaver中断异常和 Cache
一致性维护异常。
Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第9张图片

图 19 AMP模式step3

完成这一步就可以进行代码编写及调试.

代码设计及双核启动

双核AMP的基本架构同单核的区别在于单核可以直接进行代码的编写,而双核需要进行一些固定的代码支持才能够正常的运行.首先是主核即cpu0对cpu1的启动代码,其次是双核之间的数据通信.

双核AMP的软件设计要贯彻一个思想就是规避冲突,要充分理解双核各自的私有资源和公共资源,避免因为资源的访问冲突而导致逻辑错误.如果程序的功能复杂,可以考虑软件中断实现互斥,所谓互斥就是对共享数据的状态改变通过中断触发的方式进行访问,保证同一时间只有一个CPU对某个空间进行读写操作.

  1. 双核间数据通讯

中断互斥只是为了更好的提高程序的健壮性,但是无论是否使用中断,双核之间的数据传递都是通过共享内存的方式实现,大多数情况下双核传递的数据多是指针数据,数据量不会很大,所以本例程选用速度更快的OCM空间为共享内存,当然也可约定一块DDR空间.

所谓共享内存就是, CORE0 和 CORE1
在内存空间中约定一块地址及长度已知的内存区域。然后,两者之间便可通过这片区域进行数据的传递.

ZYNQ 中存在 ICache 和 DCache, ICache 用于缓存可执行程序, DCache 用于缓存数据。
一般情况下, 用于保存可执行程序的 DDR 地址范围不会被除 CPU 以外的对象访问. 因此,
一般不存在 ICache 的一致性问题. 而 DCache在很多应用中却经常会被除 CPU
以外的对象访问,所以存在一致性问题.

两个核心各自拥有独立的 L1 DCache, 并且共享同一个 L2 DCache, Snoop Control
Unit(SCU)用于维护 CORE0 和 CORE1 的 L1 DCache 与 L2 DCache
之间的一致性,无需用户干预.因此,当共享内存区域位于DDR
中时,两者之间的数据传递并不需要考虑 DCache
一致性的维护。当使用OCM时特别是使用轮询的方式去访问共享内存空间Cache的数据一致性问题就特别重要,如不进行数据一致性维护基本上数据传输不会成功.

Zynq中维护 DCache 一致性的方法为:

  • 写入方将数据写入共享空间对应地址区域后,需将残留在 DCache
    中相应地址范围内的数据全部flush。读取方在从共享空间相应地址读取数据之前,需将
    DCache 中共享空间相应地址范围内的数据全部设置为 invalid,然后 CPU 会再次通过
    DCache 从 DDR3中读取该地址范围内最新的数据。具体的操作函数见表 11.

  • 直接禁用OCM的cache属性

DCache 一致性维护的原理为:在多级存储器结构中, CPU 通过 1 级或多级 Cache 与 DDR
产生连接, CPU 本身不直接访问 DDR, 而是通过 Cache 访问 DDR。 Cache
中始终会暂存一小部分(通常是 KB~几 MB 量级) CPU 最近访问的 DDR
某些地址区域中的数据。因此,在应用程序中对 DDR 进行读或写操作, 实际上都是 CPU
对 Cache进行读或写操作。当 DDR 中某个地址范围内的数据突然被除 CPU 以外的
Master(如 DMA)改变时, 若此时 Cache中保存了这些区域的数据,且这些数据在 Cache
中状态为有效时,当 CPU 需要再次读取 DDR 这片区域的数据时,就不会让 Cache 去读取
DDR 中此区域内最新的数据来更新 Cache, 再从 Cache 里读取最新的数据, 而是直接从
Cache中读取原来的旧数据, 显然这不是期望的结果. 这时, 便产生了所谓的 Cache
一致性问题.

  1. 双核BOOT

如章节1.2.11所阐述的,双核运行中cpu0是作为主核的状态存在 ,
cpu1默认处于休眠状态,需要按照以下步骤对cpu1进行唤醒:

  • 确保 CPU1 的程序已经装入到存储器指定地址,并将这个地址(32bit)写入到
    0xFFFF_FFF0 地址。

  • 确保第一步的地址写入 OCM 生效.这时就需要进行cache数据一致性管理,可以关闭
    DCACHE 对 OCM 的缓存,也可以flush 一下 DCACHE.

  • 调用ARM指令集的SEV 指令,唤醒 CPU1.

    具体实现方式如图 110参数为cpu1的运行地址,即在lscript.ld中设置的地址

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第10张图片

图 110 cpu1唤醒函数

在cpu0_controller工程的main函数中调用上述函数即可.之后分别对双核的程序进行简单的验证设计就可以生成可执行bin文件.新建fsbl工程后与单核不同,需要4份文件生成bin,在boot
image partitions 最后追加cpu1_salver的elf文件, 由于elf文件本身含有地址信息
BOOTGEN 会自动识别出来,所以不需要指定拷贝到 DDR3
的目的地址。且固化启动时如不进行cpu1的唤醒,只会执行cpu0的用户程序.具体见图 111.

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第11张图片

图 111 生成双核bin文件.

  1. 在线调试

开发过程中不需要固化时,在JTAG模式下可以使用如图
112的方式进行下载,此时双核程序会同时运行,注意勾选项.
Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第12张图片

图 112 双核JTAG下载

Zynq复位子系统

Zynq复位系统概述

  • 设备安全系统的一个组成部分

  • 执行三级序列 : 上电, 存储器清除 , 系统使能

  • 复位系统包括 : 硬件复位 \ 看门狗复位 \ JTAG控制器复位 \ 软件复位;

  • Zynq每个模块和系统包含复位系统产生的一个复位;

  • 硬件复位由上电复位信号PS_POR_B信号和系统复位信号PS_SRST_B信号驱动;

  • PS内产生复位信号的为3个看门狗定时器;

  • JTAG控制器所产生的复位只能复位PS的调试部分和一个系统级的复位;

  • 软件能独立产生每个模块的复位或一个系统级的复位;

图 2-Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第13张图片
1 复位系统结构图

PS内主要复位信号之间的关系如图 22

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第14张图片

图 2-2 复位子系统层次图

上电复位流程如

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第15张图片

图 2-3 上电复位流程图

当上电复位后,
由外部系统和PS逻辑所控制的前两部开始相应,当PS可以开始工作后,在上电复位后可以产生任何类型的复位,这些复位可以插入到流程图.

  • 能异步的确认或使上电无效. 当上电复位后,
    有条件的允许它干净的传播到时钟模块输入逻辑.
    并且如果使能的话,连接到PLL时钟电路

  • 存在一个BOOT_MODE引脚,用于使能或者旁路所有PLL.

  • eFUSE 控制器脱离复位, 会自动将一些数据应用到PLL,
    这样可以改善性能,并且为PS内的一些RAM提供冗余信息. 用户不可见且不可操作.
    完成时间控制在50~100us内

  • 如果使能PLL,则延迟上电复位信号, 直到锁定PLL. 设置PLL时钟将花费60us

  • 如果选择旁路PLL,则不延迟上电复位信号.

  • 在开始执行BootROM前,通过将 0 写入到所有的地址来清除内部的RAM

各类复位复位结果如下:

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第16张图片

Zynq系统软件复位实现多位置启动

本节将会在Zynq的AMP模式下使用系统软件复位的方式完成多版本bin应用的切换.
多版本不断电切换的完成依赖于章节1.2.7
中提及的multiboot,本质上来说这是一种通用的版本切换方式,可应用于远程版本升级,自检跳转等应用场景.本例程在AMP模式下做一个简单的实现.

关于multiboot的详细说明可以参考ug585的6.3.11和ug821,重点关注gloden image
search和FSBL fallback.
基本原理是当触发软件复位时,Zynq会读取multiboot寄存器值,这个值*32KB即为程序存储的偏移地址,然后在此位置boot.
Multiboot寄存器的值只能通过上电清除.

涉及寄存器:

slcr->REBOOT_STATUS和devcfg->XDCFG_MULTIBOOT_ADDR_OFFSET

multiboot的使用步骤如下:

  • 确定固化器件的编码地址,这个地址32KB对齐

  • 将bin文件写入固化期间,同样需要32KB对齐,同时将头部地址写入devcfg.MULTIBOOT_ADDR
    [MULTIBOOT_ADDR]寄存器,这个头部地址需要进行计算,按照以写入5M的位置为例:

5MB -> 0x50_0000 -> addr = 0x50_0000 / 0x8000 = 0xA0

  • 通过写slcr.PSS_RST_CTRL [SOFT_RST] 寄存器位完成一次系统软件复位.

执行完上述流程就可以完成程序的切换,在本例程中要注意cpu1的启动问题,需要切换的bin文件的elf文件不能单独为cpu1.原因在于cpu1默认为静默的,如果不存在唤醒程序,在执行完复位后cpu1不会启动,系统只会对PL进行重新的启动.

需要注意SLCR和DEVCFG在读写前都需先unlock.具体的实现方式如图 2-4,

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第17张图片

图 2-4 multiboot实现

Zynq外设软件复位实现在线程序更新

由图
21可以看到,Zynq的外设复位由软件复位产生,双核AMP模式下要完成在cpu0不停机的情况下cpu1的程序更新,整体思路就是把cpu1当成一种外设,由cpu0作为主控,通过cpu0复位cpu1,cpu1复位后将其运行空间的程序进行替换,也就是擦掉DDR原有程序,直接写入替换程序,之后重新启动cpu1即可完成程序的替换.替换程序的来源不限,可以通过网口实时导入,也可从flash等空间读取.

APU复位及重启

因为两个cortex-A9同属APU,那么cpu1的复位实际上是APU的复位,原因在于所谓APU(application
processing
unit)的主要组成为cpu.Xilinx为APU复位提供上电复位,系统复位,软件复位,debug复位和系统degbug复位.

本功能的实现依赖于软件复位,与系统复位和上电复位不同,当需要对双核的某个处理器应用进行复位时,必须先停止相关的时钟,断言复位,然后重启时钟.
当然系统复位和上电复位也是需要类似的操作,但是此时硬件会自动的处理这个问题.
因此,需要复位的cpu不能运行复位代码,即不能自己复位自己,这也是采用cpu0复位cpu1的原因,这个控制也可以是PL或者JTAG.以复位cpu0为例:

按步骤注册sclr. A9_CPU_RST_CTRL的字段

  • A9_RST0 = 1 to assert reset to cpu0

  • A9_CLKSTOP0 = 1 to stop clock to cpu0

  • A9_RST0 = 0 to release reset to cpu0

  • A9_CLKSTOP0 = 0 to restart clock to cpu0

    执行复位后的状态如表 2-1所示

表 2-1 APU复位后状态表

Function State after Reset
CPU1 在执行0xFFFFFE00~0xFFFFFFF0的代码保持在WFE状态
L1 缓存 禁用
MMU 禁用
SCU 禁用
地址过滤 1M 到4G的地址空间被映射到OCM,其余空间路由到L2cache
L2cache Disabled
L2等待状态 Tag RAM and Data RAM 等待在可读可写可执行,读写访问延迟
L2生效 未知(再次使用前确认)

由上表可知,在执行完A9的外设复位后,等待在WFE状态的前提是必须是0xFFFFFE00~0xFFFFFFF0区间的代码,这一点与system
software reset不同,system software
reset是会直接加载0x00出的FSBL代码,由bsp中的boot.s进行cpu
ID识别和代码跳转,很显然,我们的需求是不可能重新引导FSBL且此时也并不会加载FSBL,所以如果无论使用那个cpu作为主控,复位cpu都不会自动进入WFE(wait
for event),此时就需要手动进入WFE模式.

手动进入即参考上电复位方式,上电复位时bootrom会使cpu1进入WFE模式,之后不断查询0xFFFF_FFF0处是否为0,不为0即是该地址存储内容即是cpu1的执行地址,启动跳转至该地址执行用户代码.所以需要实现在cpu1
reset后的0x00地址的跳转,目的在于使cpu1进入WFE模式.实现检查并跳转的代码如下:

Xil_Out32(0xFFFFFF00,0xE3E0000F);

Xil_Out32(0xFFFFFF04,0xE3A01000);

Xil_Out32(0xFFFFFF08,0xE5801000);

Xil_Out32(0xFFFFFF0C,0xE320F002);

Xil_Out32(0xFFFFFF10,0xE5902000);

Xil_Out32(0xFFFFFF14,0xE1520001);

Xil_Out32(0xFFFFFF18,0x0AFFFFFB);

Xil_Out32(0xFFFFFF1C,0xE1A0F002);

//向0x00写入跳转代码指向0xFFFFFFF0

Xil_Out32(0x00000000,0xE3E0F0FF);

//清0xFFFFFFF0

Xil_Out32(0xFFFFFFF0,0x00000000);

dmb();

结合复位和重启两个模块就可以实现cpu0对cpu1的控制,做到cpu0不停机的情况下不断重启cpu1.具体实现方式如下:
Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第18张图片

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第19张图片

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第20张图片

DDR程序写入

当成功执行cpu1的复位和重启后,可以得到cpu1随着cpu0进程执行不断重新执行用户程序,而需要完成程序的更新还需要完成重要的一步:
新程序的写入,由上一步可知,cpu1在在复位后会向0xFFFF_FFF0写入cpu1的执行地址,本例程为0x1F50_0000,这就意味至只需要将真正的可执行代码放入0x1F50_0000即可.

至此,只要的到真正的可执行文件就可以,经过对多版本的bin文件的比对,可以得到bin文件的一个特征,bin文件的头部为0x0~0x16FF,所有的bin文件0x1700的位置都是0x4900EA,通过对正在执行的cpu1用户程序的0x1F50_0000进行读取该值也为0x4900EA,所以大胆推测真正的可执行程序从0x1700开始,制作只包含cpu1_application.elf的bin文件,将其按照如下规则写入DDR(以本工程为例)
:

  • 计算写入地址, write_addr = 0x1F50_0000 – 0x1700 = 0x1F4F_E900

  • 写入长度 : cpu1_application.bin= 0x11710

  • 使用SDK dump/restore memory工具按照前两步参数将cpu1_application.bin写入DDR

Zynq-7000 AMP运行模式下的软件切换及多版本固化运行_第21张图片

图 2-5 刷写DDR

在双核程序运行时刷写,刷写后执行复位重启,即可完成cpu0不停机更新cpu1应用版本.

你可能感兴趣的:(FPGA-ZYNQ,zynq)