kl800.com省心范文网

基于SOPC的FLASH和SDRAM的读写


目录
目录................................................................................................................................................... 1 1. 实验目的...................................................................................................................................... 2 2. 实验操作过程.............................................................................................................................. 2 2.1 系统的总体构建 ................................................................................................................ 2 2.2 构建硬件系统 .................................................................................................................... 2 2.2.1 建立工程 ................................................................................................................. 2 2.2.2 构建 NIOS II 软核 ................................................................................................. 6 2.2.2.1 构建 CPU 模块 ................................................................................................. 9 2.2.2.2 建立 SDRAM 模块......................................................................................... 11 2.2.2.3 构建 Avalon 三态桥 ....................................................................................... 13 2.2.2.4 建立 FLASH 模块 .......................................................................................... 15 2.2.2.5 建立 JTAG UART ........................................................................................ 17 2.2.2.6 建立 System ID ............................................................................................... 18 2.2.2.7 配置及编译 NIOS II ....................................................................................... 20 2.2.2.8 分配管脚 ......................................................................................................... 24 2.2.3 建立锁相环 PLL 模块 .......................................................................................... 25 2.2.4 其它相关配置 ....................................................................................................... 27 2.2.5 锁定引脚 ............................................................................................................... 27 2.3 软件部分.......................................................................................................................... 32 2.3.1 SDRAM 部分......................................................................................................... 32 2.3.3.1 SDRAM 操作中的注意事项 ........................................................................... 35 2.3.3.2 SDRAM 的基本读写操作............................................................................... 36 2.3.2 FLASH 部分 ......................................................................................................... 36 3.3.2.1 FLASH 操作中的注意事项 ........................................................................ 40 3. 遇到的问题及解决方法 ............................................................................................................ 41 4. 实验总结.................................................................................................................................... 42 5. 附录............................................................................................................................................ 43 5.1 主要参考网站 .................................................................................................................. 43 5.2 参考文献.......................................................................................................................... 43 5.3 工程和源代码 .................................................................................................................. 43

基于 SOPC 的 SDRAM 和 FLASH 存储器的读写实验
1. 实验目的
1) 熟悉构建一个完整的基于 Quartus II 和 NIOS II 的 SOPC 实例。 通过 Quartus II 9.0 建立工程,学会使用 SOPC_Builder 快速建立 Embedded_System(即实验的硬件平台) ;利用 NIOS II 构建软核,并将软硬件结合起来,进行编译并下载到 DE2 板子上; 2) 学习简单关于的 SDRAM,FLASH 的读写操作(本试验中都是调用的 nios 自带的 API 函数) ; 3) 了解有关存储器内部操作的相关内容。

2. 实验操作过程 2.1 系统的总体构建
在 Quartus II 中构建最小的 SOPC 系统。此 SOPC 系统由 Nios II 中的 CPU 模块、PLL 模块和系统复位等模块组成。在系统的顶层模块中分别添加 SOPC Builder 生成的最小的 SOPC 系统,包括分别用于控制 FLASH 和 SDRAM 的 IP 核,JTAG 仿真接口。其最终的最 小系统构架如下:

2.2

构建硬件系统

2.2.1 建立工程
首先,打开 quartus ii:

西南科技大学 信息学院 08 级 林正红

接下来,建立一个工程 File->New Project Wizard

第一行是工程的路径,你选择你放置的路径即可,第二都是是工程名,第三行顶层文件

西南科技大学 信息学院 08 级 林正红

名,写好以后如下,点击 Next:

点击后,如下图所示,这个可以不需要改动,接着点击 Next

点 击 后 , 如 上 图 所 示 , Family 里 选 择 Cyclone II , 在 Available devices 中 选 择
西南科技大学 信息学院 08 级 林正红

EP2C35F672C6(具体内容根据你的芯片所定)。

接着点击 Next,也不需要修改,点击 Finish,显示如下图所示:

到此为止,工程已经建立完成。接下来,需要建立一个 Block Diagram/Schematic File, 点击 File->New,如下图所示:
西南科技大学 信息学院 08 级 林正红

点击 OK,完成建立,工程中出现了一个 Block1.bdf 文件

2.2.2 构建 NIOS II 软核
接着,我们进入构建软核环节,点击 Tools->SOPC Builder 或者下图红圈标示的图标
西南科技大学 信息学院 08 级 林正红

点击以后,SOPC Builder 运行会出现以下界面:

打开 SOPC Builder 之后,在 System Name 中输入软核的名字,这里我将其命名为 MYTEST(软核名与工程名最好不要相同) :

西南科技大学 信息学院 08 级 林正红

点击 OK 后,出现下面的界面:

按图中标注的,clk_0 为时钟名称,50.0 为时钟值(单位为 MHz) ,我们可以对他们进 行修改。用鼠标点击 50.0,将其改为 100.0。这时候,我们的软核时钟就为 100.0MHz 了。 这是软核建立的第一步。接下来,我们要建立 Nios II Processor。

西南科技大学 信息学院 08 级 林正红

2.2.2.1

构建 CPU 模块

点击后,将出现下图,下一步我们来选择软核的类型。这里给我们提供了三种类型, Nios II/e 占用资源最少,功能也最简单,速度最慢。Nios II/s 占资源比前者多一些,功能也 多了,速度也快一些,Nios II/f 占资源最多,功能也最多,速度最快。选择的时候要根据自 己的需求和芯片资源来决定。在这里,我选择 Nios II/f,功能和速度都可以得到满足。下面 的 Reset Vector 是复位后启动时的 Memory 类型和偏移量, Exception Vector 是异常情况时 的 Memory 类型和偏移量。现在还不能配置,需要 SDRAM 和 FLASH 设置好以后才能修改 这里,这两个地方都很重要。

点击 Next,如下图所示,将红圈处选择为 None,也就是关闭 Data Cache,避免在 NIOS
西南科技大学 信息学院 08 级 林正红

II 下无法进行寄存器方向操作 PIO。

接下来连续点击 Next,一直到下图为止:

这里JTAG Debug Module,即JTAG调试时所用到的功能模块。功能越多,需要的资源越 多, 这里, 我们选择Level 1即可, 即不需要过多其他的功能。 点击Finish, 结束Nios II Processor
西南科技大学 信息学院 08 级 林正红

的建立后,如下图所示:

2.2.2.2

建立 SDRAM 模块

点击后,如下图所示:

西南科技大学 信息学院 08 级 林正红

对上一步中画红框的部分进行相关设置,与实际的SDRAM相匹配(存储空间为 8Mbyte) :

西南科技大学 信息学院 08 级 林正红

点击NEXT后,如下图:

再直接点击FINISH即完成了SDRAM的加载和设置。

2.2.2.3

构建 Avalon 三态桥

接下来, 我们要建立一个Avalon三态桥, 在NIOS系统中, 要实现与FPGA片外存储器途信, 就必须在Avalon总线和连接外部存储器癿总线之间添加一个桥,这个桥就是Avalon三态桥。 点击下图所示红圈标注处:

西南科技大学 信息学院 08 级 林正红

点击后,会出现以下界面:

这步不需要修改,再继续点击NEXT,会出现以下界面:

西南科技大学 信息学院 08 级 林正红

这里,也不需要任何设置,直接点击FINISH即可完成。

2.2.2.4

建立 FLASH 模块

接下来,添加FLASH模块(存储空间为4Mbyte) :

点击后,会出现以下画面:

西南科技大学 信息学院 08 级 林正红

与SDRAM的设置类似,也要对地址线宽和数据线宽进行设置:

点击下一步以后,会出现:

西南科技大学 信息学院 08 级 林正红

这里,我们需要设置三个量,Setup,Wait,Hold,我们分别将其设置为 40,160,40 如上图所示。这些量都是根据 FLASH 的芯片决定的,各个芯片都不一样。点击 Finish 后, 完成 Flash Memory Interface(CFI)的建立。

2.2.2.5

建立 JTAG UART

西南科技大学 信息学院 08 级 林正红

点击红圈处,出现以下界面:

什么都不用修改,直接点击 Next->Finish 完成 JTAG UART 模块癿建立。

2.2.2.6

建立 System ID

System ID 就是一种标示符,类似校验和的东西,在你下载程序之前或者重启之后,都 会对它进行检验,以防止错误发生,大家知道这个东西就可以了,没太大的用处,但又需要 有的。点击下图所示红圈处:

西南科技大学 信息学院 08 级 林正红

点击后,如下图所示:

点击 Finish,完成 System ID 的建立。 到此为止,最基本的 NIOS 系统模块就建立完成了,如下图所示 :

西南科技大学 信息学院 08 级 林正红

2.2.2.7

配置及编译 NIOS II

注意下图的红圈处:

这时,cfi_flash 还没有跟 tristate_master 连接,当我们把鼠标移刡红圈处位置时,就出 现了下图所示的情况:

这时候,我们用鼠标点击红圈处的空心圆,空心圆变成了实心圆,这就完成了 cfi_flash 和三态桥的连接,如下图所示:

西南科技大学 信息学院 08 级 林正红

接下来我们需要对 cpu 进行设置一下,双击 cpu,Reset Vector 处癿 Memeory 选择 cfi_flash,Exceptioni Vector 选择 sdram,其他不变,如下图所示:

再点击 Finish,即可完成对 cpu 的设置。 接下来,我们需要对 FLASH 地址进行锁定,保证 FLASH 的起始地址为 0x00000000, 因为 FLASH 是系统重启后的起始位置,这样做的好处就是有利于我们操作,系统重启后从 0x00000000 开始也是我们的忠维习惯。点击下图所示的红圈处:

点击以后,锁会自动闭合。

西南科技大学 信息学院 08 级 林正红

最后一步设置就是对地址的自动分配,这样做是为了不浪费空间,如果有特殊要求的, 也可以手动设置,点击相应的地址,就可以手动修改了,大家自己试试吧。地址自动分配操 作如下,点击下图所示红圈处,SYSTEM->Auto-assign Basic Addresses:

点击后,大家可以发现,各个模块的地址都有相应的变化,但 CFI_FLASH 基地址还是 0x00000000,说明锁定成功。 接下来是中断的自动分配,和地址自动分配一样,SYSTEM-> Auto-assign IRQs,如果 有什么特殊需要,可以手动更改中断的优先级。之所以要自动分配一下,是因为这个软件还 不够智能,当模块建好以后,有出现重复中断号的现象,编译的过程就会出现问题,自动分 配了以后就不从上自下按顺序排列了。而且,图片上出现的红叉也都消失了。

西南科技大学 信息学院 08 级 林正红

这个时候我们就可以编译了: 点击 Next,出现下图,如果需要仿真的,点击红圈处,将其选中,我们一般不运行仿 真,此处就不选了。

点击 Generate,我们就开始编译了。这个编译需要很长的时间,请耐心等待,编译好后 的结果如下,请看下图红圈处,看到 successful 了吗?只要看到它就没问题了,软核已经编 译好了,点击 Exit,回到了 Quartus ii 界面。

西南科技大学 信息学院 08 级 林正红

2.2.2.8

分配管脚

回到 Quartus 界面以后,在 Block1.bdf 界面里在空白处双击左键,会出现下图,看多了 下图红圈处的地方了吗?这个就是我们做好的 NIOS II 软核了,用鼠标双击它(或者选中以 后点击 OK)后,将其放到 Block1.bdf 的空白处即可。

在 NIOS 软核 KERNEL 上点击右键后点击 Generate Pins for symbol ports, 这一步作用就
西南科技大学 信息学院 08 级 林正红

是生成管脚,经过命名以后分配真实的引脚:

点击后,如下图所示:

2.2.3 建立锁相环 PLL 模块
这一部分具体参见《nios 那些事儿.pdf》中的 39 到 44 页,内有很详细的说明,按照上 面的步骤进行操作即可。 建立好 PLL 模块后,接下来的工作就是将 PLL 连接到 NIOS 软核上。如下图所示(连 线方式很简单,大家自己研究一下便可知道)
西南科技大学 信息学院 08 级 林正红

注:我们利用锁相环 PLL 的 c1 来为 SDRAM 提供时钟,时钟频率设置为 100MHz,偏 移量为-75deg(这个地方会影响到 SDRAM 是否正常运行,是根据 SDRAM 的数据手册得到 的) 。 接下来我们要给 SDRAM 的时钟分配引脚,这个就由 c1 完成了。首先是加一个 output 引脚,方法很简单,在空白处双击,出现下图,在 Name 处输入 output,一个回车,OK 了。 假如你要加入 input,即输入引脚,你就在 Name 处输入 input,还有双向引脚的是 bidir,常 用的就这几个:

将其放入下图红框所示位置,连好线就可以了:

西南科技大学 信息学院 08 级 林正红

2.2.4

其它相关配置

需要 FLASH 加入的复位端口,操作与之前类似,加入一个输出引脚和电源(电源也是 直接在 Name 中输入 VCC 就可以找到)即可:

2.2.5

锁定引脚
在锁定引脚之前,先对工程进行一次编译,点击下图红圈处即可:

等待综合与分析成功之后,再锁定引脚。 注:这一步如果按照正确的相关设置,一般不会出现问题,遇到问题,再按照错误提示 进行分析解决。而且一般为逻辑错误,需要仔细检查一下。 选择 Assigments->Pins,开始锁定引脚:

西南科技大学 信息学院 08 级 林正红

点击进入后,将每一个功能管脚锁定正确的锁定到 DE2 板子上相应的管脚上。 锁定引脚这一步需要按照《DE2_资料.pdf》相关引脚的说明进行锁定,也可以参考引脚 分配表的 Excel 版本(可以更方便,快捷一些) 《DE2_pin_assignments.xls》 ,如下图:

说明:这是 FLASH 的地址引脚,按照这个顺序正确无误的与我们构建的软核相连接:

西南科技大学 信息学院 08 级 林正红

注意: 由于引脚较多, 锁定时一定要有耐心, 并在检查正确无误后关闭锁定引脚的窗口。 一旦一个引脚出现错误,就会影响以后的结果,即使在全编译时通过了,后面的步骤中也会 出现问题,所以还是细心一点为好。 下图是利用 SOPC_Builder 建立好的系统(已经分配了引脚) :
pll MYTEST
inclk0
INPUT VCC

inclk0

inclk0 f requency : 50.000 MHz Operation Mode: Normal Clk Ratio Ph (dg) DC (%) c0 c1 2/1 2/1 0.00 -75.00 50.00 50.00

PIN_N2

c0 c1

reset_n

INPUT VCC

clk_0 reset_n out_port_from_the_pio[3..0] zs_addr_from_the_sdram[11..0] zs_ba_f rom_the_sdram[1..0] zs_cas_n_from_the_sdram zs_cke_f rom_the_sdram PIN_AA7 zs_cs_n_f rom_the_sdram zs_dq_to_and_from_the_sdram[15..0] zs_dqm_from_the_sdram[1..0] zs_ras_n_f rom_the_sdram zs_w e_n_from_the_sdram address_to_the_cfi_flash[21..0] data_to_and_f rom_the_cfi_f lash[7..0] read_n_to_the_cf i_flash select_n_to_the_cfi_flash w rite_n_to_the_cfi_flash
inst
OUTPUT

PIN_N25
out_port_f rom_the_pio[3..0]

OUTPUT OUTPUT OUTPUT OUTPUT OUTPUT BIDIR VCC OUTPUT OUTPUT OUTPUT

VCC

inst1

Cy clone II

OUTPUT

sdram_clk

OUTPUT

f lash_reset

PIN_AA18

OUTPUT BIDIR VCC OUTPUT OUTPUT OUTPUT

PIN_AC22 PIN_AB21 PIN_AF23 PIN_V5 PIN_AE23 zs_cas_n_f rom_the_sdram PIN_Y1 PIN_AE3 PIN_W3 zs_cke_f rom_the_sdram PIN_AE2 PIN_AB3 PIN_W4 zs_cs_n_f rom_the_sdram PIN_AA6 PIN_U5 zs_dq_to_and_f rom_the_sdram[15..0] PIN_AC3 PIN_U7 zs_dqm_f rom_the_sdram[1..0] PIN_AA5 PIN_U6 zs_ras_n_f rom_the_sdram PIN_Y5PIN_AC1 PIN_W1 zs_we_n_f rom_the_sdram PIN_AD2 PIN_AB4 PIN_AC2 PIN_W2 PIN_AA3 PIN_V3 PIN_AD3 PIN_AA4 PIN_V4 address_to_the_cf i_f lash[21..0] PIN_AB1 PIN_T6 data_to_and_f rom_the_cf i_f lash[7..0] PIN_Y14 PIN_AB2 read_n_to_the_cf i_f lash PIN_Y15 PIN_AE21 PIN_W6 PIN_AA15 select_n_to_the_cf i_f lash PIN_AF21 PIN_W17 PIN_V7 PIN_AB15 PIN_AC20 write_n_to_the_cf i_f lash PIN_T8 PIN_V17 PIN_AC15 PIN_AB20 PIN_R8 PIN_AA17 PIN_AE16 PIN_AE20 PIN_Y4 PIN_AD16 PIN_AF20 PIN_Y3 PIN_AC16 PIN_AC19 PIN_AA1 PIN_W15 PIN_AD19 PIN_AA2 PIN_W16 PIN_V6 PIN_AF17 PIN_AE17 PIN_AC17 PIN_AD17 PIN_AA16 PIN_Y16 PIN_AF18 PIN_AE18 PIN_AF19 PIN_AE19 PIN_AB18 PIN_AC18
zs_addr_f rom_the_sdram[11..0] zs_ba_f rom_the_sdram[1..0]

说明:最后,需要进行一次全编译,点击下图标注处:

点击全编译后,会出现以下界面,表示编译正在进行:

西南科技大学 信息学院 08 级 林正红

说明:绿色的部分显示当前编译的进度,当全部被绿色填充完后,则说明编译完成。 下面是将工程编译完成后的界面:

说明: 如最后的编译中有错误, 一般都是引脚锁定中的错误。 且工程全编译成功通过后, 会在保存的路径中,产生出后缀名为.ptf 的文件,是用于后面与软件进行挂接的。也相当于 是以上所有操作得出的综合体。 经过所有的操作之后,才算完成了硬件的配置。 成功完成所有的配置后,开始下载硬件部分到 DE2 开发板上,先点击图中的红圈处:

会出现以下界面:

西南科技大学 信息学院 08 级 林正红

等到下载进度条显示 100%时,下载完成!

其中,构建好的 SDRAM 部分框架如下:

构建好的 Flash 部分框架如下:

西南科技大学 信息学院 08 级 林正红

2.3 软件部分
在 NIOS II IDE 中建立 nios ii 工程时,导入搭建硬件平台时产生的.ptf 文件,先对工程 进行编译,会产生一个 system.h 文件,里面包含了整个系统的相关信息,包括中断号,基地 址和其它相关配置信息,SDRAM、FLASH 等都有相应的基地址,我们以后就要用这些地址 对 NIOS 软核进行寄存器操作。 说明:具体的操作步骤详见《nios 那些事儿.pdf》中的软件开发部分,都已经有很详细 的说明了,在此不再叙述。 以下为 system.h 的 SDRAM 部分:

2.3.1 SDRAM 部分
以下是在 NIOS ii IDE 中编写的对 SDRAM 进行读写测试的 C 语言程序代码, 这段程序 完成的功能是向 SDRAM 中写入 100 个数字,从 0 到 99,然后通过程序,访问 SDRAM,逆

西南科技大学 信息学院 08 级 林正红

向读书写入的数据(及结果应该为 99 到 0) ,程序如下所示:
#include <stdio.h> #include "system.h" //标准的输入输出头文件,必须包括 //程序中会使用到system.h文件中的相关定义,必须加上

unsigned short *ram = (unsigned short *)(SDRAM_BASE+0x10000); unsigned //SDRAM地址,其中的SDRAM_BASE是在生成的System.h时得到的,文件中的定义为: #define SDRAM_BASE 0x01000000

void) int main(void void { int i; memset(ram,0,100); //这个函数用于向sdram中写数据,当sdram写完以后,sdram的地址已修改为(SDRAM_BASE+0x10100) for(i=0;i<100;i++){ for *(ram++)= i; } //向SDRAM中写入0到99这100个数字

for(i=0;i<100;i++){ for printf(" %d",*(--ram)); } //逆向输出0到99这100个数

return 0; }

程序写好之后,编译工程,等到编译成功之后,进行下载。操作过程如下图所示:

西南科技大学 信息学院 08 级 林正红

点击编译后,出现以下界面:

等到编译进度条满了之后,编译结束,查看结果:

若有错误,请根据错误信息,进行相关修改后再次编译,知道编译正确。然后,下载软 件到 DE2 开发板,与之前下载的硬件相结合,才能得到结果!点击下图所示下载的快捷键, 进行下载:

观察下载进度条变化当为 100%时,下载成功:
西南科技大学 信息学院 08 级 林正红

下载成功,运行结果如下:

最后,输出了 99 到 0 这 100 个数,结果表明,最后对写入的 100 个数据读取成功。到 此为止,第一个实验完成! 说明: 1)若最后输出的结果不正确或不能正确输出(即不是按照 99 到 0 的顺序倒序输出的), 则说明程序有错误。应检查程序后再次下载。 2) 如果是下载硬件时出现问题,应该是应该是 IP 核设置与实验板的器件不匹配 ,或 者引脚锁定出错。可以按照这样的思路去寻找操作或者设置中的错误。对 FLASH 的读写也 有类似结论,在 FLASH 的操作中就不再叙述了。

2.3.3.1 SDRAM 操作中的注意事项 操作中的注意 注意事项
1) SDRAM 是 Synchronous Dynamic Random Access Memory(同步动态随机存储器) 的简称,它将 CPU 和 RAM 通过一个相同的时钟锁在一起,使得 RAM 和 CPU 能够共享一 个时钟周期,以相同的速度同步工 作,从而解决了 CPU 和 RAM 之间的速度不匹配问题, 避免了在系统总线对异步 DRAM 进行操作时同步所需的额外等待时间,可加快数据的传输 速度。 2) 对 SDRAM 的读写, 是调用的 Altera 提供的 API 函数, 整个实验做完以后, SDRAM 对 的内部结构还不是很了解,于是结合芯片的数据手册和上网查询的一些资料,知道了关于 SDRAM 的新概念及相关操作,但都只是了解而已,这些功能都已经在底层函数中实现了。 具体有如下总结: SDRAM 工作过程: 启动初始化: 1)同时启动设备核心电源 VDD 和设备 I/O 电源 VDDQ。声明并维持 CKE 引脚为高电 平(CKE 引脚为 Clock Enable,时钟使能信号,高电平表示启动内部时钟信号。 2)等到 VDD 和 VDDQ 稳定后并且 CKE 设为高电平,应用稳定时钟。 3)等待 200?s 执行空操作命令。 4)Precharge:预充电命令。SDRAM 执行一条预充电命令后,要执行一条空操作命令, 这两个操作会使所有的存储单元进行一次预充电,从而使所有阵列中的器件处于待机状态。 引脚 A10(=AP Auto Precharge)可以对预充电的模式进行选择。
西南科技大学 信息学院 08 级 林正红

5)auto-refresh:自刷新命令。SDRAM 要执行两条自刷新命令,每一条刷新命令之后, 都需要执行一条空操作命令。这些操作会使 SDRAM 内部的刷新及计数器进入正常运行状 态,以便为 SDRAM 模式寄存器编程做好准备。 6) mode register:设置模式寄存器。Mode Register 一般被用于定义 SDRAM 运行的模 式,寄存器里一般设置了读取延迟,burst 长度,CAS,burst 类型,操作模式,还有是设置 SDRAM 是工作在单个读写操作还是 burst 操作下。 Mode Register 必须在所有的 bank 都处于 idle 状态下才能被载入,在所有初始化工组都进行完毕之前,控制器必须等待一定的时间。 在初始化过程中发生 了任何非法的操作都可能导致初始化失败从而导致整个计算机系统不 能启动。 注意:只有设置完模式寄存器之后才可以进入正常读写操作模式。

2.3.3.2 SDRAM 的基本读写操作
SDRAM 的基本读操作需要控制线和地址线相配合地发出一系列命令来完成。先发出 BANK 激活命令 (ACTIVE) 并锁存相应的 BANK 地址 , (BA0、 BA1 给出) 和行地址 (A0~ A12 给出) 。BANK 激活命令后必须等待大于 tRCD(SDRAM 的 RAS 到 CAS 的延迟指标)时 间后,发出读命令字。 CL (CAS 延迟值)个工作时钟后,读出数据依次出现在数据总线上。 在读操作的最后,要向 SDRAM 发出预充电(PRECHARGE)命令,以关闭已经激 活的页。 等待 tRP 时间(PRECHARGE)命令,以关闭已经激活的页。等待 tRP 时间(PRECHAREG 命令后,相隔 tRP 时间,才可再次访问该 行)后,可以开始下一次的读、写操作。SDRAM 的读操作只有突发模式(Burst Mode) ,突发长度为 1、2、4、8(可选) 。

2.3.2 FLASH 部分
以下是在 NIOS ii IDE 中编写的对 FLASH 进行读写的 C 语言程序代码:
#include "altera_avalon_cfi_flash.h" //包含了 FALSH 操作中的相关函数的信息,所以必须加上这个头文件 #include "alt_types.h" #include "sys/alt_flash.h" #include "sys/alt_flash_dev.h" #include <stdio.h> #include "system.h" #define BUF_SIZE 100 #define FLASH_OFFSET 0x5000 //包含了提取 FALSH 相关信息的定义 //包含了 FALSH 操作中的相关函数的信息 //包含了 FALSH 操作中的相关函数的信息 //标准的输入输出头文件 //System.h 中包含了配置 FLASH 的相关信息 //将缓冲区的大小定为 100 //偏移量在 System.h 中有定义

int main(void) {

西南科技大学 信息学院 08 级 林正红

int i; alt_flash_fd* fd; flash_region* regions; int number_of_regions; int ret_code = 0x0; unsigned char source[BUF_SIZE]; unsigned char dest[BUF_SIZE]; for(i=0;i<100;i++) { source[i] = i; } //向源区中的写入 0 到 99 这 100 个数 ,这是为了后面目的去读出做准备的 //指针指向 FLASH // flash_region,原型在 sopc.h 文件中有定义 //区域的数目 //初始化为 0 //源缓冲区 //目的缓冲区

fd = alt_flash_open_dev("/dev/cfi_flash");//打开 flash if(fd) { //当 FLASH 为非空时

/ /alt_get_flash_info()可以提取 Flash 的信息 ret_code = alt_get_flash_info(fd, &regions, &number_of_regions);

}

//

for(i=0;i<number_of_regions;i++) { printf("Start 0x%8x; End 0x%8x ;Number of Blocks %3d ;Block Size 0x%8x \n", (regions+i)->offset, //region 相对 FLASH 首地址的偏移量

(regions+i)->region_size+(regions+i)->offset, // region 的大小 (regions+i)->number_of_blocks, (regions+i)->block_size); } alt_erase_flash_block(fd, FLASH_OFFSET, BUF_SIZE); ret_code = alt_read_flash(fd,FLASH_OFFSET,dest,BUF_SIZE); if(ret_code != 0) { printf("Can't read flash device\n"); 西南科技大学 信息学院 08 级 林正红 //擦除 FLASH 的块的内容 // 每 个 region 中 block 的 数 量 // block 的大小

exit(-1); } //向 flash 中读入数据,成功则返回 0 else { printf("Read Flash Device Successfully.\n"); } for(i=0;i<100;i++) { printf("%d ",dest[i]);

} //打印读取的数据 ,此时为写入之前的数据 //向 FLASH 中写数据,成功后返回值为 0 , 将源区的数据写入目的去中 ret_code = alt_write_flash(fd,FLASH_OFFSET,source,BUF_SIZE); if(ret_code != 0) { printf("Can't write flash device\n"); exit(-1); } else { printf("Write Flash Device Successfully.\n"); } //读 FLASH 中的数据,成功后返回值为 0 ret_code = alt_read_flash(fd,FLASH_OFFSET,dest,BUF_SIZE); if(ret_code != 0) { printf("Can't read flash device\n"); exit(-1); } else { 西南科技大学 信息学院 08 级 林正红

printf("Read Flash Device Successfully.\n"); } //打印读取的数据 for(i=0;i<10;i++) { printf("%d } printf("\n"); for(i=90;i<100;i++) { printf("%d } alt_flash_close_dev(fd); } //使用完以后需要将 FLASH 关掉 ",dest[i]); //输出读入的最后十个数 ",dest[i]); //输出读入的前十个数

以下 sopc.h 文件中的内容:
#ifndef SOPC_H_ #define SOPC_H_ typedef struct flash_region { int offset; int region_size; int block_size; }flash_region; #endif SOPC_H_ // region相对FLASH首地址的偏移量 // region的大小 // block的大小 //sopc.h文件

int number_of_blocks; // 每个region中block的数量

具体的编译和下载过程与前相同,在此不再重复了。 说明:以上头文件中包含的信息较多,可以点击 Nios ii 软件右边界面中的对应的头文 件,进入后即可看到其包含的具体内容,如下图所示:

西南科技大学 信息学院 08 级 林正红

下载软件后的结果为:

从结果中可以看出: 这款 FLASH 中包括了 8 个 8Kbyte, 个 64Kbyte 字节的 block。而 63 且最后读出的是 0 到 9 和 90 到 99 这二十个数字,说明程序正确,FLASH 的读写也正确了。 经过上述所有操作,我们的两个实验就做好了。

3.3.2.1

FLASH 操作中的注意事项

1)由于这个程序中,调用的库函数较多,现在只知道它们怎么使用,不清楚其中的具 体内容,于是想通过一定的方法,尽量去了解一下。查了很多资料,都只是提到可以用 ALTERA 提供的 HAL 函数来调用 EPCS 相关的函数, 但是具体的函数是什么, 还是不清楚,
西南科技大学 信息学院 08 级 林正红

最 后 , 查 看 C:\altera\91\ip\altera\sopc_builder_ip\altera_avalon_epcs_flash_controller\HAL\src 文件夹下的文件,才明白了一些,但是还不是很清楚。 这里以读函数为例: typedef int (*alt_flash_write_block)( alt_flash_dev* flash, int _blockoffset , void* int offset, const void src_addr, int length ); 相关说明: 底层的函数程序中的有类似 typedef int(*P)(x)结构的函数: 其中 P 是一个指向函数的指针类型,其所指向的函数具有一个 int 类型的参数,并且函 数返回一个 int 类型的数据。 2) Altera 为用户提供了简单的 Flash 访问(Simple Flash Access)和细粒度 Flash 访问 (Fine-Grained Flash Access) 。一般情况下,使用细粒度 Flash 访问函数, 比简单的 Flash 访问也复杂不了多少, 但是可以避免通常的跨越擦除问题。 Flash 是按照 Block 组织起来的, 通常一次擦除一整个块的内容。

3. 遇到的问题及解决方法
1) 在 NIOS ii 工程中最后编译时,最好只保留一个硬件平台,以免出错。 2)在 NIOS 开发过程中,FLASH 繁琐的擦写过程 ALTERA 都已经做好了,它通过 API 给我们提供了完善的读写函数, 我们只需要调用函数就可以完成读写 FLASH 的操作。 但是, 使用这种方法操作的 FLASH 也必须要满足 CFI 标准或者 EPCSX 串行 FLASH 标准。 3)在锁定器件的引脚时,注意每个引脚的功能及其连接方式。比如 FL_CE_N 应该锁 在 FLASH 的使能端,FL_OE_N 应该锁在 FLASH 的 Read 端。一旦锁错引脚,将导致编译 时出现引脚不匹配的问题,因此无法进行后续工作,锁引脚时,一定要仔细。 4)在搭建系统时,一定要给 FLASH 加入复位端,使 FLASH 能正常工作。 5)每次下载硬件之前,检查是否已经将引脚锁定为了输入三态,同时,保证加入的是 已经修改好的.ptf 文件。 6)对端口基址的定义方式: Eg:#define led *(volatile char *) LED_BASE Unsigned short * ram = (volatile char *) (SDRAM_BASE+0x1000) 说明: 由于我们使用的是 16 位的数据总线,所以将指针类型也设置成 Unsigned short。 在基址 SDRAM_BASE 后加上 0x1000,是因为运行程序时本来就会用到一部分空间, 我们必须避免使用这部分空间来做其它操作,以免运行出错。但是 0X1000 并不是一个固定 值。 7) 其中的 volatile 是一种类型修饰符, 优化器在用到这个变量的时候必须小心的重新读 取这个变量的值,而不是使用保存在寄存器中的备份,在并行设备的硬件寄存器(如状态寄 存器等) ,一个中断服务子程序中会访问到的非自动变量,和多线程应用中的被几个任务共 享的变量等等,都需要定义为 volatile。 8)在检测 SDRAM 的 C 语言程序中,memset()函数的正确使用问题: 比如 memset(ram,0,100) ,是表示向已开辟的内存空间 ram 的开始 100 字节的值设 置为 0。 9)SDRAM 时钟的选择问题: 在设置 PLL 时,根据系统所提供的时钟大小,通过计算得出 SDRAM 相对于基准时钟
西南科技大学 信息学院 08 级 林正红

的相位差,对于 SDRAM 的正常工作,是一个很重要的问题。具体实现如下: SDRAM 的时钟周期会受到 SDRAM 的读和写操作的影响,其中,读写均有滞后和超 前时间,我们根据《Embedded Peripherals IP User Guide》手册中的说明, Maximum Lag = minimum(Read Lag, Write Lag),消极的作用; Maximum Lead = minimum(Read Lead, Write Lead).积极的作用; 例如: Read Lag = 8.107 ns, (且 Read Lag)>Write Lag) Read Lead = 1.399 ns , (且 Read Lead)>Write Lead) 我们使用时,取它们的中间值(均值)即可: (–8.107 + 1.399)/2 = –3.35 ns. 且:基准时钟 100MHz,周期为 10ns。 再根据 SDRAM 的时钟周期,可以计算出它相对于基准时钟的相位差是-70°左右,这 里我取的是-75°。 10)对 FLASH 操作时,需要注意一下问题: 在对其写入内容之前,必须擦除整个 FLASH 内存;擦除整个 FLASH,内存大约需要 20ns;而且在对 FLASH 进行读写操作时,不能关闭 DE2 的控制面板,防止芯片被损坏。 11)在对 FLASH 的读写操作程序中,最开始就没有加上#include "sys/alt_flash.h"和 #include "sys/alt_flash_dev.h"这两个头文件,我调了很久程序都有问题,总是 FLASH 的相关 函数出现问题, 最后发现在程序的头文件中包含的内容与需要的不匹配, 最后经过上网查询 资料,才发现应该调用#include "sys/alt_flash.h"和 #include "sys/alt_flash_dev.h"。再次编译程 序 后 , 就 能 正 确 读 写 了 。 网 址 为 : http://hi.baidu.com/hsyl/blog/item/bcb1dbb4d18cdd7f8ad4b25e.html/cmtid/1dc1314e81fd07c4d0c 86ad8,真的要感谢这篇文章的作者,提醒我解决了这个问题。 以上是我自己在做这个系统的时候遇到过的主要问题,希望对大家有所帮助。

4. 实验总结
1)SOPC 系统有很多优点:一方面,它是可编程片上系统,即由单个芯片完成整个系 统的主要功能,并具备软硬件系统可编程的能力;另一方面,它内嵌了处理器 IP 核,具有 灵活的设计方式,用户可根据需要随意配置、构建、裁剪处理器 IP 核。 2)目前最具有代表性的 IP 软核嵌入式处理器是 Altera 的 Nios II 软核。 Nios II 嵌入式 CPU 是一种专门为 SOPC 设计应用而优化的 CPU 软核。NIOS II 是一个用户可配置的通用 放入 32 位 RISC 嵌入式处理器,它是 SOPC 的核心。它的处理器以软核形式实现,具有高 度的灵活性和可配置性。NIOS 的开发包括硬件开发和软件开发两部分。硬件开发是在 Quartus II 中实现的,而软件开发部分是在 NIOS IDE 软件中实现的。 3) 做完这两个实验以后, 我熟悉了 Quartus II 和 Nios II IDE 软件的操作, SDRAMHE 对 和 FLASH 存储器的工作有了一定的了解,同时,还锻炼了一下自己的自学能力。现在更加 觉得,对自己所做事情做一个定期的整理记录,是很有必要的。

西南科技大学 信息学院 08 级 林正红

5. 附录 5.1 主要参考网站
[1] ( 笔 记 )NIOS II 软 核 中 EPCS 配 置 芯 片 的 存 储 操 作 NIOS Flash 读 写 操 作 : http://hi.baidu.com/hsyl/blog/item/bcb1dbb4d18cdd7f8ad4b25e.html/cmtid/1dc1314e 81fd07c4d0c86ad8 [2] 高手进阶,终极内存技术指南——完整/进阶版: http://stor-age.zdnet.com.cn/stor-age/2004/0218/399648.shtml

5.2 参考文献
[1]《nios 那些事儿.pdf》 [2]《Embedded Peripherals IP User Guide.pdf》 [3]《DE2_资料.pdf》

5.3 工程和源代码
近期学习总结\SOPC_SDRAM3

西南科技大学 信息学院 08 级 林正红


赞助商链接