有在F5系列上移植成功过ucOS-II或FreeRTOS-5.1版本么?

楼主
有在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]
1楼
老兄,一堆ASM的东西你看的不头晕吗。各位能不能提供一个C语言版本阿,F5到手了是想跑OS的。
2楼
此部分移植必须要使用汇编的啊,没有C语言版本的
3楼
推荐MSP430实现UCOS-II演示程序[F449]
http://www.microcontrol.cn/bbs/a/a.asp?B=112&ID=23865
推荐试试
4楼
5x系列寄存器有20位了。
现在5418有得买了。
5楼
DC老大, 你的Demo程序是针对MSP430F1系列的,发现F5系列的PC,和SP寄存器变成了20位的了,而且PC的16-19位和SP的内容放在一起了,所以我们在F1系列上移植的东西是不能直接用在MSP430F2,F3,F4,F5上的。哪位有以上版本的ucOS-II版本的话,希望能发出来看一下,我这里的PC指针老跑飞掉。我这里用的是IAR MSP430 4.11B版本的编译器。

电脑版 Page created in 0.1562 seconds width 3 queries.