移植uC/OS-III到ARM9(TQ2440)心得
uC/OS-III是micrium公司推出的新版本的实时操作系统,跟第二版相比有较大的区别,其中比较重要的区别就是可以支持无限个任务,并且支持分时性能。由于micrium的评估版是STM32类型的,因此没有ARM9的移植版本,这周末利用点时间移植了一下,现在简单的把自己的心得和收获分享给大家,说错的地方请批评指出。
uC/OS-III在文件上对系统功能的划分上更为明确和细分。一般可以分为下列几种:
uCOS_III
├─uC_CFG :包含各种配置文件,需要修改
│ cpu_cfg.h :配置CPU的时间戳功能
│ lib_cfg.h :配置库
│ os_cfg.h :系统裁剪用,各种开关量。
│ os_cfg_app.h :配置时钟频率,各种大小等。
│
├─uC_CPU :硬件环境的CPU相关,需要修改
│ cpu.h :CPU的数据类型定义,临界函数定义。
│ cpu_core.c :CPU时间戳功能的函数,一般不需修改。
│ cpu_core.h :CPU时间戳功能的相关宏定义
│ cpu_def.h :CPU数据类型、堆栈增长方向、临界函数等宏定义
│
├─uC_LIB :对库进行进一步封装,一般不需修改
│ lib_ascii.c
│ lib_ascii.h
│ lib_def.h
│ lib_math.c
│ lib_math.h
│ lib_mem.c
│ lib_mem.h
│ lib_str.c
│ lib_str.h
│
├─uC_OS_CPU :系统与硬件的
│ os_cpu.h :任务切换函数硬件接口,以及各种声明。
│ OS_CPU_A.S :汇编文件,CPU的任务切换函数
│ OS_CPU_C.C :任务初始化函数对寄存器的操作。
│
└─uC_SRC :内核源文件,一般不需要更改。
os.h :各种宏和函数声明
os_cfg_app.c :预定义的各种数据结构
os_core.c
os_dbg.c
os_flag.c
os_int.c
os_mem.c
os_msg.c
os_mutex.c
os_pend_multi.c
os_prio.c
os_q.c
os_sem.c
os_stat.c
os_task.c
os_tick.c
os_time.c
os_tmr.c
os_type.h :各种数据结构的字长定义。
os_var.c
以上打红色的几个文件在移植过程中要修改。在www. micrium.com官网上可以下载到ucos-III的源代码和在STM32上的移植代码,可以在stm32的代码基础上修改。
第一步:修改配置文件:
cpu_cfg.h 、lib_cfg.h、os_cfg.h、os_cfg_app.h 这几个文件是配置作用,按个人需要置0或1。
第二步:修改cpu.h
数据类型修改如下:
typedef void CPU_VOID;
typedef char CPU_CHAR;
typedef unsigned char CPU_BOOLEAN;
typedef unsigned char CPU_INT08U;
typedef signed char CPU_INT08S;
typedef unsigned short CPU_INT16U;
typedef signed short CPU_INT16S;
typedef unsigned int CPU_INT32U;
typedef signed int CPU_INT32S;
typedef unsigned long CPU_INT64U;
typedef signed long CPU_INT64S;
typedef float FP32;
typedef double FP64;
开关中断定义如下:
#define CPU_INT_DIS() { cpu_sr = OSCPUSaveSR(); }
#define CPU_INT_EN() { OSCPURestoreSR(cpu_sr); }
#define CPU_CRITICAL_ENTER() do { CPU_INT_DIS(); } while (0)
#define CPU_CRITICAL_EXIT() do { CPU_INT_EN(); } while (0)
OSCPUSaveSR和OSCPURestoreSR函数就是你在汇编文件中实现的函数。
第三步:修改os_cpu.h
#define OS_TASK_SW() OSCtxSw()
添加各种函数声明
void OSStartHighRdy (void);
void OSCtxSw (void);
void OSIntCtxSw (void);
void OSTickISR (void);
void OS_CPU_PendSVHandler (void);
void OS_CPU_SysTickHandler(void);
void OS_CPU_SysTickInit (CPU_INT32U cnts);
第四步:修改或新建文件OS_CPU_C.C
修改任务堆栈初始化函数,这里涉及到寄存器的顺序。
CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task,//
void *p_arg,//
CPU_STK *p_stk_base,
CPU_STK *p_stk_limit,
CPU_STK_SIZE stk_size,
OS_OPT opt) //
{
CPU_INT32U *stk;
CPU_INT32U ptos = (CPU_INT32U)(p_stk_base + stk_size - 1);
opt = opt;
stk = (CPU_INT32U *)(ptos);
*(stk) = (CPU_INT32U)p_task; /* Entry Point */
*(--stk) = (CPU_INT32U)0; /* LR */
*(--stk) = (CPU_INT32U)0; /* R12 */
*(--stk) = (CPU_INT32U)0; /* R11 */
*(--stk) = (CPU_INT32U)0; /* R10 */
*(--stk) = (CPU_INT32U)0; /* R9 */
*(--stk) = (CPU_INT32U)0; /* R8 */
*(--stk) = (CPU_INT32U)0; /* R7 */
*(--stk) = (CPU_INT32U)0; /* R6 */
*(--stk) = (CPU_INT32U)0; /* R5 */
*(--stk) = (CPU_INT32U)0; /* R4 */
*(--stk) = (CPU_INT32U)0; /* R3 */
*(--stk) = (CPU_INT32U)0; /* R2 */
*(--stk) = (CPU_INT32U)0; /* R1 */
*(--stk) = (CPU_INT32U)p_arg; /* R0 : argument */
*(--stk) = (CPU_INT32U)0x00000013L; /* CPSR (SVC mode, Enable both IRQ and FIQ interrupts) */
return ((CPU_STK *)stk);
}
第五步:修改或新建汇编文件OS_CPU_A.S
主要实现OSCtxSw(), OSIntCtxSw() OSStartHighRdy() OS_CPU_IRQ_ISR() OSTickISR() ,OSCPUSaveSR(),OSCPURestoreSR这几个函数。里面的具体内容见附件,复制过来有点长。
到这里之后,新建工程,把之前ucos-II的应用程序搬过来是不是就可以运行了呢?答案是否定的!
ucos-III的功能函数的命令和参数列表相比前一个版本有了很大变化,因此需要改动才可以使用。
例如,头文件是os.h而不是ucos-ii.h;信号量、延时函数等函数的参数都多了一个记录错误信息的变量;信号量有自己的数据类型OS_SEM等等。这个需要读者自己参照数据手册进行修改,不能一一列举。
到这里,移植就完成了。讲得比较粗略,希望读者亲自体验一下,会有更加深刻的理解。