原创 uCOS-II在芯唐Cortex-M0上移植

2011-5-31 23:29 5948 5 5 分类: MCU/ 嵌入式
uCOS-II在芯唐Cortex-M0(NuMicro M051)上移植(by homer)
1.新建includes.h
 因为uCOS-II的源程序都包含了includes.h,所以先新建includes.h文件。includes.h的内容:
 #ifndef __INCLUDES_H__
 #define __INCLUDES_H__
 #include <stdio.h>
 #include "M051Series.h"
 #include "DrvGPIO.h"
 #include "DrvSYS.h"
 #include "string.h"
 #include "ucos_ii.h"
 #include "os_cpu.h"
 #include "os_cfg.h"
 #endif
 其中ucos_ii.h和os_cfg.h都是有现成的,可以根据自己的需要修改os_cfg.h。只有OS_CPU.H文件需要自己准备。OS_CPU.H主要为uCOS-II typedef所用到的数据类型和定义系统堆栈的方向等。为了使uCOS-II源程序中的数据类型都是与编译器无关,这些数据类型都需要typedef下。OS_CPU.H的内容: /**************************************************
* 数据类型
**************************************************/
typedef unsigned char BOOLEAN;
typedef unsigned char INT8U;
typedef signed char INT8S;
typedef unsigned short INT16U;
typedef signed short INT16S;
typedef unsigned int INT32U;
typedef signed int INT32S;
typedef float FP32;
typedef double FP64;
typedef unsigned int OS_STK;
typedef unsigned int OS_CPU_SR;
/**************************************定义进入临界代码法***************************************************/
#define OS_CRITICAL_METHOD 3
#define OS_ENTER_CRITICAL() (cpu_sr = get_cpu_sr())
#define OS_EXIT_CRITICAL()    (restore_cpu_sr(cpu_sr))
/**************************************************
*向uCOS-II说明NuMicro M051堆栈的方向。
*因为CM0堆栈是满栈递减的,所以定义如下
**************************************************/
#define OS_STK_GROWTH 1

/**************************************************
*任务切换的宏,用PendSV来实现。不用SVC的原因是SVC不能等待
* OSCtxSw()用来产生PendSV中断
**************************************************/
#define OS_TASK_SW() OSCtxSw()

这样includes.h就准备好了。

2.OS_CPU_C.C文件
OS_CPU_C.C主要用来uCOS-II提供HOOK函数和堆栈初始化函数。其中HOOK函数都可以没有实际内容,但是必须要有,因为uCOS-II的源程序要调用这些HOOK函数。另外也把临界代码要用到的get_cpu_sr()和restore_cpu_sr()放在OS_CPU_C.C里。 OS_CPU_C.C内容如下:
void OSInitHookBegin(void) {}
void OSInitHookEnd(void) {}
void OSTaskIdleHook(void) {}
void OSTCBInitHook(OS_TCB *ptcb) {}
void OSTaskCreateHook(OS_TCB *ptcb) {}
void OSTaskSwHook(void) {}
void OSTaskSwHook1(void) {}
void OSTimeTickHook(void) {}
void OSTaskDelHook(OS_TCB *ptcb) {ptcb = ptcb;}
void OSTaskStatHook(void) {}
__asm OS_CPU_SR get_cpu_sr(void)
{
   MRS R0, PRIMASK
    CPSID I
    BX LR
}

__asm void restore_cpu_sr(uint32_t priMask)
{
   MSR PRIMASK, R0
   BX LR
}

OS_STK *OSTaskStkInit(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
   OS_STK *stk;
   pdata = pdata;
   stk = ptos;
   *--stk = (INT32U)0x01000000L;      /*PSR*/
   *--stk = (INT32U)task;                   /*PC*/
   *--stk = (INT32U)0xFFFFFFF9L;        /*LR*/
   *--stk = 0x12;                              /*R12*/
   *--stk = 0x03;                              /*R3*/
   *--stk = 0x02;                             /*R2*/
   *--stk = 0x01;                             /*R1*/
   *--stk = 0x00;                             /*R0*/
   *--stk = 0x11;                            /*R11*/
   *--stk = 0x10;                            /*R10*/
   *--stk = 0x09;                             /*R9*/
   *--stk = 0x08;                            /*R8*/
   *--stk = 0x07;                             /*R7*/
   *--stk = 0x06;                            /*R6*/
   *--stk = 0x05;                            /*R5*/
   *--stk = 0x04;                             /*R4*/
   return (stk);
}

3.OS_CPU_S.S文件
SCS_ICSR EQU 0xE000ED04
SCS_ICSR_PENDSVSET\
              EQU 0x10000000
              PRESERVE8 THUMB AREA |.text|, CODE, READONLY
OSStartHighRdy PROC
              EXPORT OSStartHighRdy [WEAK]
              IMPORT OSTaskSwHook
              IMPORT OSRunning
              IMPORT OSTCBHighRdy
              LDR R0, =OSTaskSwHook ;call OSTaskSwHook()
              BLX R0
              LDR R0, =OSRunning ;OSRunning = TRUE
              MOVS R1, #1
              STRB R1, [R0]
              LDR R0, =OSTCBHighRdy
              LDR R1, [R0]
              LDR R0, [R1]
              MOV SP, R0
              ;弹栈R4-R7
             POP {R0-R3}
             MOV R4, R0
             MOV R5, R1
             MOV R6, R2
             MOV R7, R3
             ;弹栈R8-R11
             POP {R0-R3}
             MOV R8, R0
             MOV R9, R1
             MOV R10, R2
             MOV R11, R3
             ;弹栈R0-R3
             POP {R0-R3}
             ;弹栈R12
            POP {R0}
            MOV R12, R0
           ;弹栈LR
           POP {R0}
           MOV LR, R0
           ;弹栈PSR
          LDR R0, [SP,#4]
          MSR PSR, R0
          ;弹栈R0
          SUB SP, SP, #24
          LDR R0, [SP]
          ADD SP, SP, #24
         POP {PC}
         ENDP
PendSV_Handler PROC
        EXPORT PendSV_Handler [WEAK]
        IMPORT OSTCBCur
        IMPORT OSPrioCur
        IMPORT OSPrioHighRdy
        IMPORT OSTaskSwHook
        IMPORT OSTCBHighRdy
        CPSID I
        ;压栈R8-R11
        MOV R0, R8
        MOV R1, R9
       MOV R2, R10
       MOV R3, R11
       PUSH {R0-R3}
       ;压栈R4-R7
       MOV R0, R4
       MOV R1, R5
       MOV R2, R6
       MOV R3, R7
       PUSH {R0-R3}
        ;OSTCBCur -> OSTCBStkPtr = stack poiner
      LDR R0, =OSTCBCur
      LDR R1, [R0]
      MOV R0, SP
      STR R0, [R1] ;call OSTaskSwHook()
      PUSH {R14}
      LDR R0, =OSTaskSwHook
      BLX R0
      POP {R0}
      MOV R14, R0
      ;OSPrioCur = OSPrioHighRdy
      LDR R0, =OSPrioHighRdy
      LDRB R1, [R0]
      LDR R0, =OSPrioCur
      STRB R1, [R0]
      ;OSTCBCur = OSTCBHighRdy
      LDR R0, =OSTCBHighRdy
      LDR R1, [R0]
      LDR R0, =OSTCBCur
      STR R1, [R0]
      LDR R0, [R1]
      MOV SP, R0
      ;弹栈R4-R7
      POP {R0-R3}
      MOV R4, R0
      MOV R5, R1
      MOV R6, R2
      MOV R7, R3
     ;弹栈R8-R11
      POP {R0-R3}
      MOV R8, R0
      MOV R9, R1
      MOV R10, R2
      MOV R11, R3
      CPSIE I
      BX LR
      ENDP ; Trigger the PendSV exception (causes context switch)

OSCtxSw PROC
      EXPORT OSCtxSw [WEAK]
      LDR R1, =SCS_ICSR
      LDR R2, =SCS_ICSR_PENDSVSET
      STR R2, [R1]
      BX LR
      ENDP
OSIntCtxSw PROC
      EXPORT OSIntCtxSw [WEAK]
      B OSCtxSw
      ENDP
      ALIGN
      END
以上就把移植相关的东西准备好了。 测试: 这个移植只是在Keil4.12软件仿真了下,所以测试程序比较简单。主要看了下在软件仿真的时候Task0和Task1能不能正常切换。测试程序如下:
int main (void)
{
   SystermInit();
   OSInit();
   OSTaskCreate(Task0,(void *)0,&Task0Stk[127],7);
   OSStart();
 }

void Task0(void *pdata)
{
   pdata = pdata;
   OSTaskCreate(Task1,(void *)0,&Task1Stk[127],8);
   SysTickInit();
   while(1){ OSTimeDly(1); }
}

void Task1(void *pdata)
{
   pdata = pdata;
   while(1){ OSTimeDly(1); }
}
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
5
关闭 站长推荐上一条 /3 下一条