在UCOSII 系统中,产生系统节拍的定时器中断函数为什么用C语言编写的不行啊,改为汇编就可以了。这个有什么区别呢?
#pragma vector = WDT_VECTOR
__interrupt void WDT_ISR(void)
{
OSTimeTick();
}
这个在c中的中断不行,但是我设置断点调试,他也能进来的啊。但是就进步了任务函数。
Young Hu:
中断服务程序用C语言和汇编没有什么本质上的区别。你可以对照一下C的ISR生产的汇编和你写的汇编有什么不一样的地方。
Peter_Zheng:
回复 Young Hu:
我现在理解在430上编写uCOS的中断服务程序,只能这样
————————————-
汇编中断程序:
……… 用汇编写系统代码
………
调用C函数写的用户代码
……….
………..用汇编写系统代码
中断结束
————————————
而不能这样:
————————————
C中断程序:
……… 调用汇编程序编写的系统代码
………
用C写的用户代码
……….
…………调用汇编程序编写的系统代码
中断结束
————————————
因为,如果用C写中断程序,那么在进如中断的第一句,编译器已经保存了部分积存器,但我们不知道被保存的是哪些积存器,这样在中断结束要进行任务切换时就不知道把哪些积存器出栈,任务切换会失败。
还是需要把ucos的移植那本书再好好看一下,大家探讨一下
anger0925:
回复 Peter_Zheng:
我下了一个别人移植好的,但他产生时钟节拍是看门狗定时器,我想修改为其他定时器来做时钟节拍。但是修改后中断能产生,但进步而来时钟节拍函数。
这个是看门狗定时器产生的:
WDT_ISR ; wd timer ISR
PUSHALL ; push all registers
bic.b #0x01, SFRIE1_L ; bic.b #0x01, SFRIE1 ; disable wd timer interrupt
//是否有中断嵌套,因为单独使用了系统堆栈
cmp.b #0, &OSIntNesting ; if (OSIntNesting == 0)
jne WDT_ISR_1 ;不等于时跳转
mov.w &OSTCBCur, R13 ; save task stack
mov.w SP, 0(R13)
mov.w &OSISRStkPtr, SP ; load interrupt stack
WDT_ISR_1
inc.b &OSIntNesting ; increase OSIntNesting
bis.b #0x01, SFRIE1_L ;bis.b #0x01, SFRIE1 ; enable wd timer interrupt
EINT ; enable general interrupt to allow for interrupt nesting
calla #OSTimeTick ; call ticks routine
DINT ; IMPORTANT: disable general interrupt BEFORE calling OSIntExit()
calla #OSIntExit ;
//是否有中断嵌套,因为单独使用了系统堆栈
cmp.b #0, &OSIntNesting ; if (OSIntNesting == 0)
jne WDT_ISR_2
mov.w &OSTCBHighRdy, R13 ; restore task stack SP
mov.w @R13, SP
WDT_ISR_2
POPALL ; pop all registers
reti ; return from interrupt
我修改的定时器A,后就进不了:
TIMER1_ISR ; wd timer ISR
PUSHALL ; push all registers
bic.w #0x0002, TA1CTL ; bic.b #0x01, SFRIE1 ; disable wd timer interrupt
//是否有中断嵌套,因为单独使用了系统堆栈
cmp.b #0, &OSIntNesting ; if (OSIntNesting == 0)
jne TIMER1_ISR_1 ;不等于时跳转
mov.w &OSTCBCur, R13 ; save task stack
mov.w SP, 0(R13)
mov.w &OSISRStkPtr, SP ; load interrupt stack
TIMER1_ISR_1
inc.b &OSIntNesting ; increase OSIntNesting
bis.w #0x0002, TA1CTL ;bis.b #0x01, SFRIE1 ; enable wd timer interrupt
EINT ; enable general interrupt to allow for interrupt nesting
calla #OSTimeTick ; call ticks routine
DINT ; IMPORTANT: disable general interrupt BEFORE calling OSIntExit()
calla #OSIntExit ;
//是否有中断嵌套,因为单独使用了系统堆栈
cmp.b #0, &OSIntNesting ; if (OSIntNesting == 0)
jne TIMER2_ISR_2
mov.w &OSTCBHighRdy, R13 ; restore task stack SP
mov.w @R13, SP
TIMER2_ISR_2
POPALL ; pop all registers
reti ; return from interrupt
anger0925:
回复 anger0925:
仿真时进到到这来但就是跳不进OSTimeTick这个函数
Peter_Zheng:
回复 anger0925:
;********************************************************************************************************
; TICK ISR
;
; Description: This ISR handles tick interrupts. This ISR uses the Watchdog timer as the tick source.
;
; Notes : 1) The following C pseudo-code describes the operations being performed in the code below.
;
; Save all the CPU registers
; if (OSIntNesting == 0) {
; OSTCBCur->OSTCBStkPtr = SP;
; SP = OSISRStkPtr; /* Use the ISR stack from now on */
; }
; OSIntNesting++;
; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */
; Clear the interrupt source;
; OSTimeTick(); /* Call uC/OS-II's tick handler */
; DISABLE general interrupts; /* Must DI before calling OSIntExit() */
; OSIntExit();
; if (OSIntNesting == 0) {
; SP = OSTCBHighRdy->OSTCBStkPtr; /* Restore the current task's stack */
; }
; Restore the CPU registers
; Return from interrupt.
;
; 2) ALL ISRs should be written like this!
;
; 3) You MUST disable general interrupts BEFORE you call OSIntExit() because an interrupt
; COULD occur just as OSIntExit() returns and thus, the new ISR would save the SP of
; the ISR stack and NOT the SP of the task stack. This of course will most likely cause
; the code to crash. By disabling interrupts BEFORE OSIntExit(), interrupts would be
; disabled when OSIntExit() would return. This assumes that you are using OS_CRITICAL_METHOD
; #3 (which is the prefered method).
;
; 4) If you DON'T use a separate ISR stack then you don't need to disable general interrupts
; just before calling OSIntExit(). The pseudo-code for an ISR would thus look like this:
;
; Save all the CPU registers
; if (OSIntNesting == 0) {
; OSTCBCur->OSTCBStkPtr = SP;
; }
; OSIntNesting++;
; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */
; Clear the interrupt source;
; OSTimeTick(); /* Call uC/OS-II's tick handler */
; OSIntExit();
; Restore the CPU registers
; Return from interrupt.
;********************************************************************************************************
WDT_ISR ; wd timer ISR
PUSHM.A #12, R15
BIC.W #0x01, SFRIE1 ; disable wd timer interrupt
CMP.B #0, &OSIntNesting ; if (OSIntNesting == 0)
JNE WDT_ISR_1
MOVX.A &OSTCBCur, R13 ; save task stack
MOVX.A SP, 0(R13)
MOVX.A &OSISRStkPtr, SP ; load interrupt stack
WDT_ISR_1
INC.B &OSIntNesting ; increase OSIntNesting
BIS.W #0x01, SFRIE1 ; enable wd timer interrupt
EINT ; enable general interrupt to allow for interrupt nesting
CALLA #OSTimeTick ; call ticks routine
DINT ; IMPORTANT: disable general interrupt BEFORE calling OSIntExit()
CALLA #OSIntExit
CMP.B #0, &OSIntNesting ; if (OSIntNesting == 0)
JNE WDT_ISR_2
MOVX.A &OSTCBHighRdy, R13 ; restore task stack SP
MOVX.A @R13, SP
WDT_ISR_2
POPM.A #12, R15
RETI ; return from interrupt
;********************************************************************************************************
; WD TIMER INTERRUPT VECTOR ENTRY
;
; Interrupt vectors
;********************************************************************************************************
COMMON INTVEC
ORG WDT_VECTOR
WDT_VEC DW WDT_ISR ; interrupt vector. Watchdog/Timer, Timer mode
END
这也是一个WDT产生系统节拍的,我觉得能够执行到 CALLA #OSTimeTick ; call ticks routine这条语句,就能够跳转,calla就是把20位PC指针压栈并更改PC指针以实现函数调用功能
anger0925:
回复 Peter_Zheng:
我加了这一段的, 我仿真是 CALLA #OSTimeTick 到这里了,当是没有进入OSTimeTick ()函数
COMMON INTVEC ; 定义公共段
ORG TIMER1_A1_VECTOR ; 设置特定的定位指针
TIMER1_VEC DW TIMER1_ISR ; interrupt vector. Watchdog/Timer, Timer mode
anger0925:
回复 anger0925:
仿真结果就是来这里一次Interrupt这里加1;正常的好像这里一直是1,仿真下来。不知道为什么都到这里了,进不去这个时钟节拍函数
Triton Zhang:
回复 anger0925:
1. 有查过堆栈没?
2. 仿真到 CALLA #OSTimeTick ; call ticks routine
这句话后,继续单步执行,情况是如何的,是程序跳转到未知位置还是其他情况?
Triton Zhang:
回复 anger0925:
使用WDT定时器不行的原因是因为仿真环境中不能对WDT的定时器进行仿真