本文以基于小梅哥AC620开发板的NIOS II LWIP百兆以太网例程为例,详细介绍在外部SDRAM中运行的NIOS II程序的固化方法。
【实用工具】
小梅哥一键合并sof和NIOS的elf软件程序为jic文件
http://www.corecourse.cn/forum.php?mod=viewthread&tid=27759
(出处: 芯路恒电子技术论坛)
【SDRAM NIOS程序固化的视频教程】
第一部分:https://www.bilibili.com/video/BV1NE411q7Y3?p=16
第二部分:https://www.bilibili.com/video/BV1NE411q7Y3?p=17
该视频教程里面讲了两种固化SDRAM程序的方法。
第一种是用Eclipse里面自带的NIOS II Flash Programmer来烧写Flash,首先就得烧写一次quartus的jic文件(只有verilog硬件部分,没有nios ii软件部分),然后打开NIOS II Flash Programmer对话框识别板子上的nios cpu,检测到system id和timstamp匹配后,再烧写进Flash。
这种方法操作起来很麻烦,而且出错率很高,操作难度很大。
错误1:No EPCS registers found: tried looking at addresses 0x00007000, 0x00007100, 0x00007200, 0x00007300 and 0x00007400
Info: Using cable "USB-Blaster [USB-0]", device 1, instance 0x00
Info: Resetting and pausing target processor: OK
Info: Reading System ID at address 0x040000C0: verified
Info: No EPCS registers found: tried looking at addresses
Info: 0x00007000, 0x00007100, 0x00007200, 0x00007300 and 0x00007400
Info: Leaving target processor paused
Error: Error code: 8 for command: nios2-flash-programmer "D:/Code/FPGA/Altera/nios/eth_20210407_epcs/software/eth_test_bsp/flash/main_epcs_flash_controller_0.flash" --base=0x7000 --epcs --sidp=0x40000C0 --id=0x21032600 --timestamp=1617808170 --device=1 --instance=0 '--cable=USB-Blaster on localhost [USB-0]' --program
解决方案:qsys里面将jtag_debug_module_reset与epcs_fash模块的reset引脚相连。(https://blog.csdn.net/Dable_cn/article/details/9174663)
错误2:读不到Flash ID。
解决方案:检查quartus工程里面epcs引脚的连接,是不是Pin Planner里面没有关联FPGA引脚。
错误3:读到了板子上的W25Q16的Flash ID为0xef4015,但是报错。
解决方案:板子上用的不是官方的EPCS Flash,而是非官方的华邦Flash,软件无法识别。(https://blog.csdn.net/subkiller/article/details/6394306)
在C:\altera\13.0sp1\nios2eds\bin文件夹下面新建一个nios2-flash-override.txt文件:
[EPCS-EF4015] # W25Q16 (lead-free)
sector_size = 65536
sector_count = 32
错误4:烧写完毕出现Resetting and pausing target processor: FAILED
解决办法:未知
反正错误很多,每个错误都很难解决。而且这种方法最大的弊端在于,最终我们无法得到完整的jic文件,影响到后面产品的量产。
还是第二种方法好用,也就是用小梅哥的脚本一次性执行,就能生成最终合并后的jic文件,而且整个过程只用烧写这一次jic文件。
不需要事先烧写好只有verilog没有nios ii的jic文件。是直接用脚本一次性得到最终的jic文件烧写进去!
先说明原理:
generate_jic.sh脚本里面最核心的只有三个命令:sof2flash、elf2flash和nios2-elf-objcopy。
#/bin/sh
rm -rf flashconv
mkdir flashconv
chmod 777 ../../output_files/*.sof
cp ../../output_files/*.sof ./flashconv/hwimage.sof
cp *.elf ./flashconv/swimage.elf
cd flashconv
chmod 777 swimage.elf
sof2flash --input=hwimage.sof --output=hwimage.flash --epcs -verbose
elf2flash --input=swimage.elf --output=swimage.flash --epcs --after=hwimage.flash --verbose
nios2-elf-objcopy --input-target srec --output-target ihex swimage.flash swimage.hex
rm -rf ../../../myoutput_files
mkdir ../../../myoutput_files
cp swimage.hex ../../../myoutput_files/swimage.hex
cp hwimage.sof ../../../myoutput_files/hwimage.sof
cp ../generate_jic.cof ../../../generate_jic.cof
cp ../generate_jic.tcl ../../../generate_jic.tcl
cd ../
sof2flash命令将quartus的sof文件转换成hwimage.flash文件
elf2flash命令将nios ii eclipse的elf文件转换成swimage.flash文件,其地址设置到hwimage后面
nios2-elf-objcopy将swimage.flash文件转换为hex文件
然后在quartus中,将swimage.hex和hwimage.sof合并成最终的jic文件。这个操作步骤已经保存为了cof文件(Save Conversion Setup),不用每次都去重新选择。
接下来详细说明一下操作步骤。
打开nios ii lwip以太网工程,进入qsys,添加EPCS IP核:
IP核保持默认配置:
连接clk, reset, epcs_control_port,导出external conduit引脚,地址设置为0x04001000(可随意选择),配置中断号。
注意epcs_control_port要同时连接nios2的data_master和instruction_master。
将nios ii的reset vector位置修改为epcs,exception vector位置可保持onchip memory不变,也可以修改为sdram(原本这两个都在onchip memory里面):
Generate一下:
修改verilog代码,添加epcs IP核的引脚:
output epcs_dclk,
output epcs_sce,
output epcs_sdo,
input epcs_data0
.epcs_flash_controller_0_external_dclk(epcs_dclk),
.epcs_flash_controller_0_external_sce(epcs_sce),
.epcs_flash_controller_0_external_sdo(epcs_sdo),
.epcs_flash_controller_0_external_data0(epcs_data0)
综合:
在Pin Planner里面配置epcs flash引脚的位置:
epcs引脚配置为普通I/O口:
再次综合,生成sof文件:
进入nios ii eclipse,generate一下bsp:
generate bsp过后,可以看到除了reset vector在epcs里面,其余的段都在sdram里面:
build一下c语言工程:
c语言工程编译成功:
将小梅哥的脚本拷进去:
generate_jic.cof的内容:
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<cof>
<eprom_name>EPCS16</eprom_name>
<flash_loader_device>EP4CE10</flash_loader_device>
<output_filename>./myoutput_files/hs_combined.jic</output_filename>
<n_pages>1</n_pages>
<width>1</width>
<mode>7</mode>
<hex_block>
<hex_filename>./myoutput_files/swimage.hex</hex_filename>
<hex_addressing>relative</hex_addressing>
<hex_offset>0</hex_offset>
</hex_block>
<sof_data>
<user_name>Page_0</user_name>
<page_flags>1</page_flags>
<bit0>
<sof_filename>myoutput_files/hwimage.sof</sof_filename>
</bit0>
</sof_data>
<version>5</version>
<create_cvp_file>0</create_cvp_file>
<options>
<map_file>1</map_file>
</options>
</cof>
generate_jic.tcl的内容:
exec quartus_cpf -c generate_jic.cof
在C语言工程上打开命令行:
运行sh脚本:
./generate_jic.sh
回到quartus里面,运行一下tcl脚本,即可得到最终的hs_combined.jic文件:
将hs_combined.jic文件烧写进去,整个固化过程就结束了:
板子重新上一下电,程序就运行起来了,而且掉电不丢失:
这个时候,如果想要继续在SDRAM里面调试程序,不固化,不用重新编译quartus工程,只需要在bsp editor里面将下面两个复选框去掉,就能直接在eclipse里面点击run运行程序了。要想固化了,又重新勾上去。