如何在Zynq-7000上烧写PL Image

如何在Zynq-7000上烧写PL Image,第1张

在Zynq-7000上编程PL大致有3种方法: 1. 用FSBL,将bitstream集成到boot.bin中 2. 用U-BOOT命令 3. 在Linux下用xdevcfg驱动。步骤: 1. 去掉bitstream的文件头用FSBL烧写PL Images没有什么好说的,用Xilinx SDK的Create Boot Image工具即可完成,不再赘述。用后两种方法需要把bitstream文件的文件头用bootgen工具去掉。一个典型的bif文件如下所示: the_ROM_image: { [bootloader]<fsbl_name>.elf <pl_bitstream_name>.bit <u-boot_name>.elf } bif文件可以用文本编辑器写,也可以用Xilinx SDK的Create Boot Image工具生成。然后在命令行下用以下命令即可去掉bitstream文件的文件头。 bootgen -image <bootimage>.bif -split bin -o i BOOT.BIN"-split”参数可以生成以下文件: <pl_bitstream_name>.bit.bin 2. 在U-BOOT下烧写PL Image 命令”fpga load”和”fpga loadb”都可以。区别是前一个命令接受去掉了文件头的bitstream文件,后一个命令接受含有文件头的bitstream文件。在OSL 2014.2上,缺省编译就可以完整支持写入PL Image的功能。但是在Petalinux 2013.10下,尽管可以在U-BOOT下看到命令”闷和fpga”,还需要在文件 <PROJ>/subsystems/linux/configs/u-boot/platform-top.h 中增加以下内容后重新编译才可以支持具体的功罩罩物能。/* Enable the PL to be downloaded */ #define CONFIG_FPGA #define CONFIG_FPGA_XILINX #define CONFIG_FPGA_ZYNQPL #define CONFIG_CMD_FPGA #define CONFIG_FPGA_LOADFS在OSL 2014.2 U-BOOT中,具体的功能是在zynqpl.c的zynq_load()中实现的。3. 在Linux下烧写PL Image OSL Linux 2014.2.01中已经含有xdevcfg驱动了(之前就有,不过本文是在这个版本上验证的),直接用以下命令就可以完成PL Image写入。 cat <path_to_storage_media>/<pl_bitstream_name>.bit.bin >/dev/xdevcfg Linux驱动的物液源代码在xilinx_devcfg.c中。因为驱动的编号是通过alloc_chrdev_region()动态分配的,所以不需要手工用mknod命令手动建立设备节点。在Linux驱动中,每次往DevCfg中写入4096字节,直到全部写完。4. 在用户程序中烧写PL Image目前没有现成的源码来完成这个功能,不过可以用mmap()把DevCfg的寄存器映射到用户程序的虚地址中,然后参考一些现成的软件代码来完成这个功能: * FSBL中的pcap.c * U-BOOT中的zynqpl.c * Linux中的xilinx_devcfg.c * Xilinx SDK中的例子。例子位于以下位置,随SDK的版本会有变化。 C:\Xilinx\SDK\2014.1\data\embeddedsw\XilinxProcessorIPLib\drivers\devcfg_v3_0\examples\index.html小结: DevCfg外设内部有自己的DMA,只需要简单的配置PL Image的基地址和长度到DevCfg寄存器,就可以完成Zynq-7000 PL Image的加载。Xilinx已经提供了灵活的解决方案,如果开发者要把这个功能集成在自己的应用程序中,也有很多的代码可以参考,并不是很困难的任务。

长话短说开始搞SD卡烧写UBOOT,从SD启动UBOOT。从s5pv210_irom_applicationnote_preliminary_20091126.pdf知道,s5pv210启动分BL0、BL1、BL2阶段。BL0是s5pv210内部IROM固化的代码,这段代码根据OM引脚配置状态来选择从哪个外部存储设备加载BL1段代码(实际上BL1代码就是我们编写的UBOOT的前8K代码,这段代码要包含完整的将后半部UBOOT代码复制和清bss段的功能,当然我们要从SD卡启动烧写在上面的UBOOT,OM引脚就必须配置为从SD卡启动配置)。图1从上图可知,逗慎毕从sd启动的时候BL0加载的代码是从第512个字节处开始加载代码,为什么要这样做呢?由于以后功能扩展的需要三星的软件工程师写的固化到IROM中的BL0代码是从SD卡的512字节处加载BL1的,他就是这样写的,我们对应UBOOT放置在SD卡中的位置就要往后移动512字节,后面有介绍怎么指定把uboot写到sd卡指定的位置的命令。还有一定要注意如下所示的地方:图2在BL1之前要加16个字节的头部信息。也就是在真正的UBOOT第一条指令之前孝段要加16个字节的头部信息,于是就山芹有我们所看到的uboot代码如下的用宏定义的一段:[cpp]viewplaincopy#ifdefined(CONFIG_EVT1)&&!defined(CONFIG_FUSED).word0x2000.word0x0.word0x0.word0x0#endif.globl_start_start:bresetldrpc,_undefined_instructionldrpc,_software_interruptldrpc,_prefetch_abort其中的.word0x2000代表BL1size(8K长度),.word0x0为保留字节.word0x0为checksum(后续会通过一个mkbl1工具来计算bl1的checksum并填写这个位置),最后一个.word0x0也为保留字节。再来看看uboot的下面的部分,如果bl0正常读取了bl1,代码就会到如下段:[cpp]viewplaincopy/*Readbootinginformation*/ldrr0,=PRO_ID_BASEldrr1,[r0,#OMR_OFFSET]//读OM引脚的配置状态bicr2,r1,#0xffffffc1#ifdefCONFIG_VOGUES/*PS_HOLD(GPH0_0)settooutputhigh*/ldrr0,=ELFIN_GPIO_BASEldrr1,=0x00000001strr1,[r0,#GPH0CON_OFFSET]ldrr1,=0x5500strr1,[r0,#GPH0PUD_OFFSET]ldrr1,=0x01strr1,[r0,#GPH0DAT_OFFSET]#endif/*NANDBOOT*/cmpr2,#0x0@512B4-cyclemoveqr3,#BOOT_NAND//根据OM引脚配置状态来给R3寄存器赋予代表系统是从何冲外部存储器启动的配置值。cmpr2,#0x2@2KB5-cyclemoveqr3,#BOOT_NANDcmpr2,#0x4@4KB5-cycle8-bitECCmoveqr3,#BOOT_NANDcmpr2,#0x6@4KB5-cycle16-bitECCmoveqr3,#BOOT_NANDcmpr2,#0x8@OneNANDMuxmoveqr3,#BOOT_ONENAND/*SD/MMCBOOT*/cmpr2,#0xcldrsp,_TEXT_PHY_BASE/*setuptempstackpointer*/subsp,sp,#12movfp,#0/*nopreviousframe,sofp=0*//*whenwealreadyruninram,wedon'tneedtorelocateU-Boot.*andactually,memorycontrollermustbeconfiguredbeforeU-Boot*isrunninginram.*/ldrr0,=0xff000fffbicr1,pc,r0/*r0moveqr3,#BOOT_MMCSD/*NORBOOT*/cmpr2,#0x14moveqr3,#BOOT_NOR#if0/*AndroidC110BSPusesOneNANDbooting!*//*Forseconddevicebooting*//*OneNANDBOOTONGfailed*/cmpr2,#0x8moveqr3,#BOOT_SEC_DEV#endif/*UartBOOTONGfailed*/cmpr2,#(0x1//ldrsp,=0xd0036000/*endofsramdedicatedtou-boot*/ldrsp,=0xd0035400//BL1段的函数进行 *** 作的堆栈位置,这里我修改了堆栈到了0xd0035400是由于图2中所示BL0代码进行了它自己代码堆栈的初始化,而RW/ZIregionHeap的最低部就位于0xd0035400,为了不修改BL0堆栈和BL0代码已经写好的一些函数功能(会在下面用到),我将堆栈修改到了0xd0035400subsp,sp,#12/*setstack*/movfp,#0bllowlevel_init/*gosetuppll,mux,memory*///这里会进行始终,内存,串口初始化之后运行到ldrsp,_TEXT_PHY_BASE/*setuptempstackpointer*///由于上面一步已经初始化了DRAM,所以在这里将以后的堆栈设置到了DRAM中的位置(以后BL2代码中函数都是基于此堆栈)subsp,sp,#12movfp,#0/*nopreviousframe,sofp=0*//*whenwealreadyruninram,wedon'tneedtorelocateU-Boot.*andactually,memorycontrollermustbeconfiguredbeforeU-Boot*isrunninginram.*/ldrr0,=0xff000fffbicr1,pc,r0/*r0ldrr0,=INF_REG_BASEldrr1,[r0,#INF_REG3_OFFSET]cmpr1,#BOOT_NAND/*0x0=>bootdeviceisnand*/beqnand_bootcmpr1,#BOOT_ONENAND/*0x1=>bootdeviceisonenand*/beqonenand_bootcmpr1,#BOOT_MMCSDbeqmmcsd_bootcmpr1,#BOOT_NORbeqnor_bootcmpr1,#BOOT_SEC_DEVbeqmmcsd_boot//代码判断要拷贝后,读取之前存入到用户使用寄存器中的值来判断此次启动从何种外部存储设备启动,这里为sd卡启动~~~~~省略若干代码~~~~~~~~mmcsd_boot:#ifDELETEldrsp,_TEXT_PHY_BASEsubsp,sp,#12movfp,#0#endifblmovi_bl2_copy//最后BL1代码来到此处从sd卡拷贝剩余的代码bafter_copy


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12500466.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存