Nios中PIO的INT
初涉nios中的INT,开始做的时候中断虽然正常的产生了,但是debug发现初始化木有成功的返回值,main函数中代码:
if(!init_KEY1())
{
printf("interupt register successfully!\n");
}
else
{
printf("Error: interupt register failed!\n");
}
while(1);
中断能正常产生,这说明初始化一定好了。但是那两个printf都木有打出来,还为这个苦恼了一会儿。咱不能光初始化了以后啥事儿都跑到ISR里做吧,嗯!问题一定得解决的。
后来看到了http://www.cnblogs.com/crazybingo/archive/2011/04/03/2004477.html#2356430这篇文章,真是一下点醒了我,以前做ARM时,记得在有INT初始化时,一定要clear pending bit的,否则直接挂掉了(ARM中进入ISR也要有这步的)。
最后问题解决了,写点东西,做个备份吧,如果还能帮上别人,那更好了。如果有异议,希望大家指教。
做的是4bit PIO接4个按键,任何一个按下都会有独立的LED响应(4个LED也用4bit的PIO接的)。4个键不能冲突,没有中断嵌套。贴上源码:
SOPC.h
1 #ifndef SOPC_H_
2 #define SOPC_H_
3
4 #include "system.h"
5
6 #define _LED
7 #define _KEY
8
9
10 typedef struct
11 {
12 unsigned long int DATA;
13 unsigned long int DIRECTION; // 0-> input; 1->output
14 unsigned long int INTERRUPT_MASK; // 1-> enable the INT
15 unsigned long int EDGE_CAPTURE;
16 }PIO_STR;
17
18 #ifdef _LED
19 #define LED ((PIO_STR*)PIO_LED_BASE)
20 #endif
21
22 #ifdef _KEY
23 #define KEY ((PIO_STR*)PIO_KEY_BASE)
24 #endif
25
26 #endif /*SOPC_H_*/
main.c
1 /********************************************************************
2 * enable bit cleaning for PIO-key-INT
3 *
4 * when any of the 4 key is down,interrupt will occured,and check the
5 * edge-capture-register to determine which key is down
6 *
7 * during INT register initial, bit clean should be done once.
8 * During ISR,bit clean should NOT be done(Line 48);INT disable/enable is useless(Line 41/72).
9 *
10 *
11 * 2012-4-16 Lefroy Guo
12 *
13 ********************************************************************/
14
15 #include <stdio.h>
16 #include "../inc/sopc.h"
17 #include <system.h>
18 #include <unistd.h>
19
20 //*******************************************************************
21
22
23 // comment this line because there is no need to store key pressed imformation
24 //unsigned int key_flag = 0x0; // 4bit for 4 key. 0->UP, 1->DOWN
25
26 void blink(unsigned int times)
27 {
28 unsigned int i;
29 for(i=0;i<times;i++)
30 {
31 LED->DATA = 0xf;
32 usleep(50000);
33 LED->DATA = 0x0;
34 usleep(50000);
35 }
36 }
37
38 void ISR_KEY(void *context,unsigned long id)
39 {
40 unsigned int i;
41 KEY->INTERRUPT_MASK = 0x0; // disable INT
42 usleep(20000); // delay 20ms
43 for(i=0;i<4;i++)
44 {
45 if(((KEY->EDGE_CAPTURE>>(3-i))&1) == 1)
46 {
47 // (3-i)bit of key 's INT is occur,without knowing posedge or negedge!
48 // KEY->EDGE_CAPTURE |= 1<<(3-i); // Should NOT be done
49 if(((KEY->DATA>>(3-i))&1) == 0)
50 {
51 // (3-i)bit of key is down
52 // ((key_flag>>(3-i))&1) |= 1;
53 // mark key_flag (3-i) bit to 1, meaning this bit(3-i) of key is down
54 LED->DATA |= 1<<(3-i);
55 // set corresponding bit of led to high
56 }
57 else
58 {
59 // (3-i)bit of key is down
60 // ((key_flag>>(3-i))&1) &= 0;
61 // mark key_flag (3-i) bit to 0, meaning this bit(3-i) of key is up
62 LED->DATA &= ~(1<<(3-i));
63 // set corresponding bit of led to low
64 }
65 }
66 // else
67 // {
68 // // (3-i)bit of key 's INT is NOT occur, nothing happend to this bit key
69 // }
70
71 }
72 KEY->INTERRUPT_MASK = 0xF; // enable INT
73 }
74
75 int init_KEY(void) // Declaration the KEY_INT's ISR
76 {
77 KEY->INTERRUPT_MASK = 0xF; // enable INT
78 KEY->EDGE_CAPTURE = 0xF; // clear all pending bit
79 return alt_irq_register(PIO_KEY_IRQ,NULL,ISR_KEY);
80 }
81
82 void main()
83 {
84 printf("*************************************************\n");
85 blink(3);
86 init_KEY();
87 usleep(1000000);
88 blink(3);
89
90 while(1);
91 reture(0);
92 }
结论: INT初始化中,必须要先enable了再clear一下,否则挂掉!个人感觉这点最关键了,以前做ARM也是这样(都是RISC还挺像的);
ISR里,不用clear,进去时先disable了,出来时再enable了(这点貌似没区别,但养成这习惯了,呵呵)。如果clear了,中断响应有问题!