<3> 设备驱动程序
其实,“总线仲裁器”也可看作一种硬件控制器,只不过它管的不是具体的硬件,而是负责数据的传输。那么它也有自己的设备驱动,封装了总线操作的细节。既然总线是现成的,我们秉承“拿来主义”的原则,甭管它怎么实现的,会用就行。
例如,数码管设备驱动要把数据“5”和“显示”命令传给数码管控制器,设计两个函数,由于数据和命令的传递必须经过总线,那么需调用总线驱动函数IOWR(基地址, 偏移量, 数据),另外,读取寄存器用到IORD(基地址, 偏移量),这两个函数在<io.h>里。
<io.h>的路径是"..aLTErakits ios2_60componentsaltera_ NIOS 2HALinc"。
至此,“桥”搭完。
函数功能从字面上很好理解。刚才定义两个寄存器时,data_reg在前面,所以偏移量是0,cmd_reg在后面,偏移量是1。××_REG_MSK称 为掩码, Avalon总线 数据接口共32位,但我们设计的data_reg位宽是3,cmd_reg位宽为1,掩码的作用在于告知寄存器宽度,知道就行, 实际上用不着。××_REG_OFST是寄存器内的偏移量,这里同样用不着,先写上吧。
OK,我们的数码管设备驱动文件正式出炉了,看看是不是简洁明了很多啊?
<4> 硬件抽象层(HAL)
设备驱动程序封装的仅仅是对某个寄存器的一次读写操作,功能单一,需要在硬件抽象层再做一次封装。
直接将这些函数列出来,一目了然,不作多余的解释了。
至此,“桥”搭完。
接下来在把我们的“数码管控制器”加入sopc builder系统中。
现在几乎所有讲nios的书都会提及自定义用户外设,而且用的都是altera官方提供的例子PWM,本文的“数码管控制器”就是照着它依葫芦画瓢改过来 的,呵呵,惭愧惭愧,之所以想改它,一是因为它用的是verilog而不是 VHDL ,而大多数人先接触却是VHDL;二来PWM的显示效果似乎不太明显, 改成数码管显示相对比较有成就感;第三,PWM的逻辑稍微有一点点复杂,我们的重点在于说明怎样自定义外设,当然例子越简单越好。
既然是照着PWM原样改的,所以本文工程的结构与之保持高度一致,将其加入sopc builder的步骤也差不多,这里我就不再码字了,各位照着书上做吧:
《SOPC嵌入式系统基础教程(周立功等著)》第8章……
再接下来,建立一个包含“数码管控制器”的nios系统,并编写应用程序,实现从0到9计数。
贴张官方的nios设计流程图,看起来很漂亮是吧,不愧是altera的东西,大而全而不乱。
先说最中间的"SOPC Builder",它的任务是建立一个“以Nios CPU为核心,以Avalon总线为纽带,将各种硬件设备连接起来”的nios系统;这个系统要在FPGA中运行,所以必须挂靠一个Quartus II工程,用左边的Quartus II进行分配引脚等等工作,生成硬件系统;接着,右边的Nios II IDE就可以在这个硬件系统上设计应用程序了;最后将硬件系统和软件程序分别下载到FPGA芯片上,大功告成。
下面step by step
<1> Quartus II 新建一个工程名,工程名"DE2_SEG7"。
<2> "Tool" → "SOPC Builder" 打开SOPC Builder。
<3> "System Name": nios2_system 选VHDL。
一个包含“数码管控制器”的最小系统至少由3部分组成:CPU必不可少,RAM存储代码,还有刚才设计的"seg7_avalon"。
<4> 加入"Nios II Processor",选"Nios II/e",精简型够用了。
<5> 加入"On-Chip Memory",类型选"RAM",位宽默认"32 bits","Total Memory"选"48Kbytes",等会儿软件要占用四十多K空间。
<6> 加入"seg7_avalon"。
<7> 将这三个组件的名称改好看点,然后设定RAM的基地址为"0x00000000",再右键锁定基地址,如图:
为什么要锁定RAM的基地址为0呢?点选第二个选项卡,可以看到"Reset Address"对应着RAM,系统的复位肯定要从地址0开始。
<8> 由于刚才人为改动了地址分配,弄乱了,让系统自动再分配一次,当然被锁定的RAM基地址是不会变的。"System" →"Auto-Assign Base Addresses"。最终系统组件列表如下:
注意,seg7的地址范围是"0x00010800"→"0x00010807",占8个地址,nios系统的地址按字节分配,也就是说,每个字节占用一 个地址,数码管控制器中定义了两个寄存器,avalon总线规定每个寄存器占32位(实际上是不是32位它就不管了,反正按最大32位分配),这样两个寄 存器共占去8个字节,自然需要8个地址。
<9> 点击"Generate"生成nios系统,回到Quartus II。
<10> 新建一个顶层文件"File"→"New"→"BLOCk Diagram/SchematIC File",引入nios II系统,增加输入输出引脚。然后,"Assignment"→"Import Assignment",添加引脚分配文件(在DE2光盘目录下的DE2_tutorialsdesign_files DE2_PIN_assignments.csv),改动顶层文件的引脚名称使其与.csv文件中保持一致。
<11> 编译,查看编译报告,可见,48K的RAM占用了芯片83%的memory bits,差不多耗光了。
<12> 硬件部分已经搞定,关掉Quartus II,打开Nios II IDE,切换到工作目录下。
<13> "File"→"New"→"C/C++ Application","SOPC Builder System"选择"nios2_system.ptf"(就是刚才Generate Nios II系统生成的东东),再选模板"Hello World"(纯属偷懒 ),顶上的"name"改成"seg_example","Finish"。
<14> 改动hello_world.c,代码的功能为:先初始化数码管,等待2秒钟,再进行0-9的循环,循环过程中穿插2秒钟的清屏。SEG7_BASE的宏 定义在system.h中,实际上就是在SOPC Builder中的seg7_avalon的基地址0x00010800。
<15> "Project"→"Build Project",得到编译报告,软件占用了7K空间……
<16> 下载到DE2板上,运行,数码管不停地闪啊闪。
OK,从硬件到软件的一条龙讲完了。