本帖最后由 catking25 于 2013-10-31 14:59 编辑
本文的目的是希望读者能够通过本文的内容掌握移植uCOS-II 的规范方法。如果只是需要移植文件,可以直接去Micriμm的官网上下载。 移植uCOS-II,主要的移植工作是编写如下三个文件: OS_CPU.H OS_CPU_C.C OS_CPU_A.ASM 下面就按照这三个文件的顺序来介绍。本文以STM32F107+RealView Compiler 开发环境为例。如果使用的其他的开发环境,个别代码可能需要做些小修改。
OS_CPU.H
OS_CPU.H 的第一部分是定义了一个宏OS_CPU_EXT。这一部分暂时可以先不去管。 #ifdef OS_CPU_GLOBALS #define OS_CPU_EXT #else #define OS_CPU_EXT extern #endif 接下来是一系列的类型定义。这一部分的移植需参考RealView Compiler Reference Guide的如下章节: RealView Compiler Reference Guide->C and C++ Implementation Details->Basic data types 从这里可以得到如下信息。 Type
| Size in bits
| Natural alignment in bytes
| char
| 8
| 1 (byte-aligned)
| short
| 16
| 2 (halfword-aligned)
| int
| 32
| 4 (word-aligned)
| long
| 32
| 4 (word-aligned)
| long long
| 64
| 8 (doubleword-aligned)
| float
| 32
| 4 (word-aligned)
| double
| 64
| 8 (doubleword-aligned)
| long double
| 64
| 8 (doubleword-aligned)
| All pointers
| 32
| 4 (word-aligned)
| _Bool
| 8
| 1 (byte-aligned)
|
根据上面的信息,形成下面的代码: [cpp] view plaincopy
- 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;
上面代码中OS_STK 表示堆栈出栈、入栈的基本数据长度。我们知道Cortex-M3 的所有堆栈操作都是以字为单位的,所以这里为 unsigned int 型。OS_CPU_SR 对应的是程序状态寄存器PSRs,自然也是unsigned int 型。 然后是关于临界区的处理,一般来说我们都喜欢使用第三种方法来实现临界区,这里也不例外。这里多说几句,第一种直接开关中断的实现临界区的方法很少采用,因为这种方法可能将原本关闭了的中断意外的打开。第二种方法是最高效的实现方法,但是这种方法调整了堆栈指针,对于需要利用堆栈指针间接寻址局部变量的系统并不适用。(x86通常采用第二种方法,因为它有单独的寄存器来做局部变量的寻址)第三种方法最保险,虽然效率比第二种方法略低一点。 [cpp] view plaincopy
- #define OS_CRITICAL_METHOD 3
- #define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}
- #define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}
-
- #if OS_CRITICAL_METHOD == 3
- OS_CPU_SR OS_CPU_SR_Save(void);
- void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
- #endif
这两个函数可以用汇编(OS_CPU_A.ASM)来编写:[plain] view plaincopy
- EXPORT OS_CPU_SR_Save
- EXPORT OS_CPU_SR_Restore
- OS_CPU_SR_Save
- MRS R0, PRIMASK ; Set prio int mask to mask all (except faults)
- CPSID I
- BX LR
-
- OS_CPU_SR_Restore
- MSR PRIMASK, R0
- BX LR
也可以通过C代码(OS_CPU_C.C)中插入汇编的方式来实现:
[cpp] view plaincopy
- __asm OS_CPU_SR OS_CPU_SR_Save(void)
- {
- MRS R0, PRIMASK ; Set prio int mask to mask all (except faults)
- CPSID I
- BX LR
- }
- __asm void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr)
- {
- MSR PRIMASK, R0
- BX LR
- }
上面的代码利用的RealView Compiler 的特殊功能(Embedded assembler),如需进一步的信息,可以参考RealView Compiler Reference Guide中Using the Inline and Embedded Assemblers这一章的内容。 然后是堆栈增长方向,ARM Cortex-M3 的堆栈是倒生的: [cpp] view plaincopy
任务切换,OSCtxSw()在OS_CPU_A.ASM 中定义:
[cpp] view plaincopy
- #define OS_TASK_SW() OSCtxSw()
最后是一些函数原型声明: [cpp] view plaincopy
- void OSCtxSw(void);
- void OSIntCtxSw(void);
- void OSStartHighRdy(void);
- void OS_CPU_PendSVHandler(void);
- void OS_CPU_SysTickHandler(void);
OS_HOOK.C在原本uCOS-II 的移植代码中是没有这个文件的。由于下面这9个函数的函数体基本都是空的,并且移植时几乎不需要更改,所以我就将其拿出到一个单独的文件中来了。 OSInitHookBegin() OSInitHookEnd() OSTaskCreateHook() OSTaskDelHook() OSTaskIdleHook() OSTaskStatHook() OSTaskSwHook() OSTCBInitHook() OSTimeTickHook() 这9个函数的代码都很简单,下面是代码,不多介绍。 [cpp] view plaincopy
- #if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
- void OSInitHookBegin (void)
- {
- #if OS_TMR_EN > 0
- OSTmrCtr = 0;
- #endif
- }
- #endif
-
- #if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
- void OSInitHookEnd (void)
- {
- }
- #endif
-
- #if OS_CPU_HOOKS_EN > 0
- void OSTaskCreateHook (OS_TCB *p_tcb)
- {
- #if OS_VIEW_MODULE > 0
- OSView_TaskCreateHook(p_tcb);
- #else
- (void)p_tcb ; /* Prevent compiler warning */
- #endif
- }
- #endif
-
- #if OS_CPU_HOOKS_EN > 0
- void OSTaskDelHook (OS_TCB *p_tcb)
- {
- (void)p_tcb ; /* Prevent compiler warning */
- }
- #endif
-
- #if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251
- extern volatile unsigned long wdg_clr_flag;
- void OSTaskIdleHook (void)
- {
- }
- #endif
-
- #if OS_CPU_HOOKS_EN > 0
- void OSTaskStatHook (void)
- {
- }
- #endif
-
- #if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0)
- void OSTaskSwHook (void)
- {
- #if OS_VIEW_MODULE > 0
- OSView_TaskSwHook();
- #endif
- }
- #endif
-
- #if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
- void OSTCBInitHook (OS_TCB *ptcb)
- {
- (void) ptcb; /* Prevent Compiler warning */
- }
- #endif
-
- #if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0)
- void OSTimeTickHook (void)
- {
- #if OS_VIEW_MODULE > 0
- OSView_TickHook();
- #endif
-
- #if OS_TMR_EN > 0
- OSTmrCtr++;
- if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC))
- {
- OSTmrCtr = 0;
- OSTmrSignal();
- }
- #endif
- }
|