原创
uCOS-II在芯唐Cortex-M0上移植
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);
}
}
文章评论(0条评论)
登录后参与讨论