主要参考
http://blog.ednchina.com/summerooooo/1770874/message.aspx
在本例中不通过pio,直接自定义外设控制irq信号,实现中断处理。
硬件部分:
自定义一个简单的键盘控制器,按下FPGA板上的键盘就产生irq中断信号。
其源代码如下:
- module buttoncontroller(buttonin,clk,reset_n,chipselect,address,read,write,readdata,writedata,byteenable,irq);
-
input buttonin,clk,reset_n,byteenable,chipselect,read,write;
-
input address;
-
input [31:0] writedata;
-
output [31:0] readdata;
-
output irq;
-
-
reg buttonin_0,buttonpush,irq;
-
-
initial
-
begin
-
irq=0;
-
end
-
-
always@(posedge clk)
-
begin
- buttonin_0=buttonin;
-
end
-
-
always@(posedge clk)
-
begin
- if(buttonin_0 && !buttonin)
- buttonpush=1;
-
else
- buttonpush=0;
-
end
-
-
always@(posedge clk)
-
begin
- if(chipselect && write && address==0)
- irq=0;
- else if(buttonpush)
- irq=1;
-
-
end
-
-
endmodule
在上述代码中,只要按下按键,buttonin则为0。buttonpush产生一个周期的高电平,表示按下一次按键。此时irq被置1。但当进入中断处理程序时,会对控制器发出写请求以使irq清0。
对irq清0是非常重要的,因为irq的持续周期不好确定。如果太长会使cpu一直在处理中断。而如果太短则可能不会触发中断处理程序。因此本例中使用的方法是在进入中断处理程序后,对控制器发出写请求以使irq清0。
进入sopc builder后在自己的系统中加入自定义的外设。
其中各信号类型设置如下:
信号接口如下:
最后完整的sopc系统如图:
绑定管脚后编译即完成了硬件系统。
软件系统:
软件代码如下:
- #include <stdio.h>
-
#include <io.h>
-
#include "system.h"
-
#include "alt_types.h"
-
#include "sys/alt_irq.h"
-
-
void button_isr(void* context, alt_u32 id)
-
{
-
IOWR(BUTTONCONTROLLER_0_BASE,0,0);
-
printf("you have pushed %d times\n",++(*((int *)context)));
- //最好还是不要在中断处理程序里使用printf这样的不可重入函数
-
}
-
-
int main()
-
{
-
volatile int i=0;
-
alt_irq_init(ALT_IRQ_BASE);
-
if(!alt_irq_register(BUTTONCONTROLLER_0_IRQ,&i,button_isr))
-
printf("the irq is set\n");
-
printf("oh yeah\n");
-
while(1);
-
return 0;
-
}
注意在中断处理程序中:
1,如果使用变量,变量类型必须为volatile。确保每次都从内存中获得该变量值。
2,不能使用printf这样的不可重入的函数,否则可能死锁。
编译运行后,按下按键则产生如下结果:
使用signal tap捕捉到的按下按键时的信号如下:
阅读(4277) | 评论(0) | 转发(0) |