(转)SOPC系统自定义外设之:软件设计
原文地址:http://www.cnblogs.com/nick123/archive/2009/05/09/1453422.html
完成自定义外设的硬件设计后,就需要编写软件来测试外设的设计是否正确了。
在这之前首先要弄清楚Nios II中的地址对齐,对Avalon slave来说,有两种地址对齐方式:动态地址对齐和静态地址对齐。
动态地址对齐:动态地址对齐可以自动适应和Avalon master端口宽度不同的器件,而同时保持地址增长的方式是以字节为单位增长的方式。匹配不同端口宽度的master和slave时使用动态地址对齐方式可以得到一个连续的存贮器空间。但动态地址对齐在读操作的时候有附作用。当一个32位Nios II core读一个8位宽的slave时,物理会产生4次8位的读操作,而读一个16位宽的slave时,则要产生2次的读操作。大部分寄存器类型的外设不能容忍这种附作用,所以动态地址对齐一般不适合用于寄存器外设,主要用于存贮器。如果外部存贮器的宽度大于8位时,比如16位或32位,则必然有字节使能信号,以便进行字节粒度的写操作。所以在为这些存贮器做接口的时候,如果采用动态地址对齐的方式,则一定要连接字节使能信号。
静态地址对齐:静态地址对齐的地址增长单位是Avalon master的端口宽度,每次读写都只对应一次操作没有什么附作用。但在匹配不同端口宽度的master和slave时,地址不能自动调整,某些地址没有相应的物理实体和它对应。当一个32位的Nios II core读一个8位宽的slave时,其获得的32位数据低8位从slave获取,而高24位则没有定义。同样,当它读16宽的slave时,其获得的32位数据低16位从slave获取,而高16位则没有定义。当Nios II core想继续读下一个8位(或16位)时,则需要增长字节地址4。除非你一定需要一个连续的地址空间,否则使用静态地址对齐方式是比较保险的方式。
在刚调试期间遇到这样一个问题:用IOWR(KEYBOARD_BASE,2,0);清楚irq中断信号,在用SignalTap II逻辑分析仪始终抓不到write信号,一直保持低电平,后来用IOWR(KEYBOARD_BASE,0,0)就能抓到write信号了。我想一定是地址对齐的问题,然后打开SOPC Builder,准备地址对齐对齐方式,可是始终没有看到那一项,以前6.0版本是有这个选项的。折腾了我一天,后来只好硬着头皮看Altera官方文档,终于找到答案了。
于是决定找到源文件,改代码,在生成的key_hw.tcl中
#set_interface_property avalon_slave addressAlignment DYNAMIC
set_interface_property avalon_slave addressAlignment NATIVE
注释掉DYNAMIC,改成NATIVE。
重新编译,问题就不服存在了,用SignalTap II成功到捕捉write信号
测试源程序如下:
2 #include <stdio.h>
3 #include <io.h>
4 #include "alt_types.h"
5 #include "sys/alt_irq.h"
6 static void key_isr(void* context, alt_u32 id);
7 volatile int irq_capture;
8 int main (void) __attribute__ ((weak, alias ("alt_main")));
9 int alt_main (void)
10 {
11 alt_irq_init(ALT_IRQ_BASE); //使能中断
12 alt_irq_register(KEYBOARD_IRQ,NULL , key_isr);//注册中断服务程序
13 while (1);
14 return 0;
15 }
16 static void key_isr(void* context, alt_u32 id)
17 {
18 irq_capture = IORD(KEYBOARD_BASE,1);
19 IOWR(KEYBOARD_BASE,2,0);
20 printf("key_value:%d\n",irq_capture);
21 }
22
为了能弄清楚中断的工作流程,决定进行单步调试。但必须先知道中断时如何控制和执行的。
中断由三个寄存器控制:state,ienable,ipending。
state:最后一位PIE,中断开关,1:中断使能。0:禁止外部中断
ipending:32位,第n位为1则表示正在处理第n个中断。
ienable:32位,每1位对应1个外部中断源的使能位,若第n位为1,则使能对应的中断,为0则禁止对应的中断。
注意,ienable变成了0x4,联想到上一篇(原创)SOPC系统自定义外设之:硬件设计,中断号为2,表示键盘中断已经使能。
还有一个就是终端向量表alt_irq,一共有32个,每一个对应一个中断优先级,如果中断注册成功,就会向中断向量表里面写入ISR和context
如上图,alt_irq[2]的handler指向key_isr()中断服务程序,中断注册成功!
Context为全0,因为程序在注册中断服务程序时设置的context参数为NULL。
alt_irq_active是一个32位的全局变量,当某个中断被使能后,对应位就为1。
开始硬件上运行程序,让程序执行key_isr()中断服务程序。在按键时,输出如下:
中断服务程序成功执行!!
经过这次自定义外设软硬件的调试,实在是让人感叹SOPC的灵活性!