在线情况
楼主
  • 头像
  • 级别
    • 积分10
    • 经验539
    • 文章20
    • 注册2008-10-25
    有在F5系列上移植成功过ucOS-II或FreeRTOS-5.1版本么?
    最近在MSP430F5438上想移植一个嵌入式操作系统,看了2种方案,一个是ucOS-II,另外一个是freeRTOS 5.1.但是在移植的过程中发现一个问题:
    对于恢复堆栈指针SP的时候,SP就指向的一个不明确的地址,这个地址不在堆栈范围之内。 我在网络上下了一个ucOS-II for MSP430F1XXX的版本时,就没有这样的问题, 而且汇编代码也用的是一样的。难道F5系列有什么变化了么?
    MSP430F1XXXX
    [CODE];********************************************************************************************************
    ;                                               uC/OS-II
    ;                                         The Real-Time Kernel
    ;
    ;                              (c) Copyright 2002, Micrium, Inc., Weston, FL
    ;                                          All Rights Reserved
    ;
    ;                                               TI MSP430
    ;
    ;
    ; File         : OS_CPU_A.S43
    ; By           : Jian Chen (yenger@hotmail.com)
    ;                Jean J. Labrosse
    ;********************************************************************************************************

    #include   <msp430x14x.h>

    ;********************************************************************************************************
    ;                                           MACRO DEFINITIONS
    ;********************************************************************************************************

    PUSHALL     MACRO
                push     r4
                push     r5
                push     r6
                push     r7
                push     r8
                push     r9
                push     r10
                push     r11
                push     r12
                push     r13
                push     r14
                push     r15        
                ENDM

    POPALL      MACRO
                pop      r15
                pop      r14
                pop      r13
                pop      r12
                pop      r11
                pop      r10
                pop      r9
                pop      r8
                pop      r7
                pop      r6
                pop      r5
                pop      r4          
                ENDM
               
    ;********************************************************************************************************
    ;                                  PUBLIC AND EXTERNAL DECLARATIONS
    ;********************************************************************************************************

                EXTERN  OSIntExit
                EXTERN  OSIntNesting

                EXTERN  OSISRStkPtr

                EXTERN  OSPrioCur
                EXTERN  OSPrioHighRdy

                EXTERN  OSRunning

                EXTERN  OSTCBCur
                EXTERN  OSTCBHighRdy

                EXTERN  OSTaskSwHook
                EXTERN  OSTimeTick

                PUBLIC  OSCtxSw
                PUBLIC  OSCPURestoreSR
                PUBLIC  OSCPUSaveSR
                PUBLIC  OSIntCtxSw
                PUBLIC  OSStartHighRdy
                PUBLIC  WDT_ISR

    ;********************************************************************************************************
    ;                                  START HIGHEST PRIORITY READY TASK
    ;
    ; Description: This function is called by OSStart() to start the highest priority task that is ready to run.
    ;
    ; Note       : OSStartHighRdy() MUST:
    ;                 a) Call OSTaskSwHook() then,
    ;                 b) Set OSRunning to TRUE,
    ;                 c) Switch to the highest priority task.
    ;********************************************************************************************************

                RSEG    CODE                    ; Program code

    OSStartHighRdy
                call     #OSTaskSwHook

                mov.b    #1, &OSRunning         ; kernel running

                mov.w    SP, &OSISRStkPtr       ; save interrupt stack             

                mov.w    &OSTCBHighRdy, R13     ; load highest ready task stack
                mov.w    @R13, SP

                POPALL                          ; pop all registers
                
                reti                            ; emulate return from interrupt
     

    ;********************************************************************************************************
    ;                                     TASK LEVEL CONTEXT SWITCH
    ;
    ; Description: This function is called by OS_Sched() to perform a task level context switch.
    ;
    ; Note       : OSCtxSw() MUST:
    ;                 a) Save the current task's registers onto the current task stack
    ;                 b) Save the SP into the current task's OS_TCB
    ;                 c) Call OSTaskSwHook()
    ;                 d) Copy OSPrioHighRdy to OSPrioCur
    ;                 e) Copy OSTCBHighRdy to OSTCBCur
    ;                 f) Load the SP with OSTCBHighRdy->OSTCBStkPtr
    ;                 g) Restore all the registers from the high priority task stack
    ;                 h) Perform a return from interrupt
    ;********************************************************************************************************

    OSCtxSw
                push      sr                    ; emulate interrupt by also saving the SR
                PUSHALL                         ; push all registers             
                
                mov.w     &OSTCBCur, R13        ; OSTCBCur->OSTCBStkPtr = SP
                mov.w     SP, 0(R13)

                call      #OSTaskSwHook

                mov.b     &OSPrioHighRdy, R13   ; OSPrioCur = OSPrioHighRdy
                mov.b     R13, &OSPrioCur       ;
                              
                mov.w     &OSTCBHighRdy, R13    ; OSTCBCur  = OSTCBHighRdy
                mov.w     R13, &OSTCBCur        ;
                              
                mov.w     @R13, SP              ; SP        = OSTCBHighRdy->OSTCBStkPtr
                
                POPALL                          ; pop all registers
                
                reti                            ; return from interrup


    ;********************************************************************************************************
    ;                                       ISR LEVEL CONTEXT SWITCH
    ;
    ; Description: This function is called by OSIntExit() to perform an ISR level context switch.
    ;
    ; Note       : OSIntCtxSw() MUST:
    ;                 a) Call OSTaskSwHook()
    ;                 b) Copy OSPrioHighRdy to OSPrioCur
    ;                 c) Copy OSTCBHighRdy to OSTCBCur
    ;                 d) Load the SP with OSTCBHighRdy->OSTCBStkPtr
    ;                 e) Restore all the registers from the high priority task stack
    ;                 f) Perform a return from interrupt
    ;********************************************************************************************************

    OSIntCtxSw
                
                call      #OSTaskSwHook

                mov.b     &OSPrioHighRdy, R13   ; OSPrioCur = OSPrioHighRdy
                mov.b     R13, &OSPrioCur       ;
                              
                mov.w     &OSTCBHighRdy, R13    ; OSTCBCur  = OSTCBHighRdy
                mov.w     R13, &OSTCBCur        ;
                              
                mov.w     @R13, SP              ; SP        = OSTCBHighRdy->OSTCBStkPtr
                
                POPALL                          ; pop all registers
                
                reti                            ; return from interrup


    ;********************************************************************************************************
    ;                                              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
                PUSHALL                         ; push all registers             
                
                bic.b    #0x01, IE1             ; 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, IE1             ; enable wd timer interrupt
                
                EINT                            ; enable general interrupt to allow for interrupt nesting

                call     #OSTimeTick            ; call ticks routine             

                DINT                            ; IMPORTANT: disable general interrupt BEFORE calling OSIntExit()

                call     #OSIntExit             ; call ticks routine

                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
                                              

    ;********************************************************************************************************
    ;                             SAVE AND RESTORE THE CPU'S STATUS REGISTER
    ;
    ; Description: These functions are used to implement OS_CRITICAL_METHOD #3 by saving the status register
    ;              in a local variable of the calling function and then, disables interrupts.
    ;
    ; Notes      : R12 is assumed to hold the argument passed to OSCPUSaveSR() and also, the value returned
    ;              by OSCPURestoreSR().
    ;********************************************************************************************************

    OSCPUSaveSR
                MOV.W    SR,R12
                DINT
                RET


    OSCPURestoreSR
                MOV.W    R12,SR
                RET

    ;********************************************************************************************************
    ;                                 WD TIMER INTERRUPT VECTOR ENTRY
    ;
    ; MSP430x11x1/MSP430F14x Interrupt vectors             
    ;********************************************************************************************************
                COMMON  INTVEC

                ORG     WDT_VECTOR
    WDT_VEC     DW      WDT_ISR                 ; interrupt vector. Watchdog/Timer, Timer mode

                END[/CODE]



    MSP430F5438
    ;********************************************************************************************************
    ;                                               uC/OS-II
    ;                                         The Real-Time Kernel
    ;
    ;                              (c) Copyright 2002, Micrium, Inc., Weston, FL
    ;                                          All Rights Reserved
    ;
    ;                                               TI MSP430
    ;
    ;
    ; File         : OS_CPU_A.S43
    ; By           : Jian Chen (yenger@hotmail.com)
    ;                Jean J. Labrosse
    ;********************************************************************************************************

    #include   <msp430x54x.h>

    [CODE];********************************************************************************************************
    ;                                           MACRO DEFINITIONS
    ;********************************************************************************************************

    PUSHALL     MACRO
                push     r4
                push     r5
                push     r6
                push     r7
                push     r8
                push     r9
                push     r10
                push     r11
                push     r12
                push     r13
                push     r14
                push     r15        
                ENDM

    POPALL      MACRO
                pop      r15
                pop      r14
                pop      r13
                pop      r12
                pop      r11
                pop      r10
                pop      r9
                pop      r8
                pop      r7
                pop      r6
                pop      r5
                pop      r4          
                ENDM
               
    ;********************************************************************************************************
    ;                                  PUBLIC AND EXTERNAL DECLARATIONS
    ;********************************************************************************************************

                EXTERN  OSIntExit
                EXTERN  OSIntNesting

                EXTERN  OSISRStkPtr

                EXTERN  OSPrioCur
                EXTERN  OSPrioHighRdy

                EXTERN  OSRunning

                EXTERN  OSTCBCur
                EXTERN  OSTCBHighRdy

                EXTERN  OSTaskSwHook
                EXTERN  OSTimeTick

                PUBLIC  OSCtxSw
                PUBLIC  OSCPURestoreSR
                PUBLIC  OSCPUSaveSR
                PUBLIC  OSIntCtxSw
                PUBLIC  OSStartHighRdy
                PUBLIC  WDT_ISR

    ;********************************************************************************************************
    ;                                  START HIGHEST PRIORITY READY TASK
    ;
    ; Description: This function is called by OSStart() to start the highest priority task that is ready to run.
    ;
    ; Note       : OSStartHighRdy() MUST:
    ;                 a) Call OSTaskSwHook() then,
    ;                 b) Set OSRunning to TRUE,
    ;                 c) Switch to the highest priority task.
    ;********************************************************************************************************

                RSEG    CODE                    ; Program code

    OSStartHighRdy
                call     #OSTaskSwHook

                mov.b    #1, &OSRunning         ; kernel running

                mov.w    SP, &OSISRStkPtr       ; save interrupt stack             

                mov.w    &OSTCBHighRdy, R13     ; load highest ready task stack
                mov.w    @R13, SP

                POPALL                          ; pop all registers
                
                reti                            ; emulate return from interrupt
     

    ;********************************************************************************************************
    ;                                     TASK LEVEL CONTEXT SWITCH
    ;
    ; Description: This function is called by OS_Sched() to perform a task level context switch.
    ;
    ; Note       : OSCtxSw() MUST:
    ;                 a) Save the current task's registers onto the current task stack
    ;                 b) Save the SP into the current task's OS_TCB
    ;                 c) Call OSTaskSwHook()
    ;                 d) Copy OSPrioHighRdy to OSPrioCur
    ;                 e) Copy OSTCBHighRdy to OSTCBCur
    ;                 f) Load the SP with OSTCBHighRdy->OSTCBStkPtr
    ;                 g) Restore all the registers from the high priority task stack
    ;                 h) Perform a return from interrupt
    ;********************************************************************************************************

    OSCtxSw
                push      sr                    ; emulate interrupt by also saving the SR
                PUSHALL                         ; push all registers             
                
                mov.w     &OSTCBCur, R13        ; OSTCBCur->OSTCBStkPtr = SP
                mov.w     SP, 0(R13)

                call      #OSTaskSwHook

                mov.b     &OSPrioHighRdy, R13   ; OSPrioCur = OSPrioHighRdy
                mov.b     R13, &OSPrioCur       ;
                              
                mov.w     &OSTCBHighRdy, R13    ; OSTCBCur  = OSTCBHighRdy
                mov.w     R13, &OSTCBCur        ;
                              
                mov.w     @R13, SP              ; SP        = OSTCBHighRdy->OSTCBStkPtr
                
                POPALL                          ; pop all registers
                
                reti                            ; return from interrup


    ;********************************************************************************************************
    ;                                       ISR LEVEL CONTEXT SWITCH
    ;
    ; Description: This function is called by OSIntExit() to perform an ISR level context switch.
    ;
    ; Note       : OSIntCtxSw() MUST:
    ;                 a) Call OSTaskSwHook()
    ;                 b) Copy OSPrioHighRdy to OSPrioCur
    ;                 c) Copy OSTCBHighRdy to OSTCBCur
    ;                 d) Load the SP with OSTCBHighRdy->OSTCBStkPtr
    ;                 e) Restore all the registers from the high priority task stack
    ;                 f) Perform a return from interrupt
    ;********************************************************************************************************

    OSIntCtxSw
                
                call      #OSTaskSwHook

                mov.b     &OSPrioHighRdy, R13   ; OSPrioCur = OSPrioHighRdy
                mov.b     R13, &OSPrioCur       ;
                              
                mov.w     &OSTCBHighRdy, R13    ; OSTCBCur  = OSTCBHighRdy
                mov.w     R13, &OSTCBCur        ;
                              
                mov.w     @R13, SP              ; SP        = OSTCBHighRdy->OSTCBStkPtr
                
                POPALL                          ; pop all registers
                
                reti                            ; return from interrup


    ;********************************************************************************************************
    ;                                              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
                PUSHALL                         ; push all registers             
                
                bic.b    #0x01, WDTIE             ; 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, WDTIE             ; enable wd timer interrupt
                
                EINT                            ; enable general interrupt to allow for interrupt nesting

                call     #OSTimeTick            ; call ticks routine             

                DINT                            ; IMPORTANT: disable general interrupt BEFORE calling OSIntExit()

                call     #OSIntExit             ; call ticks routine

                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
                                              

    ;********************************************************************************************************
    ;                             SAVE AND RESTORE THE CPU'S STATUS REGISTER
    ;
    ; Description: These functions are used to implement OS_CRITICAL_METHOD #3 by saving the status register
    ;              in a local variable of the calling function and then, disables interrupts.
    ;
    ; Notes      : R12 is assumed to hold the argument passed to OSCPUSaveSR() and also, the value returned
    ;              by OSCPURestoreSR().
    ;********************************************************************************************************

    OSCPUSaveSR
                MOV.W    SR,R12
                DINT
                RET


    OSCPURestoreSR
                MOV.W    R12,SR
                RET

    ;********************************************************************************************************
    ;                                 WD TIMER INTERRUPT VECTOR ENTRY
    ;
    ; MSP430x11x1/MSP430F14x Interrupt vectors             
    ;********************************************************************************************************
                COMMON  INTVEC

                ORG     WDT_VECTOR
    WDT_VEC     DW      WDT_ISR                 ; interrupt vector. Watchdog/Timer, Timer mode

                END[/CODE]
    [ 此贴最后由DC在2008-11-12 14:07:23编辑过 ]
    微控网感谢您的参与
    在线情况
    2
    • 头像
    • 级别
      • 积分10
      • 经验539
      • 文章20
      • 注册2008-10-25
      此部分移植必须要使用汇编的啊,没有C语言版本的
      微控网感谢您的参与
      在线情况
      3
      • 头像
      • 级别
        • 积分10
        • 经验539
        • 文章20
        • 注册2008-10-25
        DC老大, 你的Demo程序是针对MSP430F1系列的,发现F5系列的PC,和SP寄存器变成了20位的了,而且PC的16-19位和SP的内容放在一起了,所以我们在F1系列上移植的东西是不能直接用在MSP430F2,F3,F4,F5上的。哪位有以上版本的ucOS-II版本的话,希望能发出来看一下,我这里的PC指针老跑飞掉。我这里用的是IAR MSP430 4.11B版本的编译器。
        微控网感谢您的参与
        在线情况
        4
        • 头像
        • 级别
          • 积分10
          • 经验539
          • 文章20
          • 注册2008-10-25
          我确认了,这个是MSP430F1的!发现F5系列的所有CPU寄存器都是20位的,PC和SP用满了20位, 而r3-r15只是用了16位。所以可以这么说。
          顺便说一下,6楼的话我收回,只有F5系列的CPU指令有重大变化,所以所有移植在以前MSP430的操作系统都会有问题。请大家注意了。
          我在想办法解决这个问题!希望大家也能参与一下讨论。
          微控网感谢您的参与
          在线情况
          5
          • 头像
          • 级别
            • 积分10
            • 经验539
            • 文章20
            • 注册2008-10-25
            已经移植成功啦, F5系列的ucOS-II,爽啊!庆祝一下!
            微控网感谢您的参与
            在线情况
            6
            • 头像
            • 级别
              • 积分10
              • 经验539
              • 文章20
              • 注册2008-10-25
              晚上发现还有不完善的地方,任务调度不起来,估计是恢复堆栈的时候,最新的任务创建的时候把老的任务堆栈覆盖掉了.继续研究中....
              微控网感谢您的参与
              Powered by LeadBBS 9.2 .
              Page created in 0.0957 seconds with 6 queries.