?? isr.c
字號(hào):
/***************************************************************************\
Copyright (c) 2004-2007 threewater@up-tech.com, All rights reserved.
by threewter 2004.5.12
\***************************************************************************/
/***************************************************************************\
#說(shuō)明:中斷處理函數(shù)
#接口函數(shù)
---------------------------------- Bug --------------------------------------
---------------------------------- TODO list --------------------------------------
2004-5-12 對(duì)于邋IO口的多中斷源的共享
----------------------------------修正--------------------------------------
2004-5-12 1、移植
2、改變了中斷函數(shù)的定義,添加了一個(gè)標(biāo)志中斷號(hào)的參數(shù)
3、添加了void ISR_Init(void)函數(shù)定義,系統(tǒng)初始化中斷的時(shí)候調(diào)用
\***************************************************************************/
#include "../inc/reg2410.h"
#include "../uhal/isr.h"
#include "../inc/macro.h"
#include <string.h>
//#include <intrinsics.h>
extern void INTS_OFF(void);
extern void INTS_ON(void);
typedef void (*mask_func_t)(unsigned int);
typedef struct{
Interrupt_func_t InterruptHandlers;
void* data;
int valid; //設(shè)置中斷1=有效0=無(wú)效
mask_func_t mask;
mask_func_t unmask;
mask_func_t ack_irq;
}struct_InterruptFunc;
static struct_InterruptFunc InterruptFunc[NR_IRQS]={NULL,};
#define GetISROffsetClr() rINTOFFSET
#define ClearPending(x) do{rSRCPND = (1u << (x)); rINTPND = rINTPND;}while(0)
#define EINT_OFFSET(x) ((x) - NORMAL_IRQ_OFFSET + 4)
#define SUBIRQ_OFFSET(x) ((x) - EXT_IRQ_OFFSET)
#define EXTINT_MASK 0x7
//--------------------------------IRQ for s3c2410---------------------------------//
void INTS_OFF()
{
asm("mrs r0, cpsr"); // current CSR
asm("mov r1, r0"); //make a copy for masking
asm("orr r1, r1, #0xC0"); // mask off int bits
asm("msr CPSR_cxsf, r1"); // disable ints (IRQ and FIQ)
asm("and r0, r0, #0x80"); // return FIQ bit from original CSR
asm("mov pc,lr"); //return
}
void INTS_ON()
{
asm("mrs r0, cpsr"); //current CSR
asm("bic r0, r0, #0xC0"); // mask on ints r0高兩位清零
asm("msr CPSR_cxsf, r0"); // enable ints (IRQ and FIQ)
asm("mov pc,lr"); // return
}
/*
static int fixup_irq_num(int irq)
{
if (irq < IRQ_EINT4) return irq;
else return ((irq + 4) - NORMAL_IRQ_OFFSET);
}
*/
/*
static void set_gpios(int irq, int pullup)
{
int shift;
if (irq < 8) {
shift = 2*irq;
rGPFCON &= ~(0x3 << shift);
rGPFCON |= (0x2 << shift);
//GPFUP &= ~(GRAB_PULLUP(pullup) << irq); modify by threewater
rGPFUP &= ~(1<< irq);
rGPFUP |= (GRAB_PULLUP(pullup) << irq);
} else {
shift = 2*(irq - 8);
rGPGCON &= ~(0x3 << shift);
rGPGCON |= (0x2 << shift);
//GPGUP &= ~(GRAB_PULLUP(pullup) << (irq - 8));
rGPGUP &= ~(1<< (irq - 8));
rGPGUP |= (GRAB_PULLUP(pullup) << (irq - 8));
}
}
*/
/*int set_external_irq(int irq, int edge, int pullup)
{
int real_irq, reg_ofs, shift;
volatile U32 *extint = &rEXTINT0;
if (((irq < IRQ_EINT0) && (irq > IRQ_EINT23)) ||
((irq > IRQ_EINT3) && (irq < IRQ_EINT4)))
return FAIL;
real_irq = fixup_irq_num(irq);
set_gpios(real_irq, pullup);
reg_ofs = (real_irq / 8);
shift = 4 * (real_irq - 8 * reg_ofs);
extint += reg_ofs;
*extint &= ~(EXTINT_MASK << shift);
*extint |= (edge << shift);
if (irq < 4) {
rSRCPND |= (1 << real_irq);
rINTPND |= (1 << real_irq);
} else {
rEINTPEND |= (1 << real_irq);
}
InterruptFunc[irq].valid=1;
return 0;
}*/
/*
* Defined irq handlers
*/
static void ack_irq(unsigned int irq)
{
rSRCPND = (1 << irq);
rINTPND = (1 << irq);
}
static void mask_irq(unsigned int irq)
{
rINTMSK |= (1 << irq);
}
static void unmask_irq(unsigned int irq)
{
rINTMSK &= ~(1 << irq);
}
/* for EINT? */
static void EINT4_23ack_irq(unsigned int irq)
{
irq = EINT_OFFSET(irq);
rEINTPEND = (1 << irq);
if (irq < EINT_OFFSET(IRQ_EINT8)) {
ClearPending(SHIFT_EINT4_7);
} else {
ClearPending(SHIFT_EINT8_23);
}
}
static void EINT4_23mask_irq(unsigned int irq)
{
irq = EINT_OFFSET(irq);
rEINTMASK |= (1 << irq);
}
static void EINT4_23unmask_irq(unsigned int irq)
{
rEINTMASK &= ~(1 << EINT_OFFSET(irq));
if (irq < IRQ_EINT8) {
rINTMSK &= ~(1 << SHIFT_EINT4_7);
} else {
rINTMSK &= ~(1 << SHIFT_EINT8_23);
}
}
/* for sub_IRQ */
static void SUB_ack_irq(unsigned int irq)
{
rSUBSRCPND = (1 << SUBIRQ_OFFSET(irq));
if (irq <= IRQ_ERR0){
ClearPending(IRQ_UART0);
}else if (irq <= IRQ_ERR1){
ClearPending(IRQ_UART1);
}else if (irq <= IRQ_ERR2){
ClearPending(IRQ_UART2);
} else { /* if ( irq <= IRQ_ADC_DONE ) { */
ClearPending(IRQ_ADCTC);
}
}
static void SUB_mask_irq(unsigned int irq)
{
rINTSUBMSK |= (1 << SUBIRQ_OFFSET(irq));
}
static void SUB_unmask_irq(unsigned int irq)
{
rINTSUBMSK &= ~(1u << SUBIRQ_OFFSET(irq));
if (irq <= IRQ_ERR0) {
rINTMSK &= ~(1u << IRQ_UART0);
} else if (irq <= IRQ_ERR1) {
rINTMSK &= ~(1u << IRQ_UART1);
} else if (irq <= IRQ_ERR2){
rINTMSK &= ~(1u << IRQ_UART2);
} else { /* if ( irq <= IRQ_ADC_DONE ) { */
rINTMSK &= ~(1u << IRQ_ADCTC);
}
}
unsigned int get_subIRQ(int irq, int begin, int end, int fail_irq) {
int i;
for(i=begin; i <= end; i++) {
if (irq & (1 << i))
return (EXT_IRQ_OFFSET + i);
}
return fail_irq;
}
unsigned int get_extIRQ(int irq, int begin, int end, int fail_irq) {
int i;
for(i=begin; i <= end; i++) {
if (irq & (1 << i))
return (NORMAL_IRQ_OFFSET - 4 + i);
}
return fail_irq;
}
static unsigned int fixup_irq(int irq) {
unsigned int ret;
unsigned long sub_mask, ext_mask;
switch (irq) {
case IRQ_UART0:
sub_mask = rSUBSRCPND & ~rINTSUBMSK;
ret = get_subIRQ(sub_mask, 0, 2, irq);
break;
case IRQ_UART1:
sub_mask = rSUBSRCPND & ~rINTSUBMSK;
ret = get_subIRQ(sub_mask, 3, 5, irq);
break;
case IRQ_UART2:
sub_mask = rSUBSRCPND & ~rINTSUBMSK;
ret = get_subIRQ(sub_mask, 6, 8, irq);
break;
case IRQ_ADCTC:
sub_mask = rSUBSRCPND & ~rINTSUBMSK;
ret = get_subIRQ(sub_mask, 9, 10, irq);
break;
case IRQ_EINT4_7:
ext_mask = rEINTPEND & ~rEINTMASK;
ret = get_extIRQ(ext_mask, 4, 7, irq);
break;
case IRQ_EINT8_23:
ext_mask = rEINTPEND & ~rEINTMASK;
ret = get_extIRQ(ext_mask, 8, 23, irq);
break;
default:
ret = irq;
}
return ret;
}
void ISR_Init(void)
{
int irq;
//FIQ disable and disable all interrupt
rINTMOD = 0x0; //All=IRQ mode
rINTMSK = BIT_ALLMSK; //All interrupt is masked.
rINTSUBMSK = BIT_SUB_ALLMSK; //All sub-interrupt is masked
// Define irq handler
for (irq=0; irq < NORMAL_IRQ_OFFSET; irq++) {
InterruptFunc[irq].valid = 1;
InterruptFunc[irq].ack_irq = ack_irq;
InterruptFunc[irq].mask = mask_irq;
InterruptFunc[irq].unmask = unmask_irq;
}
InterruptFunc[IRQ_RESERVED6].valid = 0;
InterruptFunc[IRQ_RESERVED24].valid = 0;
InterruptFunc[IRQ_EINT4_7].valid = 0;
InterruptFunc[IRQ_EINT8_23].valid = 0;
InterruptFunc[IRQ_EINT0].valid = 0;
InterruptFunc[IRQ_EINT1].valid = 0;
InterruptFunc[IRQ_EINT2].valid = 0;
InterruptFunc[IRQ_EINT3].valid = 0;
for (irq=NORMAL_IRQ_OFFSET; irq < EXT_IRQ_OFFSET; irq++) {
InterruptFunc[irq].valid = 0;
InterruptFunc[irq].ack_irq = EINT4_23ack_irq;
InterruptFunc[irq].mask = EINT4_23mask_irq;
InterruptFunc[irq].unmask = EINT4_23unmask_irq;
}
for (irq=EXT_IRQ_OFFSET; irq < SUB_IRQ_OFFSET; irq++) {
InterruptFunc[irq].valid = 1;
InterruptFunc[irq].ack_irq = SUB_ack_irq;
InterruptFunc[irq].mask = SUB_mask_irq;
InterruptFunc[irq].unmask = SUB_unmask_irq;
}
}
//--------------------------------IRQ core---------------------------------//
#if 0
int GetISROffsetClr()
{
//計(jì)算中斷的偏移地址,高位優(yōu)先
int i,ispr=rI_ISPR,tmp=1<<(MAXHNDLRS-1);//temp bit
for(i=MAXHNDLRS;i>0;i--){
if(ispr&tmp){
return i-1;
}
tmp>>=1;
}
return -1;
}
#endif
int SetISR_Interrupt(int vector, void (*handler)(int, void*), void* data)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
if(vector>NR_IRQS || vector<0)
return -1;
if(!InterruptFunc[vector].valid)
return -1;
//OS_ENTER_CRITICAL();
//cpu_sr = INTS_OFF();
INTS_OFF();
//__disable_interrupt();
InterruptFunc[vector].ack_irq(vector); //clear pending
InterruptFunc[vector].InterruptHandlers = handler;
InterruptFunc[vector].data = data;
InterruptFunc[vector].unmask(vector); //enable interrupt
//__enable_interrupt();
//OS_EXIT_CRITICAL();
//if(cpu_sr == 0) INTS_ON();
INTS_ON();
return 0;
}
void Enable_Irq(int vector)
{
if(vector>NR_IRQS || vector<0)
return;
if(!InterruptFunc[vector].valid)
return;
InterruptFunc[vector].ack_irq(vector); //clear pending
InterruptFunc[vector].unmask(vector); //enable interrupt
}
void Disable_Irq(int vector)
{
if(vector>NR_IRQS || vector<0)
return;
if(!InterruptFunc[vector].valid)
return;
InterruptFunc[vector].mask(vector); //disable interrupt
}
void ISR_IrqHandler(void)
{
unsigned int irq=GetISROffsetClr(); //得到中斷向量的偏移地址
irq=fixup_irq(irq);
if(irq>=NR_IRQS)
return;
if(InterruptFunc[irq].InterruptHandlers==NULL){
InterruptFunc[irq].ack_irq(irq); //clear pending
return;
}
//OSIntEnter();
INTS_OFF();
//__disable_interrupt();
// Call interrupt service routine
InterruptFunc[irq].InterruptHandlers(irq, InterruptFunc[irq].data);
InterruptFunc[irq].ack_irq(irq); //clear pending
INTS_ON();
//__enable_interrupt();
//OSIntExit();
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -