03-ZYNQ学习(启动篇)之程序的固化_zynq ps网口-CSDN博客
ZYNQ启动之后,
PS_POR_B 复位引脚置低后,硬件立即对引导带引脚进行采样,并可选择启用 PS 时钟 PLL。然后,PS开始执行片上ROM中的BootROM代码来引导系统。 POR 会重置整个器件,且不保存之前的状态。非 POR 类型复位也会导致 BootROM 执行,但硬件不会对带引脚进行采样。非 POR 复位后,一些寄存器值将被保留,并且器件会了解其之前的安全模式。非 POR 复位包括 PS_SRST_B 引脚和多个内部复位源。
BootROM是APU中运行的第一个软件。 BootROM 在 CPU 0 上执行,而 CPU 1 正在执行等待事件 (WFE) 指令。 BootROM的主要任务是配置系统,将引导映像FSBL/用户代码从引导设备复制到OCM,然后将代码执行分支到OCM。或者,可以在非安全环境中直接从 Quad-SPI 或 NOR 设备执行 FSBL/用户代码。
PS Master 引导设备保存一个或多个引导映像。引导映像由 BootROM 标头和第一阶段引导加载程序 (FSBL) 组成。引导设备还可以保存用于配置 PL 和嵌入式操作系统的比特流,但BootROM 不能访问这些。用于启动的闪存设备可以是 Quad-SPI、NAND、NOR 或 SD 卡。
BootROM 执行流程受引脚设置、BootROM 标头及其发现的系统内容的影响。
BootROM 可以在具有加密 FSBL/用户代码的安全环境或非安全环境中执行。
BootROM 执行后,FSBL/用户代码负责系统,如 UG821、Zynq-7000 All Programmable SoC 软件开发人员指南中所述。
对于开发,系统可以在 JTAG 模式下启动。或者,可以在非安全闪存设备启动后启用 JTAG。
JTAG 始终意味着非安全环境,但它允许访问 CPU 复合体 (APU) 中的 ARM 调试访问端口 (DAP) 控制器和 PL 中的 Xilinx 测试访问端口 (TAP) 控制器。
根据BootModeRegister加载BOOT.BIN(部分)
if (BootModeRegister == SD_MODE) {
fsbl_printf(DEBUG_GENERAL,"Boot mode is SD\r\n");
/*
* SD initialization returns file open error or success
*/
Status = InitSD("BOOT.BIN");
if (Status != XST_SUCCESS) {
fsbl_printf(DEBUG_GENERAL,"SD_INIT_FAIL\r\n");
OutputStatus(SD_INIT_FAIL);
FsblFallback();
}
MoveImage = SDAccess;
fsbl_printf(DEBUG_INFO,"SD Init Done \r\n");
} else
if (BootModeRegister == MMC_MODE) {
fsbl_printf(DEBUG_GENERAL,"Booting Device is MMC\r\n");
/*
* MMC initialization returns file open error or success
*/
Status = InitSD("BOOT.BIN");
if (Status != XST_SUCCESS) {
fsbl_printf(DEBUG_GENERAL,"MMC_INIT_FAIL\r\n");
OutputStatus(SD_INIT_FAIL);
FsblFallback();
}
MoveImage = SDAccess;
fsbl_printf(DEBUG_INFO,"MMC Init Done \r\n");
} else
PS 主引导模式
在主引导模式下,系统从闪存设备引导。这里,BootROM 配置 PS 来访问引导设备,读取引导标头,验证标头,然后通常将 FSBL/用户代码复制到 OCM 内存。
主模式可以是安全或非安全环境。在安全模式下,引导映像始终由 CPU 写入 OCM 存储器。从那里,它被发送(使用 DMA)进出 AES/HMAC 单元以进行解密和身份验证。解密后的启动映像将被写回 OCM 内存,并在 BootROM 完成后执行。本章和第 32 章“设备安全启动”中介绍了安全硬件。
在非安全模式下,BootROM 标头可以指示 PS 直接从支持就地执行选项的 Quad-SPI 或 NOR 启动设备执行启动映像。在其他情况下,FSBL/用户代码被复制到 OCM 内存以供执行。
如果Flash设备中的BootROM头无效,则BootROM会搜索另一个头。标头搜索将继续,直到找到有效的标头或搜索整个范围。 Quad-SPI、NAND 和 NOR 启动模式支持 BootROM 标头搜索。对于 SD 卡启动模式,仅读取一个标头。
JTAG 从启动
在 JTAG 启动模式下,BootROM 执行最少的系统配置并启用 JTAG 接口。
然后,系统进入空闲状态,等待DAP控制器重新启动CPU 0。级联JTAG启动模式循环DAP和TAP控制器,是最常见的JTAG启动模式。独立 JTAG 启动模式将 TAP 控制器连接到 PL JTAG 引脚,并为用户提供时间使用 TAP 控制器配置 PL,以将 DAP 控制器连接到 EMIO JTAG 接口。路径如第 190 页图 6-7 所示。
在非安全主引导模式下,当 PL 启动时,启用 JTAG 接口进行调试
一.BootROM
根据此程序读取的 Boot mode 寄存器来判断是哪一种启动方式(SD card/QSPI Flash/JTAG)。
确定启动方式后,BootROM 从相应的启动设备(SD Card/QSPI Flash)加 载 First Stage Bootloader (FSBL)或 用 户 代 码 到 On Chip Memory(OCM)的 RAM 上,并且将执行权交付给 FSBL,这个被拷贝到片上 RAM 执行的程序就来自用户自设计的BOOT.bin。
利用上位机程序结合已经通过JTAG烧入的BIT文件程序写进Flash中的就是BIN文件。
在线升级之ICAP,ISP,BIN,HEX,MCS_NoNoUnknow的博客-CSDN博客
二.FSBL & BOOT.bin
BOOT.bin 其实就是由 FSBL.elf + 原工程.bit + 原工程.elf 构成(其中原工程.bit 和原工程.elf 在程序编译完成后便已产生 )。
FSBL 可以配置 DDR 存储器和硬件设计过程中所定义的一些外设。
这些器件需要在加载软件应用及配置 PL 之前就初始化完毕。
总结一下 FSBL 的工作内容:
1、 初始化 PS;
2、 如果提供了 BIT 文件,则配置 PL;
3、 加载裸机应用程序到 DDR 中,或者加载 Second-Stage Boot Loader(SSBL);
4、 开始执行裸机应用程序,或者 SSBL。
在线升级之ICAP,ISP,BIN,HEX,MCS_NoNoUnknow的博客-CSDN博客
三.SSBL
这一阶段是可选的,通常 SSBL 就是裸机程序,对于 linux 启动来说就是 uboot 之类的 bootloader。这一阶段也完全由用户控制。
具体操作:
1.配置FSBL程序
Vitis中选择
配置在CPU 1 上启动代码
UG585 6.1.10
CPU 0 负责在CPU 1 上启动代码执行。
BootROM 将CPU 1 置于等待事件模式。没有启用任何功能,仅修改了几个通用寄存器以将其置于等待 WFE 指令的状态。
CPU 0 在 CPU1 上启动应用程序需要少量协议。当CPU 1接收到系统事件时,它立即读取地址0xFFFFFFF0的内容并跳转到该地址。
如果在更新目标地址位置 (0xFFFFFFF0) 之前发出 SEV(系统事件),则 CPU 1 继续处于 WFE (等待事件模式)状态,因为 0xFFFFFFF0 将 WFE 指令的地址作为安全网。如果写入地址 0xFFFFFFF0 的软件无效或指向未初始化的内存,则结果是不可预测的。
CPU 1 上的初始跳转仅支持 ARM-32 ISA 代码。跳转目标不支持 Thumb 和 Thumb-II 代码。这意味着目标地址必须是 32 位对齐的并且必须是有效的 ARM-32 指令。如果不满足这些条件,结果是不可预测的。
CPU 0 在 CPU 1 上启动应用程序的步骤如下:
1. 将 CPU 1 的应用程序地址写入 0xFFFFFFF0。
2. 执行SEV 指令使CPU 1 唤醒并跳转到应用程序。
地址范围 0xFFFFFE00 至 0xFFFFFFF0 被保留,直到第 1 级或以上应用程序完全发挥作用时才可用。在第二个 CPU 成功启动之前对这些区域的任何访问都会导致不可预测的结果。
#define CPU1STARTADR 0xFFFFFFF0
#define CPU1STARTMEM 0x2000000
#define sev() asm(“sev”)
void StartCpu1(void)
{
Xil_Out32(CPU1STARTADR, CPU1STARTMEM);
dmb(); //waits until write has finished
sev();
}
* 这个函数需要在加载完镜像后才可以使用。
/*
* Load boot image
*/
HandoffAddress = LoadBootImage();
fsbl_printf(DEBUG_INFO,"Handoff Address: 0x%08lx\r\n",HandoffAddress);
StartCpu1();
读取指定地址内的地址数值并跳转的函数
static inline void Xil_Out32(UINTPTR Addr, u32 Value)
通过将 32 位 Value 写入指定地址来执行内存位置的输出操作。
参数:
Addr – 包含执行输出操作的地址,也就是CPU1程序开始时读取的地址。
Value – 包含要写入指定地址的 32 位值。
即:
把程序地址写入到CPU1的执行开始地址的位置,让其读取到所写程序的地址并因此跳转到所写程序地址的位置运行程序。
/******************************************************** **************************/
/**
* * @brief 通过写入 * 32 位来执行内存位置的输出操作值到指定的地址。
* * @param Addr 包含执行输出操作的地址
* @param Value 包含要写入指定地址的 32 位值。
* * @返回无。
********************************************************* *****************************/
/*****************************************************************************/
/**
*
* @brief Performs an output operation for a memory location by writing the
* 32 bit Value to the the specified address.
*
* @param Addr contains the address to perform the output operation
* @param Value contains the 32 bit Value to be written at the specified
* address.
*
* @return None.
*
******************************************************************************/
static INLINE void Xil_Out32(UINTPTR Addr, u32 Value)
{
/* write 32 bit value to specified address */
#ifndef ENABLE_SAFETY
volatile u32 *LocalAddr = (volatile u32 *)Addr;
*LocalAddr = Value;
#else
XStl_RegUpdate(Addr, Value);
#endif
}
/******************************************************** ****************************/ 0/** * @brief 该函数设置覆盖 1MB * 内存的部分的内存属性翻译表。
* * @param Addr:需要设置内存属性的32位地址。
* @param attrib:给定内存区域的属性。 xil_mmu.h 包含常用内存属性的定义,可用于此函数。
*
* * @return 无。
* * @note 在更改转换表条目之前不需要禁用 MMU 或 D 缓存。
********************************************************* *****************************/
/*****************************************************************************/
/**
* @brief This function sets the memory attributes for a section covering 1MB
* of memory in the translation table.
*
* @param Addr: 32-bit address for which memory attributes need to be set.
* @param attrib: Attribute for the given memory region. xil_mmu.h contains
* definitions of commonly used memory attributes which can be
* utilized for this function.
*
*
* @return None.
*
* @note The MMU or D-cache does not need to be disabled before changing a
* translation table entry.
*
******************************************************************************/
void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib)
{
u32 *ptr;
u32 section;
section = Addr / 0x100000U;
ptr = &MMUTable;
ptr += section;
if(ptr != NULL) {
*ptr = (Addr & 0xFFF00000U) | attrib;
}
Xil_DCacheFlush();
mtcp(XREG_CP15_INVAL_UTLB_UNLOCKED, 0U);
/* Invalidate all branch predictors */
mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0U);
dsb(); /* ensure completion of the BP and TLB invalidation */
isb(); /* synchronize context on this processor */
}