外部SPI FLASH: Micron N25Q128A13ESE40G (128Mbit (16MByte))
FPGA: XC7A100T
CPU: Microblaze
第一种情况: Microblaze在简单的应用,比如运行LED,IIC,SPI,UART之类的低俗接口驱动,或做一些简单的辅助型工作时,一般生成的application elf文件都不大,在10几KB或者几十,百几KB,此时使用FPGA内部的BRAM资源已经足够。 XC7A100T本身就有600几KB的BRAM资源。这种情况下直接将 硬件流文件 和 elf 文件 合并为download.bit文件,在直接烧录到外部SPI FLAH即可。
1. Xilinx -- Program FPGA (合并硬件流和app.elf, 生成download.bit)
当Program完成后,FPGA已经可以运行起来了,不过这不是固化,断电重启后就消失。
2. Xilinx -- Program Flash
Program完成后,断电重启即可。简单!!!
因为我们使用的SPI flash支持x4, 在xdc加入下面代码大大加快加载速度:
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
文章来源地址https://uudwc.com/A/Z3P6
第二种情况: 当Microblaze需要运行文件系统,网络协议栈,例如lwip时,编译代码最终可能会高达几十MB,此时就需要通过SREC SPI Bootloader从SPI Flash加载elf到外部DDR运行。
1. 因为需要从SPI Flash读取应用文件,Vivado BD硬件需要添加 AXI Quad SPI IP, 配置如下:
引出引脚,命名为qspi_flash, xdc下加入引脚定义:
#spi_flash
set_property IOSTANDARD LVCMOS33 [get_ports {qspi_flash_ss_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports qspi_flash_io0_io]
set_property IOSTANDARD LVCMOS33 [get_ports qspi_flash_io1_io]
set_property IOSTANDARD LVCMOS33 [get_ports qspi_flash_io2_io]
set_property IOSTANDARD LVCMOS33 [get_ports qspi_flash_io3_io]
set_property PACKAGE_PIN T19 [get_ports {qspi_flash_ss_io[0]}]
set_property PACKAGE_PIN P22 [get_ports qspi_flash_io0_io]
set_property PACKAGE_PIN R22 [get_ports qspi_flash_io1_io]
set_property PACKAGE_PIN P21 [get_ports qspi_flash_io2_io]
set_property PACKAGE_PIN R21 [get_ports qspi_flash_io3_io]
#qspi_flash_ss_io[0] 为 QSPI_CS
#qspi_flash_io0_io 为 QSPI_DQ0
#qspi_flash_io1_io 为 QSPI_DQ1
#qspi_flash_io2_io 为 QSPI_DQ2
#qspi_flash_io3_io 为 QSPI_DQ3
#QSPI_CLK 不用接
保存,生成硬件流文件 top_wrapper.bit
2. 进入SDK, 新建工程。 File -- New-- Application Project
Next >
Finish
可以看到Project Explorer下建立刚刚的新工程
3.设置 FLASH_IMAGE_BASEADDR的offset (这个offset是在SPI Flash 存储应用程序的Flash偏移量)
外部Flash大小为16MByte, 我们设置前面大概8MB存放top_wrapper.bit 和 SREC BootLoader.elf, 后面存放app. 需要根据实际FPGA容量进行调整。
修改blconfig.h
4.因为SREC BootLoader是加载到BRAM运行的,所以确保其在BRAM
文章来源:https://uudwc.com/A/Z3P6
5. 右键lwipbootloader_bsp -- Board Support Package Setting. 修改xilisf, 设置serial_flash_family=5, 因为我们使用Micron,其他不变
6. 编译,生成的lwipbootloader.elf 大小18.208KB
7. 先合并硬件流文件和lwipbootloader.elf,生成download.bit
8. 烧写download.bit 到Flash中,记住这里的Offset = 0
9. 再烧写应用程序即之前的lwiptcp.elf (这个文件的代码大小为507KB,可以烧录到Flash,但其加上未定义变量,需要30几MB空间,所以需要加载到DDR中运行)
注意: Image File选择lwiptcp.elf应用程序文件,Offset为之前设置的0x80000, 同时需要勾选Convert ELF to bootloadable SREC format and program,因为应用程序是通过转换为SREC格式保存在Flash中。使用SREC格式也导致了代码固化后加载时间极其漫长,如何优化关注我另外一篇文章。
10. 断电重启,OK? ??
为什么只打印了SREC SPI BootLoader就没有反应?
查看bootloader.c main函数,
简单修改一下,保证这个初始化函数有足够的时候等待Flash就OK了
volatile int wait;
do
{
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if (Status != XST_SUCCESS)
{
xil_printf("XIsf_Initialize failed! Status=%d\r\n", Status);
for (wait=0; wait < 100000; wait++);
for (wait=0; wait < 100000; wait++);
}
} while (Status != XST_SUCCESS);
用一个循环,直到初始化成功。编译,合并生成download.bit, 重新program即可。(这个时候应用程序不用再下载,因为之前已经下载过了)
SREC Bootloader 不断一条一条读取应用程序并加载。