- UID
- 872235
|
与外设通信,PIO中断是必不可少的,比如,为了与ENC28J60高效沟通,必须能捕捉到ENC28J60发出的中断信号。
NoisII的PIO模块提供两种中断方式,参考Embedded Peripherals IP User Guide中的PIO核一节
Interrupt
Turn on Generate IRQ to assert an IRQ output when a specified event occurs on input
ports. The user must further specify the cause of an IRQ event:
■ Level— The core generates an IRQ whenever a specific input is high and
interrupts are enabled for that input in the interruptmaskregister.
■ Edge— The core generates an IRQ whenever a specific bit in the edge capture
register is high and interrupts are enabled for that bit in the interruptmask
register.
When Generate IRQis off, the interruptmask register does not exist
由于ENC28J60发出的中断是下降沿,参考ENC28J60的手册。
所以本文也以捕捉下降沿中断为研究对象。
首先在构建NiosII时,加入能捕捉下降沿中断的PIO Core,如下图示:
然后在EDS中输入下面的程序:
#include //用到printf()函数
#include "altera_avalon_pio_regs.h" //读写IO寄存器相关函数
#include "sys/alt_irq.h" //NoisII中断处理相关函数,这里遵循增强型中断风格以向后兼容
void KeyIn_Init(void); //键盘中断初始化函数申明
void KeyIn_ISR(void* isr_context);//键盘中断服务函数申明
int keycount = 0; //记录Key按下次数
unsigned int keyin_isr_context;
int main()
{
KeyIn_Init();
while(1)
{
IOWR_ALTERA_AVALON_PIO_DATA(LEDEDGE_BASE,keycount%2);
}
return 0;
}
void KeyIn_Init(void)
{
void* isr_context_ptr = (void*) &keyin_isr_context;
//清中断捕获寄存器
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(EDGEINPUT_BASE, 0x01);
//使能中断
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(EDGEINPUT_BASE, 0x01);
alt_ic_isr_register
(
EDGEINPUT_IRQ_INTERRUPT_CONTROLLER_ID, // 中断控制器标号,从system.h复制
EDGEINPUT_IRQ, // 硬件中断号,从system.h复制
KeyIn_ISR, // 中断服务子函数
isr_context_ptr, // 指向与设备驱动实例相关的数据结构体
NULL // flags,保留未用
);
}
void KeyIn_ISR(void* isr_context)
{
//应答中断,将Edgecapture寄存器清零;写1清零
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(EDGEINPUT_BASE,0x01);
keycount += 1;
}
总结:1,当Interruptmask和edgecapture位同时为1时,PIO core将向System Interconnect Fabric发送IRQ
2,若不清掉edgecapture, 则PIO core产生的IRQ一直有效,这使得CPU一直在响应中断,感觉是程序跑飞或跑死了
3,在使能interruptmask时,必须先清一次edgecapture,为了防止edgecapture为1,一旦使能interruptmask,则马上产生中断。虽然在Reset后,edgecapture的每个位会被清零,这样做显得有些多此一举,但我认为把清edgecapture,放在使能interruptmask前面比放在后面好 |
|