SEP4020的中断共有32位,用一个寄存器来保存中断产生信号,当产生中断时,对应寄存器那一位将置位。
获取中断控制函数的方式是建立一个32位的数组,将所有中断处理函数保存在数组中,如下:
INT_VECTOR vector[] =
{
/* interrupt number, handler */
{ INTSRC_NULL, NULL },
{ INTSRC_EXINT0, EntIntKey },
{ INTSRC_EXINT1, EntIntKey },
{ INTSRC_EXINT2, EntIntKey },
{ INTSRC_EXINT3, EntIntKey },
{ INTSRC_EXINT4, EntIntKey },
{ INTSRC_EXINT5, NULL },
{ INTSRC_EXINT6, NULL },
{ INTSRC_EXINT7, NULL },
{ INTSRC_EXINT8, NULL },
{ INTSRC_EXINT9, NULL },
{ INTSRC_EXINT10, NULL },
{ INTSRC_SDIO, NULL },
{ INTSRC_SMC1, NULL },
{ INTSRC_SMC0, NULL },
{ INTSRC_USB, NULL },
{ INTSRC_NULL, NULL },
{ INTSRC_SSI, NULL },
{ INTSRC_I2S, NULL },
{ INTSRC_LCDC, NULL },
{ INTSRC_PWM, NULL },
{ INTSRC_UART3, NULL },
{ INTSRC_UART2, NULL },
{ INTSRC_UART1, NULL },
{ INTSRC_UART0, NULL},
{ INTSRC_TIMER3, NULL },
{ INTSRC_TIMER2, NULL },
{ INTSRC_TIMER1, NULL },
{ INTSRC_MAC, NULL },
{ INTSRC_EMI, NULL },
{ INTSRC_DMAC, NULL },
{ INTSRC_RTC, NULL },
};
判断中断的方式是通过不断移位,获取被置位的中断源:
void int_vector_handler(void)
{
U32 intnum;
U8 i = 0;
intnum = *(RP)(INTC_IFSR); //读取IRQ 中断最终状态寄存器获得中断号
while (intnum != 1)
{
intnum = intnum >> 1;
i++;
}
(*vector[i].handler)(); //通过调用相应的处理函数
return ;
}
姑且不讨论这种方法是否符合SEP4020的中断优先级,采用移位方法判断中断源,best需要O(1),worst需要O(32),效率太低,让我们讨论下有何改进方法。
改进算法1:
采用二分法,32bit需要5次可以找到我们想要的位置
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
| |
1) XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
| | | |
2) XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
| | | | | | | |
3) XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
|| || || || || || || ||
4) XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
5)X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
Time=O(5)
改进算法2:
若查表,可以获得最快的速度,但是32bit组成的表足有2^32=4G之大。
若将32bit分成两个16bit的表,可将表缩小为2^16=65536,还是比较大。
若将32bit分成四个8bit的表,可将表缩小为2^8=256,同时这四张表可以复用!
Pseudocode
tablenum <- (intnum & 0xFFFFFF00)
if tablenum is not zero
i<- table[tablenum]
goto end;
tablenum <- (intnum & 0xFFFF00FF)>>8)
if tablenum is not zero
i<- table[tablenum]+8
goto end;
tablenum <- (intnum & 0xFF00FFFF)>>16)
if tablenum is not zero
i<- table[tablenum]+16
goto end;
tablenum <- (intnum & 0x00FFFFFF)>>24)
if tablenum is not zero
i<- table[tablenum]+24
goto end;
Best case : O(1)
Worest case: O(4)
阅读(1042) | 评论(0) | 转发(0) |