snifer

[原创]基于ADI ADuC7124 精密模拟微控制器中断模拟

0
阅读(4285)

ADuC7124是一款完全集成的1 MSPS、12位数据采集系统,在单芯片内集成高性能多通道ADC、16位/32位MCU和Flash/EE存储器。

ADuC7124内置一个高级中断控制器。该矢量中断控制器(VIC)可以为每个中断指定一个优先级。它还支持嵌套中断,每个IRQ和FIQ最多允许8级嵌套。如果将IRQ和FIQ中断源合并,则可以支持总计16级嵌套中断。

今天我就写一下 ADuC7124 的一个中断实现,主要应用于一个医疗设备的温度传感器数据的接受,项目要求保密,拿了点保密费用,暂时就不详细说这个项目了,我主要用模拟及程序的形式介绍一下这个芯片的中断应用。

在我的很多博客里中提到了中断的原理,今天主要写一下具体的应用。

现在我把整个中断流程用一个图加以说明:

以上这个图清楚地说明了一个中断异常处理流程。
下面用INT_TIMER0, INT_TIMER2 和INT_UART0 三个中断完整地介绍一次中断异常处
理。首先我们得做几个假设:
假设1:这三个中断的屏蔽被取消。
假设2:PRIORITY寄存器中ARB_MODE2,ARB_MODE5皆为0,既不进行优先级的自动旋转排序,任何时候ARBITER2,ARBITER5控制的中断组优先级次序分别为0-1-2-3-4-5和1-2-3-4。

假设3:这三个中断皆为IRQ类型。
假设4:这三个中断同时被触发。
INT_TIMER0, INT_TIMER2和INT_UART0三个中断被同时触发,此时三个中断信号流向SRCPND寄存器,使该寄存器中的第10位,12位,28位被置为1,中断信号继续向前流经INTMASK 寄存器,这三个中断都没有被屏蔽,于是信号进一步流经INTMODE寄存器,这三个中断皆为IRQ类型,故中断信号继续向前流向PRIORITY寄存器,经过优先级判断,INT_TIMER0中断信号使INTPND 寄存器的第10位置1(INT_TIMER0优先级最高),此时INTOFFSET 寄存器的值为10,CPU转向相应的中断服务例程进行处理。处理完毕后,我们的程序将INTPND和SRCPND的第10置为0,至此INT_TIMER0中断处理完毕。时SRCPND 的第12位,28位仍为1(这两个中断请求未被处理),故他们会继续被CPU已刚才描述的方式进行处理。

具体程序代码 ADuC7124-int.c 重要代码说明如下:

#define DEVICE_NAME "ADuC7124 int"
#define ADuC7124_IRQ3 IRQ_EINT3 //IRQ_EINT3  //定义为中断3
#define GPIO_key_int01 (GPIO_MODE_IN | GPIO_PULLUP_DIS | GPIO_F3) //GPIO_F3为GPF3,设置为1表示为中断3
//两位代表一个引脚,一个数据位对应一个输出引脚
//用GPC5来控制LED0,GPC6来控制LED1,GPC7来控制LED2
#define led01_enable() \
({ GPCCON &=~ 0xc00; \  //将控制字段的 第11位置为1表示output模式
GPCCON |= 0x400; \
GPCDAT&=~ 0x20; \
GPCDAT |= 0x0; \
})
#define led01_disable() \
({ GPCDAT&=~ 0x20; \ //使得GPCDAT的输出位置高,使得片选无效
GPCDAT |= 0x20; \
})

#define led02_enable() \
({ GPCCON &=~ 0x3000; \  //使得GPC6置为1,表示为output模式
GPCCON |= 0x1000; \
GPCDAT&=~ 0x40; \  //输出低电平,使得片选选通
GPCDAT |= 0x0; \
})
#define led02_disable() \
({ GPCDAT&=~ 0x40; \ //此位设置为高,片选无效
GPCDAT |= 0x40; \
})
#define led03_enable() \
({ GPCCON &=~ 0xc000; \  //使得GPC7置为低,表示GPC7为output模式
GPCCON |= 0x4000; \
GPCDAT&=~ 0x80; \
GPCDAT |= 0x0; \
})
#define led03_disable() \
({ GPCDAT&=~ 0x80; \  //使得GPC7置为高,LED3无效
GPCDAT |= 0x80; \
})
static void s3c2410_IRQ3_fun(int irq, void *dev_id, struct pt_regs *reg)
{
unsigned char byte;
int i =0 ;
DPRINTK("enter interrupt 3 !\n");
for (i=0;i<2;i++)
{
led01_enable();//此时LED1有效,如果此时外部有操作写入数据到GPCDATA,那么将会
输出
mdelay(800);
led01_disable();//l拉高,置为无效。
mdelay(800);

led02_enable();//此时LED2有效,如果此时外部有操作写入数据到GPCDATA,那么
输出
mdelay(800);
led02_disable();//l拉高,置为无效。
mdelay(800);
led03_enable();//此时LED3有效,如果此时外部有操作写入数据到GPCDATA,那么
输出
mdelay(800);
led03_disable();
}
}
static int __init s3c2410_interrupt_init(void)
{
int i, ret;
int flags;
//set_gpio_ctrl(GPIO_MCP2510_CS);
//printGPE();
//printSPI();
//printRegisters();
set_gpio_ctrl(GPIO_key_int01);//先设置GPIO口。
led01_disable();//先将LED置为无效状态。
led02_disable();
led03_disable();
for (i=0;i<2;i++)
{
led01_enable();
led02_enable();
led03_enable();
// printk(DEVICE_NAME"GPCCON:%x\t GPCDAT:%x\t\n", GPCCON, GPCDAT );
mdelay(500);
led01_disable();
led02_disable();
led03_disable();

// printk (DEVICE_NAME"GPCCON:%x\t GPCDAT:%x\t\n",GPCCON, GPCDAT );
mdelay(500);
}
local_irq_save(flags);
/* Register IRQ handlers */

需要说明的是这个程序经过修改以后能用于很多中断程序的开发,自己比较满意吧,现在项目进展比较顺利,我负责这一部分已经提交了,感谢大家。