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 的问题

Other Parts Discussed in Thread: MSP430F5438A

在UCOSII 系统中,产生系统节拍的定时器中断函数为什么用C语言编写的不行啊,改为汇编就可以了。这个有什么区别呢?

#pragma vector = WDT_VECTOR

__interrupt void WDT_ISR(void)

{

  OSTimeTick();

}

这个在c中的中断不行,但是我设置断点调试,他也能进来的啊。但是就进步了任务函数。

  • 中断服务程序用C语言和汇编没有什么本质上的区别。你可以对照一下C的ISR生产的汇编和你写的汇编有什么不一样的地方。

  • 我现在理解在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

  • 仿真时进到到这来但就是跳不进OSTimeTick这个函数

  • ;********************************************************************************************************

    ;                                              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指针以实现函数调用功能

  • 我加了这一段的,     我仿真是 CALLA       #OSTimeTick 到这里了,当是没有进入OSTimeTick ()函数

         COMMON  INTVEC                  ; 定义公共段

               ORG     TIMER1_A1_VECTOR              ; 设置特定的定位指针

    TIMER1_VEC     DW      TIMER1_ISR                 ; interrupt vector. Watchdog/Timer, Timer mode

  • 仿真结果就是来这里一次Interrupt这里加1;正常的好像这里一直是1,仿真下来。不知道为什么都到这里了,进不去这个时钟节拍函数

  • 1. 有查过堆栈没?

    2. 仿真到   CALLA       #OSTimeTick             ; call ticks routine

      这句话后,继续单步执行,情况是如何的,是程序跳转到未知位置还是其他情况?

  • 估计是中断频繁发生导致,我换了一种定时器方式就可以了

  • 使用WDT定时器不行的原因是因为仿真环境中不能对WDT的定时器进行仿真

  • WDT的定时器是可以,楼主想换成其他定时器,发现最开始使用的timer定时器有问题,换成另一种timer就没有问题。我觉得应该timer都可以用来做系统时钟节拍,可能哪里存在配置的问题吧。

  • 我也不知道是哪里配置有问题,我用的是MSP430F5438A,我用定时器A的定时溢出来做时钟节拍就有问题,但换成CCR0定时溢出这个中断就没有问题。就是

    TA1CCR0= 8192;

    TA1CTL = TASSEL_1 + MC_1 + TACLR + TAIE;初始化成为这个就不行,

    设置成为

    TA1CCTL0 = CCIE;                    

    TA1CCR0=8192;

    TA1CTL = TASSEL_1 + MC_1 + TACLR;   就可以他们对应的中断入口不同