共2条
1/1 1 跳转至页
ucos,ii ucos-ii中断结构及中断嵌套的问题
问
ucos-ii中断结构及中断嵌套的问题
中断处理流程
1:IRQ中断发生后调用UCOS_IRQHandler()
2:UCOS_IRQHandler()先压栈
3:后调用OSIntEnter()
4:根据IRQ偏移量查找处理函数
5:用户中断处理函数
6:OSIntExit()
7:如果发生中断切换调用INTCTXSW否则恢复现场至中断前任务
代码如下:
UCOS_IRQHandler
stmfd sp!,{r0-r12,lr}
bl OSIntEnter
bl C_IRQHandler
bl OSIntExit
ldr r0,=OSIntCtxSwFlag 调用OSIntCtxSw后置1
ldr r1,[r0]
cmp r1,#1
beq _IntCtxSw
ldmfd sp!,{r0-r12,lr}
subs pc,lr,#4
_IntCtxSw
mov r1,#0
str r1,[r0]
ldmfd sp!,{r0-r12,lr}
stmfd sp!,{r0-r3}
mov r1,sp
add sp,sp,#16
sub r2,lr,#4
mrs r3,spsr
orr r0,r3,#NOINT
msr spsr_c,r0
ldr r0,=.+8
movs pc,r0
stmfd sp!,{r2} ; push old task's pc
stmfd sp!,{r4-r12,lr} ; push old task's lr,r12-r4
mov r4,r1 ; Special optimised code below
mov r5,r3
ldmfd r4!,{r0-r3}
stmfd sp!,{r0-r3} ; push old task's r3-r0
stmfd sp!,{r5} ; push old task's psr
mrs r4,spsr
stmfd sp!,{r4} ; push old task's spsr
; OSPrioCur = OSPrioHighRdy
ldr r4,=OSPrioCur
ldr r5,=OSPrioHighRdy
ldrb r5,[r5]
strb r5,[r4]
; Get current task TCB address
ldr r4,=OSTCBCur
ldr r5,[r4]
str sp,[r5] ; store sp in preempted tasks's TCB
bl OSTaskSwHook ; call Task Switch Hook
; Get highest priority task TCB address
ldr r6,=OSTCBHighRdy
ldr r6,[r6]
ldr sp,[r6] ; get new task's stack pointer
; OSTCBCur = OSTCBHighRdy
str r6,[r4] ; set new current task TCB address
ldmfd sp!,{r4} ; pop new task's spsr
msr SPSR_cxsf,r4
ldmfd sp!,{r4} ; pop new task's psr
msr CPSR_cxsf,r4
ldmfd sp!,{r0-r12,lr,pc} ; pop new task's r0-r12,lr & pc
void C_IRQHandler(void) //void C_IRQHandler(void)
{
U32 wTemp;
wTemp = rINTOFFSET<<2;
((void(*)(void))(*((U32 *)(aISR_EINT0+wTemp))))();
}
void __vWDTInterrupt()
{
rSRCPND &= BIT_WDT; // Clear pending bit -- Watchdog timer
rINTPND &= BIT_WDT;
OSTimeTick();
}
我现在用看门狗做时钟中断,没有其他中断时一切正常,但是我加了个串口中断后发现以下问题,
串口中断如下:
void __irq Uart1Task(void)
{
rINTSUBMSK|=(BIT_SUB_RXD1|BIT_SUB_TXD1|BIT_SUB_ERR1);
if(rSUBSRCPND&BIT_SUB_RXD1)
{
Uart0RxBuffer[Uart0RxInSp++] =(char)RdURXH1();
}
rSUBSRCPND&=(BIT_SUB_RXD1|BIT_SUB_ERR1); // Clear Sub int pending
rINTSUBMSK&=~(BIT_SUB_RXD1|BIT_SUB_ERR1);
rSRCPND &= BIT_UART1;
rINTPND &= BIT_UART1;
}
1:中断响应慢,而且丢数据,我发送几个数据后串口才开始响应中断,但前几个数据都丢失,本以为是优先级低,采取了取消优先级,及建立高于看门狗优先级的INT0中断,取消掉任务中的关中断及WHILE(1)等,但是问题依旧。
2:接受1-3个中断后出现指令异常,修改void C_IRQHandler(void)如下
C_IRQHandler(void)
{
U32 wTemp;
wTemp = rINTOFFSET<<2;
Uart_Printf("IRQ Int 0x%x\n",rINTOFFSET);
((void(*)(void))(*((U32 *)(aISR_EINT0+wTemp))))();
},监控中断出现号
收到如下信息:
IRQ Int 0x9 (0x9看门狗中断)
IRQ Int 0x9
IRQ Int 0x9
IRQ Int 0x17 (0x17串口中断)
IRQ Int 0x17
IRQ Int 0x17
IRQ Int 0x9
Undefined instruction exception!!!
第2个问题我怀疑是中断级的任务切换出了问题,但第1个现在还不是很清楚,请各位给看看。 答 1: 哦?怎么没人理? 答 2: 搞定了,大家注意下带_IRQ前缀的用法。 通过反汇编,发现带_irq的函数,在ADS中编译的时候会在前边会增加保存LR的指令,而且在函数返回时,会增加将当前LR中地址减4赋给PC的指令,如果对中断的处理就这一个函数,那是没问题的,但是如果在中断嵌套的时候增加此前缀,就会让函数再次执行后发生异常,因为在中断发生的时候LR中的地址已经加过4了。因为对开发工具不熟,所以同样移植过来的代码就不能用了,请大家注意呀。
中断处理流程
1:IRQ中断发生后调用UCOS_IRQHandler()
2:UCOS_IRQHandler()先压栈
3:后调用OSIntEnter()
4:根据IRQ偏移量查找处理函数
5:用户中断处理函数
6:OSIntExit()
7:如果发生中断切换调用INTCTXSW否则恢复现场至中断前任务
代码如下:
UCOS_IRQHandler
stmfd sp!,{r0-r12,lr}
bl OSIntEnter
bl C_IRQHandler
bl OSIntExit
ldr r0,=OSIntCtxSwFlag 调用OSIntCtxSw后置1
ldr r1,[r0]
cmp r1,#1
beq _IntCtxSw
ldmfd sp!,{r0-r12,lr}
subs pc,lr,#4
_IntCtxSw
mov r1,#0
str r1,[r0]
ldmfd sp!,{r0-r12,lr}
stmfd sp!,{r0-r3}
mov r1,sp
add sp,sp,#16
sub r2,lr,#4
mrs r3,spsr
orr r0,r3,#NOINT
msr spsr_c,r0
ldr r0,=.+8
movs pc,r0
stmfd sp!,{r2} ; push old task's pc
stmfd sp!,{r4-r12,lr} ; push old task's lr,r12-r4
mov r4,r1 ; Special optimised code below
mov r5,r3
ldmfd r4!,{r0-r3}
stmfd sp!,{r0-r3} ; push old task's r3-r0
stmfd sp!,{r5} ; push old task's psr
mrs r4,spsr
stmfd sp!,{r4} ; push old task's spsr
; OSPrioCur = OSPrioHighRdy
ldr r4,=OSPrioCur
ldr r5,=OSPrioHighRdy
ldrb r5,[r5]
strb r5,[r4]
; Get current task TCB address
ldr r4,=OSTCBCur
ldr r5,[r4]
str sp,[r5] ; store sp in preempted tasks's TCB
bl OSTaskSwHook ; call Task Switch Hook
; Get highest priority task TCB address
ldr r6,=OSTCBHighRdy
ldr r6,[r6]
ldr sp,[r6] ; get new task's stack pointer
; OSTCBCur = OSTCBHighRdy
str r6,[r4] ; set new current task TCB address
ldmfd sp!,{r4} ; pop new task's spsr
msr SPSR_cxsf,r4
ldmfd sp!,{r4} ; pop new task's psr
msr CPSR_cxsf,r4
ldmfd sp!,{r0-r12,lr,pc} ; pop new task's r0-r12,lr & pc
void C_IRQHandler(void) //void C_IRQHandler(void)
{
U32 wTemp;
wTemp = rINTOFFSET<<2;
((void(*)(void))(*((U32 *)(aISR_EINT0+wTemp))))();
}
void __vWDTInterrupt()
{
rSRCPND &= BIT_WDT; // Clear pending bit -- Watchdog timer
rINTPND &= BIT_WDT;
OSTimeTick();
}
我现在用看门狗做时钟中断,没有其他中断时一切正常,但是我加了个串口中断后发现以下问题,
串口中断如下:
void __irq Uart1Task(void)
{
rINTSUBMSK|=(BIT_SUB_RXD1|BIT_SUB_TXD1|BIT_SUB_ERR1);
if(rSUBSRCPND&BIT_SUB_RXD1)
{
Uart0RxBuffer[Uart0RxInSp++] =(char)RdURXH1();
}
rSUBSRCPND&=(BIT_SUB_RXD1|BIT_SUB_ERR1); // Clear Sub int pending
rINTSUBMSK&=~(BIT_SUB_RXD1|BIT_SUB_ERR1);
rSRCPND &= BIT_UART1;
rINTPND &= BIT_UART1;
}
1:中断响应慢,而且丢数据,我发送几个数据后串口才开始响应中断,但前几个数据都丢失,本以为是优先级低,采取了取消优先级,及建立高于看门狗优先级的INT0中断,取消掉任务中的关中断及WHILE(1)等,但是问题依旧。
2:接受1-3个中断后出现指令异常,修改void C_IRQHandler(void)如下
C_IRQHandler(void)
{
U32 wTemp;
wTemp = rINTOFFSET<<2;
Uart_Printf("IRQ Int 0x%x\n",rINTOFFSET);
((void(*)(void))(*((U32 *)(aISR_EINT0+wTemp))))();
},监控中断出现号
收到如下信息:
IRQ Int 0x9 (0x9看门狗中断)
IRQ Int 0x9
IRQ Int 0x9
IRQ Int 0x17 (0x17串口中断)
IRQ Int 0x17
IRQ Int 0x17
IRQ Int 0x9
Undefined instruction exception!!!
第2个问题我怀疑是中断级的任务切换出了问题,但第1个现在还不是很清楚,请各位给看看。 答 1: 哦?怎么没人理? 答 2: 搞定了,大家注意下带_IRQ前缀的用法。 通过反汇编,发现带_irq的函数,在ADS中编译的时候会在前边会增加保存LR的指令,而且在函数返回时,会增加将当前LR中地址减4赋给PC的指令,如果对中断的处理就这一个函数,那是没问题的,但是如果在中断嵌套的时候增加此前缀,就会让函数再次执行后发生异常,因为在中断发生的时候LR中的地址已经加过4了。因为对开发工具不熟,所以同样移植过来的代码就不能用了,请大家注意呀。
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动——B站互动赢积分】活动开启啦! | |
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |