ZYNQ7000 FSBL加载启动代码详解

article/2025/11/8 7:09:35

参考资料:

https://blog.csdn.net/zhaoxinfan/article/details/54958641

https://blog.csdn.net/asmartkiller/article/details/84072643

https://blog.csdn.net/qq_40155300/article/details/89001808

SDK版本:2017.4

写在前面:

该文档不足以使你清楚FSBL启动的寄存器级的操作细节,但可以让你看明白整个ZYNQ7000 FSBL代码执行的主要流程。

1. ZYNQ7000加载启动流程

 

(1)BootRom阶段为ARM上电后最早加载的代码,根据MIO引脚配置确认加载方式,初始化相应的启动介质,加载FSBL到OCM中,把控制权交给FSBL

(2)FSBL阶段完成PS的初始化,加载PL bit流文件,加载SSBL引导程序或者ARM的裸机程序

(3)SSBL阶段分两种情况:①裸机程序直接在DDR中执行②uboot引导加载kernel的过程

 

2. FSBL代码分析

(1)在文件FSBL_bsp/standalone_v6_5/src/asm_ventors.S中,声明了一个代码段,位于地址0处。开机后PS自动执行地址0处的指令,其中第一行代码为一个跳转:B _boot

.org 0
.text.globl _vector_table.section .vectors
_vector_table:B	_bootB	UndefinedB	SVCHandlerB	PrefetchAbortHandlerB	DataAbortHandlerNOP	/* Placeholder for address exception vector*/B	IRQHandlerB	FIQHandler

(2)在同目录下找到文件boot.S中可以看到_boot标号下的代码,_boot会对系统做一系列的初始化,包括DDR,中断,MMU,cache等,执行完成后PS将具有执行C代码的能力。

可以看到在_boot代码最后又执行了一次跳转:b _start

	b	_start				/* jump to C startup code */and	r0, r0, r0			/* no op */

(3)在同目录下找到文件xil-crt0.S中可以看到_start标号下的代码,可以看到_start首先执行跳转:bl __cpu_init去执行CPU初始化操作

_start:bl      __cpu_init		/* Initialize the CPU first (BSP provides this) */mov	r0, #0/* clear sbss */ldr 	r1,.Lsbss_start		/* calculate beginning of the SBSS */ldr	r2,.Lsbss_end		/* calculate end of the SBSS */

(4)在_start标号代码的末尾可以看到bsp完成了所有的初始化工作,将跳转到main函数开始执行。

	/* make sure argc and argv are valid */mov	r0, #0mov	r1, #0/* Let her rip */bl	main

(5)回到FSBL工程,在目录FSBL/src/main.c中找到main函数,可以看到第一步就是调用了ps7_init()函数。

ps7_init()函数位于ps7_init.c文件中,这个C文件是由XPS根据用户的配置自动生成的。

查看ps7_init()函数,根据代码可以很明显可以看出该函数其实就是根据PS版本执行了MIO,PLL,CLK,DDR和其他外设的初始化。

int main(void)
{u32 BootModeRegister = 0;u32 HandoffAddress = 0;u32 Status = XST_SUCCESS;/** PCW initialization for MIO,PLL,CLK and DDR*/Status = ps7_init();if (Status != FSBL_PS7_INIT_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"PS7_INIT_FAIL : %s\r\n",getPS7MessageInfo(Status));OutputStatus(PS7_INIT_FAIL);/** Calling FsblHookFallback instead of Fallback* since, devcfg driver is not yet initialized*/FsblHookFallback();}
int
ps7_init() 
{// Get the PS_VERSION on run timeunsigned long si_ver = ps7GetSiliconVersion ();int ret;//int pcw_ver = 0;if (si_ver == PCW_SILICON_VERSION_1) {ps7_mio_init_data = ps7_mio_init_data_1_0;ps7_pll_init_data = ps7_pll_init_data_1_0;ps7_clock_init_data = ps7_clock_init_data_1_0;ps7_ddr_init_data = ps7_ddr_init_data_1_0;ps7_peripherals_init_data = ps7_peripherals_init_data_1_0;//pcw_ver = 1;} else if (si_ver == PCW_SILICON_VERSION_2) {ps7_mio_init_data = ps7_mio_init_data_2_0;ps7_pll_init_data = ps7_pll_init_data_2_0;ps7_clock_init_data = ps7_clock_init_data_2_0;ps7_ddr_init_data = ps7_ddr_init_data_2_0;ps7_peripherals_init_data = ps7_peripherals_init_data_2_0;//pcw_ver = 2;} else {ps7_mio_init_data = ps7_mio_init_data_3_0;ps7_pll_init_data = ps7_pll_init_data_3_0;ps7_clock_init_data = ps7_clock_init_data_3_0;ps7_ddr_init_data = ps7_ddr_init_data_3_0;ps7_peripherals_init_data = ps7_peripherals_init_data_3_0;//pcw_ver = 3;}// MIO initret = ps7_config (ps7_mio_init_data);  if (ret != PS7_INIT_SUCCESS) return ret;// PLL initret = ps7_config (ps7_pll_init_data); if (ret != PS7_INIT_SUCCESS) return ret;// Clock initret = ps7_config (ps7_clock_init_data);if (ret != PS7_INIT_SUCCESS) return ret;// DDR initret = ps7_config (ps7_ddr_init_data);if (ret != PS7_INIT_SUCCESS) return ret;// Peripherals initret = ps7_config (ps7_peripherals_init_data);if (ret != PS7_INIT_SUCCESS) return ret;//xil_printf ("\n PCW Silicon Version : %d.0", pcw_ver);return PS7_INIT_SUCCESS;
}

(6)System Software Reset,使能系统软件复位功能

/** Unlock SLCR for SLCR register write*/SlcrUnlock();

(7)关闭cache功能

/** Flush the Caches*/Xil_DCacheFlush();/** Disable Data Cache*/Xil_DCacheDisable();

(8)注册异常中断

/** Register the Exception handlers*/RegisterHandlers();

这里相当于异常处理函数全部指向0地址。

Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_UNDEFINED_INT,(Xil_ExceptionHandler)Undef_Handler,(void *) 0);

	XExc_VectorTable[Exception_id].Handler = Handler;XExc_VectorTable[Exception_id].Data = Data;

(9)DDR读写测试,在DDR不同地址段进行读写比对

   /** DDR Read/write test */Status = DDRInitCheck();if (Status == XST_FAILURE) {fsbl_printf(DEBUG_GENERAL,"DDR_INIT_FAIL \r\n");/* Error Handling here */OutputStatus(DDR_INIT_FAIL);/** Calling FsblHookFallback instead of Fallback* since, devcfg driver is not yet initialized*/FsblHookFallback();}

(10)Processor Configuration Access Port即处理器配置接口,连接软件和硬件的桥梁。

	/** PCAP initialization*/Status = InitPcap();if (Status == XST_FAILURE) {fsbl_printf(DEBUG_GENERAL,"PCAP_INIT_FAIL \n\r");OutputStatus(PCAP_INIT_FAIL);/** Calling FsblHookFallback instead of Fallback* since, devcfg driver is not yet initialized*/FsblHookFallback();}fsbl_printf(DEBUG_INFO,"Devcfg driver initialized \r\n");

 

(11)获取PS版本号

/** Get the Silicon Version*/GetSiliconVersion();

(12)获取PCAP接口控制器配置信息,检查是否允许系统复位

	/** Get PCAP controller settings*/PcapCtrlRegVal = XDcfg_GetControlRegister(DcfgInstPtr);/** Check for AES source key*/if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) {/** For E-Fuse AES encryption Watch dog Timer disabled and* User not allowed to do system reset*/
#ifdef	XPAR_XWDTPS_0_BASEADDRfsbl_printf(DEBUG_INFO,"Watchdog Timer Disabled\r\n");XWdtPs_Stop(&Watchdog);
#endiffsbl_printf(DEBUG_INFO,"User not allowed to do ""any system resets\r\n");}

(13)配置FSBL正在执行状态

	/** Store FSBL run state in Reboot Status Register*/MarkFSBLIn();

(14)读取启动模式寄存器,启动模式是通过MIO引脚来配置的,要配置相应的启动模式可以参考下图中MIO各个引脚在不同模式的配置情况

/** Read bootmode register*/BootModeRegister = Xil_In32(BOOT_MODE_REG);BootModeRegister &= BOOT_MODES_MASK;

 

(15)根据启动模式初始化对应的存储设备

QSPI启动

①初始化qspi Flash

②MoveImage = QspiAccess;函数指针赋值,实现从Norflash中拷贝image到内存中

	if (BootModeRegister == QSPI_MODE) {fsbl_printf(DEBUG_GENERAL,"Boot mode is QSPI\n\r");InitQspi();MoveImage = QspiAccess;fsbl_printf(DEBUG_INFO,"QSPI Init Done \r\n");

Norlflash启动

	/** NOR BOOT MODE*/if (BootModeRegister == NOR_FLASH_MODE) {fsbl_printf(DEBUG_GENERAL,"Boot mode is NOR\n\r");/** Boot ROM always initialize the nor at lower speed* This is the chance to put it to an optimum speed for your nor* device*/InitNor();fsbl_printf(DEBUG_INFO,"NOR Init Done \r\n");MoveImage = NorAccess;

JTAG启动

	/** JTAG  BOOT MODE*/if (BootModeRegister == JTAG_MODE) {fsbl_printf(DEBUG_GENERAL,"Boot mode is JTAG\r\n");/** Stop the Watchdog before JTAG handoff*/
#ifdef	XPAR_XWDTPS_0_BASEADDRXWdtPs_Stop(&Watchdog);
#endif/** Clear our mark in reboot status register*/ClearFSBLIn();/** SLCR lock*/SlcrLock();FsblHandoffJtagExit();

(16)FlashReadBaseAddress是在上述流程中根据不同的启动设备进行初始化的。

通常情况下我们使用Norflash启动,InitQspi()函数中会对FlashReadBaseAddress赋值,就是qspi falsh的起始地址为0xFC000000,在zynq7000的数据手册UG585中可以看到。

	/** Check for valid flash address*/if ((FlashReadBaseAddress != XPS_QSPI_LINEAR_BASEADDR) &&(FlashReadBaseAddress != XPS_NAND_BASEADDR) &&(FlashReadBaseAddress != XPS_NOR_BASEADDR) &&(FlashReadBaseAddress != XPS_SDIO0_BASEADDR)) {fsbl_printf(DEBUG_GENERAL,"INVALID_FLASH_ADDRESS \r\n");OutputStatus(INVALID_FLASH_ADDRESS);FsblFallback();}/** NOR and QSPI (parallel) are linear boot devices*/if ((FlashReadBaseAddress == XPS_NOR_BASEADDR)) {fsbl_printf(DEBUG_INFO, "Linear Boot Device\r\n");LinearBootDeviceFlag = 1;}

(17)接下来就是最关键的地方了,这个函数做两件事情①分析烧录到qspi中的数据的头的部分②根据分析结果拷贝数据到DDR中

	/** Load boot image*/HandoffAddress = LoadBootImage();fsbl_printf(DEBUG_INFO,"Handoff Address: 0x%08lx\r\n",HandoffAddress);

(18)我们进入到函数LoadBootImage()中进一步分析代码

这段代码的作用是从multiboot寄存器中读取要执行的image的地址,其实如果就一个image的话可以不用管这个,这个算出来的imagestartaddress一定是0

	/** read the multiboot register*/MultiBootReg =  XDcfg_ReadReg(DcfgInstPtr->Config.BaseAddr,XDCFG_MULTIBOOT_ADDR_OFFSET);fsbl_printf(DEBUG_INFO,"Multiboot Register: 0x%08lx\r\n",MultiBootReg);/** Compute the image start address*/ImageStartAddress = (MultiBootReg & PCAP_MBOOT_REG_REBOOT_OFFSET_MASK)* GOLDEN_IMAGE_OFFSET;

(19)解析Image即BOOT.bin的头信息

①从bootloader中解析出BOOT.bin的大小(这个信息后续未看到有使用)

②把BOOT.bin中header解析出partition header并保存到全局变量PartHeader PartitionHeader[MAX_PARTITION_NUMBER]中,实际有效的只有3个partitions,即FSBL.elf,FPGA.bit,application.elf

③根据解析出的partition header数据解析出partition的数量

	/** Get partitions header information*/Status = GetPartitionHeaderInfo(ImageStartAddress);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "Partition Header Load Failed\r\n");OutputStatus(GET_HEADER_INFO_FAIL);FsblFallback();}

PartHeader为BOOT.bin中解析出的各个partition的Header信息结构体

typedef struct StructPartHeader {u32 ImageWordLen;	/* 0x0 */u32 DataWordLen;	/* 0x4 */u32 PartitionWordLen;	/* 0x8 */u32 LoadAddr;		/* 0xC */u32 ExecAddr;		/* 0x10 */u32 PartitionStart;	/* 0x14 */u32 PartitionAttr;	/* 0x18 */     // 用来判断文件属性,例如FPGA.bit文件或者application.elf文件u32 SectionCount;	/* 0x1C */u32 CheckSumOffset;	/* 0x20 */u32 Pads1[1];u32 ACOffset;	/* 0x28 */u32 Pads2[4];u32 CheckSum;		/* 0x3C */
}PartHeader;

这里需要了解一下BOOT.bin的结构。
在boot.bin中从地址0-0x8BF可以分成17个部分,每个部分都有一定的含义 
1. 0x000  中断向量表 
2. 0x020  固定值 0xaa995566 
3. 0x024  固定值 0x584c4e58  ASCII: XLNX 
4. 0x028  如果是0xa5c3c5a3或者0x3a5c3c5a为加密的 
5. 0x02C  bootrom头版本号,不用管 
6. 0x030  从bootrom开始到app地址的总数(bytes) 
7. 0x034  从loadimage拷到OCM的长度 【上电后BootRom会主动把FSBL拷贝到OCM中执行】
8. 0x038  目的地址到哪儿拷贝FSBL 
9. 0x03C  开始执行的地址 
10. 0x040  同7 【此处代码逻辑中其实是把该字段的值赋给FSBL的size】
11. 0x044  0x01为固定值 
12. 0x048  校验和(从0x020-0x047)按32-bit word 相加取反 
13. 0x04C  bootgen相关 
14. 0x098  image头的表指针 
15. 0x09C  partition头的表指针 
16. 0x0A0  寄存器初始化的参数 
17. 0x8A0  fsbl user defined 
18. 0x8C0  fsbl开始的地方 

(20)拿到partition header后应该分别加载各个partition,但由于第0个partition其实就是FSBL,而我们当前其实已经在FSBL执行中了,所以不用加载直接跳过从partitionNum = 1开始加载

	/** First partition header was ignored by FSBL* As it contain FSBL partition information*/PartitionNum = 1;

(21)接下来开始加载对各个partition是类似的,主要完成两部分工作:

①解析并检查各个partition header中内容的正确性

②从norflash中加载各个partiton到指定的目标地址中。(这里对FPGA.bit和application.elf有所差别)

根据partition header中属性判断当前为bit文件或者application文件

		if (PartitionAttr & ATTRIBUTE_PL_IMAGE_MASK) {fsbl_printf(DEBUG_INFO, "Bitstream\r\n");PLPartitionFlag = 1;PSPartitionFlag = 0;BitstreamFlag = 1;}if (PartitionAttr & ATTRIBUTE_PS_IMAGE_MASK) {fsbl_printf(DEBUG_INFO, "Application\r\n");PSPartitionFlag = 1;PLPartitionFlag = 0;ApplicationFlag = 1;}

该函数搬移partition数据到DDR中

	/** Move partitions from boot device*/Status = PartitionMove(ImageStartAddress, HeaderPtr);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"PARTITION_MOVE_FAIL\r\n");OutputStatus(PARTITION_MOVE_FAIL);FsblFallback();}

FPGA.bit和application.elf文件都是通过下面函数依次搬移传输到DDR中

if ((LinearBootDeviceFlag && PLPartitionFlag &&(SignedPartitionFlag || PartitionChecksumFlag)) ||(LinearBootDeviceFlag && PSPartitionFlag) ||((!LinearBootDeviceFlag) && PSPartitionFlag && SecureTransferFlag)) {/** PL signed partition copied to DDR temporary location* using non-secure PCAP for linear boot device*/if(PLPartitionFlag){SecureTransferFlag = 0;LoadAddr = DDR_TEMP_START_ADDR;}/** Data transfer using PCAP*/Status = PcapDataTransfer((u32*)SourceAddr,(u32*)LoadAddr,ImageWordLen,DataWordLen,SecureTransferFlag);if(Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "PCAP Data Transfer Failed\r\n");return XST_FAILURE;}

(22)如果partition为FPGA bit文件,那么通过以下函数完成从DDR中加载启动bit文件,这个函数中涉及PCAP的操作流程,这里不再深入探究。

/** Load Signed PL partition in Fabric*/if (PLPartitionFlag) {Status = PcapLoadPartition((u32*)PartitionStartAddr,(u32*)PartitionLoadAddr,PartitionImageLength,PartitionDataLength,EncryptedPartitionFlag);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"BITSTREAM_DOWNLOAD_FAIL\r\n");OutputStatus(BITSTREAM_DOWNLOAD_FAIL);FsblFallback();}}

(23)至此函数LoadBootImage全部执行完成,当前已完成FPGA.bit加载,并且application也已经写入到DDR中。

在下面的函数中HandoffAddress应该为application partition header中的执行地址,也是application.elf保存在DDR中的基地址,即0x00100000

	/** FSBL handoff to valid handoff address or* exit in JTAG*/FsblHandoff(HandoffAddress);

在该函数中最后通过FsblHandoffExit(FsblStartAddr)函数实现了FSBL到application.elf的跳转

if(FsblStartAddr == 0) {/** SLCR lock*/SlcrLock();fsbl_printf(DEBUG_INFO,"No Execution Address JTAG handoff \r\n");FsblHandoffJtagExit();} else {fsbl_printf(DEBUG_GENERAL,"SUCCESSFUL_HANDOFF\r\n");OutputStatus(SUCCESSFUL_HANDOFF);FsblHandoffExit(FsblStartAddr);}

在src/fsbl_handoff.S文件中,bx lr指令实现了跳转到application开始执行

FsblHandoffExit:mov	 lr, r0	/* move the destination address into link register */mcr	 15,0,r0,cr7,cr5,0		/* Invalidate Instruction cache */mcr	 15,0,r0,cr7,cr5,6		/* Invalidate branch predictor array */dsbisb					/* make sure it completes */ldr	r4, =0mcr	 15,0,r4,cr1,cr0,0		/* disable the ICache and MMU */isb					/* make sure it completes */bx		lr	/* force the switch, destination should have been in r0 */.Ldone: b		.Ldone					/* Paranoia: we should never get here */
.end

(24)以上FSBL运行加载FPGA.bit和引导application.elf执行过程代码分析全部完成。


http://chatgpt.dhexx.cn/article/PdbEjIGI.shtml

相关文章

xilinx ZYNQ 7000 AXI GPIO

.0AXI GPIO 第一部分 PS 和 PL之间的通讯有一个接口称为AXI。AXI总线具体的内容这边不去深究,可以理解为一种特殊协议的通讯方式。 AXI GPIO是什么意思? PL是FPGA它可以做成任何你想要的东西,做一个GPIO外设当然是可以的。 如上图所示&…

Xilinx ZYNQ 7000 HDMI

High-Definition Multimedia Interface (HDMI) 参考xilinx application note XAPP460 HDMI来自High-Definition Multimedia Interface 高分辨率多媒体接口,多媒体一般包含图像和声音。 Transition Minimized Differential Signaling (TMDS) 是HDMI的物理层。 TMDS…

ZYNQ7000 Uboot编译

使用的板子是闲鱼淘的ebaz4205,petalinux编译工程弄了几天都无法下载linux源码,索性按照官网教程U-boot自己一步步搭建编译环境 uboot版本xlnx_rebase_v2020.01备份的gitee链接https://gitee.com/lign17314/u-boot-xlnx.git交叉编译链gcc-linaro-7.5.0-…

linux系统移植 基于zynq7000平台

目录 1. 准备工作1.1. 新建工作目录1.2. 安装必备库 2. zynq 平台交叉编译器的安装2.1 解压编译环境2.2 在 zynq 目录下编写激活脚本,并激活2.3 测试编译器版本 3. Uboot 编译及制作3.1 Uboot 编译和配置:3.2 生成 boot.bin 4. Linux 内核配置及移植4.1 …

Zynq7000 USB2.0协议解析及USB控制器详解

USB 2.0规范及控制器 文章目录 USB 2.0规范及控制器USB2.0Univerasl Serial BusUSBHost USB总线接口标准总线信号USB拓扑结构数据流模型数据编解码和位填充USB逻辑部件 USB时间基准USB 描述符USB设备USB设备供电方式USB设备分层USB设备插入检测机制USB设备状态USB总线枚举 USB传…

zynq7000开发流程

1 开发工具 1.1 独立开发环境 PL—>Vivado PS(ARM)-->SDK(Xilinx)或者第三方ARM开发工具 1.2 集成开发环境 SDSoC 1.3 总结 独立开发环境大概分为四个步骤: &#xf…

ZYNQ7000 SPI LCD与Petalinux

前言 ZYNQ内部集成两个ARM Cortex A9核心,Xilinx也推出了Petalinux工具,与Vidado搭配可以方便地完成Linux的uboot、kernel、rootfs部署。 开发板上集成了HDMI,但是需要在FPGA中实现逻辑,但是实现之后占用了7010快一半的资源&…

ZYNQ7000 (二十)等精度频率计的原理分析和实例实现

等精度频率计的原理分析和实例实现 这一视频主要来分析实现等精度频率计。通过分析硬件实现原理,编写 PL的逻辑实现部分,以及对应 PS的 C语言操作,操作挂在 PS寻址空间的寄存器, 达到控制等精度频率计逻辑,读取计数结果…

ZYNQ7000-MIO与EMIO详解

摘要 本文参考芯片手册详细介绍了ZYNQ7000芯片的信号、接口与引脚,结合芯片封装说明了引脚的类别与分布,并说明了MIO与EMIO的区别。 关键词:ZYNQ;信号;引脚;MIO;EMIO;Bank 前言 了解…

ZYNQ7000 SDK开发使用

Zynq开发平台工具 ZYNQSDK开发使用 Zynq开发平台工具导入硬件平台配置BSP包创建和配置创建应用程序下载固件和调试应用程序创建FSBL工程建立内存测试工程启动模式spi flash及sd卡的测试 参考文档:zynq_sw\Lab_instructions\Lab01 - Explore Zynq Hardware Platform …

Zynq7000 OPENAMP 实验

前言 Zynq7000 openamp实验,最近想做一个多cpu异构系统,后面会用zynqmp去做,先拿zynq7000试一下 首先说明,openamp是开源异构多处理通信框架。现在cpu不再像以前单个cpu,而是越来越复杂,比如TI的TDA4芯片…

ZYNQ7000固化流程

ZYNQ7000固化流程 生成BOOT.bin文件 (1)在SDK开发环境下,将FSBL.elf文件,FPGA.bit文件和FW.elf文件按次序添加并打包成BOOT.bin文件 2. BOOT.bin文件固化 (1)在xilinx SDK环境中通过JTAG进行固化&#x…

zynq7000 资源介绍

zynq 7000 资源介绍 整体框架PS端资源PS端资源 整体框架 Zynq7000系列是基于APSOC的可拓展处理平台,它的本质特征是将一个双核ARM Cortex-A9处理器和一个可编程的FPGA芯片集成到一个片上系统中。在进行Zynq7000的详细说明前,本节首先对架构的高层模型进…

zynq7000 创建fsbl工程,并打开log

背景:若通过petalinux编译的启动文件,放到sd卡里面(或者flash),上电后串口没有任何log信息;可以考虑搭建fsbl工程。 以2018.3版本为例。 1、把*.hdf文件放到想要创建的文件里面,然后双击“Xil…

ZYNQ7000-GPIO详解

摘要 本文介绍了ZYNQ7000芯片中GPIO的基本概念,分组、功能、控制寄存器、中断设置以及如何在Vitis中配置GPIO。 本文参考:UG585 - Zynq-7000 SoC Technical Reference Manual (v1.12.2) 385~394页–Ch14: General Purpose I/O(GPIO) 关键词&#xff1a…

zynq7000中断系统

7.1环境 这一章节描述了系统级的中断环境以及中断控制器功能。PS端是基于ARM架构的,并且使用了两个Cortex-A9处理器以及型号为pl390的GIC中断控制器。整个中断结构与处理器、可编程逻辑器件(PL)、从外部IO接受到的中断请求有非常紧密的联系。本章节包含了下面这些关…

【ZYNQ】ZYNQ7000 UART 控制器及驱动应用示例

UART 简介 我们在使用 PS 的时候,通常会添加 UART 控制器,用于打印信息和调试代码。除此之外,PS 在和外部设备通信时,也会经常使用串口进行通信。 UART 控制器 UART 控制器是一个全双工异步收发控制器,ZYNQ 内部包含…

Xilinx ZYNQ 7000入门

ZYNQ是Xilinx推出的新一代全可编程片上系统,将处理器的软件可编程性与FPGA的硬件可编程性完美整合。 ZYNQ7020:xc7z020clg400-2 ZYNQ7010:xc7z010clg400-1 组合了一个双核ARM Cortex-A9(PS)处理器和一个传统的…

ZYNQ7000平台介绍

基于ZYNQ7000平台软件开发 ZYNQ7000平台简介 本文介绍ZYNQ7000平台采用Avnet推出的ZedBoard开发板进行讲解,ZedBoard开发板基于Xilinx Zynq-7000 All Programmable Soc,整合了双核Cortex-A9的PS处理单元和PL逻辑单元。 在zynq上,ARM Cortex…

【ZYNQ】ZYNQ7000 全局定时器及其驱动示例

定时器简介 在 ZYNQ 嵌入式系统中,定时器的资源是非常丰富的,每个 Cortex-A9 处理器都有各自独立的 32 位私有定时器和 32 位看门狗定时器,这两个 CPU 同时共享一个 64 位的全局定时器(GT)。 系统框图 全局定时器&am…