在UCOSII 系统中,产生系统节拍的定时器中断函数为什么用C语言编写的不行啊,改为汇编就可以了。这个有什么区别呢?
#pragma vector = WDT_VECTOR
__interrupt void WDT_ISR(void)
{
OSTimeTick();
}
这个在c中的中断不行,但是我设置断点调试,他也能进来的啊。但是就进步了任务函数。
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
在UCOSII 系统中,产生系统节拍的定时器中断函数为什么用C语言编写的不行啊,改为汇编就可以了。这个有什么区别呢?
#pragma vector = WDT_VECTOR
__interrupt void WDT_ISR(void)
{
OSTimeTick();
}
这个在c中的中断不行,但是我设置断点调试,他也能进来的啊。但是就进步了任务函数。
我现在理解在430上编写uCOS的中断服务程序,只能这样
-------------------------------------
汇编中断程序:
......... 用汇编写系统代码
.........
调用C函数写的用户代码
..........
...........用汇编写系统代码
中断结束
------------------------------------
而不能这样:
------------------------------------
C中断程序:
......... 调用汇编程序编写的系统代码
.........
用C写的用户代码
..........
............调用汇编程序编写的系统代码
中断结束
------------------------------------
因为,如果用C写中断程序,那么在进如中断的第一句,编译器已经保存了部分积存器,但我们不知道被保存的是哪些积存器,这样在中断结束要进行任务切换时就不知道把哪些积存器出栈,任务切换会失败。
还是需要把ucos的移植那本书再好好看一下,大家探讨一下
我下了一个别人移植好的,但他产生时钟节拍是看门狗定时器,我想修改为其他定时器来做时钟节拍。但是修改后中断能产生,但进步而来时钟节拍函数。
这个是看门狗定时器产生的:
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
;********************************************************************************************************
; 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指针以实现函数调用功能
1. 有查过堆栈没?
2. 仿真到 CALLA #OSTimeTick ; call ticks routine
这句话后,继续单步执行,情况是如何的,是程序跳转到未知位置还是其他情况?
使用WDT定时器不行的原因是因为仿真环境中不能对WDT的定时器进行仿真
WDT的定时器是可以,楼主想换成其他定时器,发现最开始使用的timer定时器有问题,换成另一种timer就没有问题。我觉得应该timer都可以用来做系统时钟节拍,可能哪里存在配置的问题吧。