嵌入式系统μC/OS-II在LPC2119上的移植方法和技巧
W(void); /* 任务级任务切换函数 */
__swi(0x01) void _OSStartHighRdy(void); /* 运行优先级最高的任务 */
__swi(0x02) void OS_ENteR_CRITICAL(void); /*关中断 */
__swi(0x03) void OS_EXIT_CRITICAL(void); /* 开中断 */
__swi(0x80) void ChangeToSYSMode(void); /* 任务切换到系统模式 */
__swi(0x81) void ChangeToUSRMode(void); /* 任务切换到用户模式 */
#define OS_STK_GROWTH 1 /* 堆栈是从上往下长的*/
定义工作模式:
#define USR32Mode 0x10 /* 用户模式 */
#define SYS32Mode 0x1f /* 系统模式*/
#define NoInt 0x80
#ifndef USER_USING_MODE
#define USER_USING_MODE USR32Mode /* 任务缺省模式*/
#endif
定义开关信号量: extern OS_STK OsEnterSum
④ 在文件OS_CPU_C.C中需要添加或修改的代码:
OS_ENTER_CRITICAL()代码
__asm
{ MRS R0, SPSR
ORR R0, R0, #NoInt
MSR SPSR_c, R0
}
OsEnterSum++;
OS_EXIT_CRITICAL()代码
if (--OsEnterSum == 0)
{ __asm
{ MRS R0, SPSR
BIC R0, R0, #NoInt
MSR SPSR_c, R0
}
}
编写任务堆栈的初始化代码:
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{ OS_STK *stk;
opt = opt; /* 'opt' 没有使用。作用是避免编译器警告 */
stk = ptos; /* 获取堆栈指针*/
/* 建立任务环境,使用满递减堆栈 */
*stk = (OS_STK) task; /* pc */
*--stk = (OS_STK) task; /* lr */
*--stk = 0; /* r12 */
?? /*r11?r2*/
*--stk = 0; /* r1 */
*--stk = (unsigned int) pdata; /* r0,第一个参数使用R0传递 */
*--stk = (USER_USING_MODE|0x00); /* spsr,允许 IRQ, FIQ 中断 */
*--stk = 0; /* 关中断计数器OsEnterSum; */
return (stk);
}
编写如void OSInitHookBegin ( )、void OSInitHookEnd ( )、void OSTaskCreateHook ( )、void OSTaskDelHook ( )等钩子函数,用户可根据需要自行添加代码。
⑤ 在文件OS_CPU_A.S中需要添加或修改的代码:
编写运行优先级最高的就绪任务函数OSStartHighRdy()调用的__OSStartHighRdy代码
__OSStartHighRdy
MSR CPSR_c, #(NoInt | SYS32Mode)
LDR R4, =OSRunning
MOV R5, #1
STRB R5, [R4]
BL OSTaskSwHook
LDR R6, =OSTCBHighRdy
LDR R6, [R6]
B OSIntCtxSw_1
编写OSIntCtxSw代码
由于篇幅所限,这里给出OSIntCtxSw函数原型,可由此编写代码。源代码详见参考文献[1]。
void OSIntCtxSw(void)
{
调用用户定义的OSTaskSwHook();
STCBCur=OSTCBHighRdy;
SPrioCur=OSPrioHighRdy;
得到需要恢复的任务的堆栈指针;
堆栈指针=OSTCBHighRdy->OSTCBStkPtr;
将所有处理器寄存器从新任务的堆栈中恢复出来;
执行中断返回指令;
}
由于篇幅所限,以上给出了移植时需要修改的与处理器相关的三个文件中的主要代码,当然更详细的移植说明可见参考文献[1].为了验证移植成功与否,你可以编写一个简单用户程序(例如通过串口通讯在PC界面显示字符)与mC/OS-II一起编译烧写进芯片来检验,笔者已经试验成功。
需要避免的错误
用户程序中的includes.h要修改为config.h,这是因为后者包含了前者和特定的头文件以及配置项。
数据类型的定义不能直接使用C中的short、int、long等,因为它们与处理器类型有关,隐含着不可移植性,所以在OS_CPU.H中定义移植性强的不依赖于编译器的数据类型。
必须定义堆栈的生长方向,1表示堆栈从上往下长,0表示堆栈从下往上长,ARM处理器两种方式都支持,但使用的ADS编译器仅支持从上往下长的方式,因此必须定义为1,否则将发生寄存器值入栈错误。
注意任务堆栈初始化函数中的stk指针定义成INT32U,这是因为我们的处理器是32位的,对堆栈操作也是4字节对齐的。如果处理器是16位的,且对堆栈访问也是2字节对齐的,就要将stk定义成INT16U,否则将会发生严重错误。
结语
μC/OS-II具有很好的可靠性、实时性和可裁减性,很适合于工业控制、通信等对实时性、可靠性要求高的领域。笔者采用广州周立功公司的EASYARN2100试验开发板,已经成功把μC/OS-II移植到该开发板上。如果用户对ARM处理器及相关底层硬件和μC/OS-II有一定了解,参照本文,对将μC/OS-II移植到LPC21xx系列ARM处理器上大有帮助。
方法 技巧 移植 LPC2119 系统 C OS-II 嵌入式 相关文章:
- 基于FPGA的DSP设计方法(08-26)
- 专家指导:Linux操作系统密码恢复方法(05-16)
- 基于多核DSP Bootload代码加载方法研究(01-16)
- 基于DSP 的大容量无线传输技术中高性能的启动方法(03-16)
- 多核调试新方法探讨(10-22)
- 有备无患Linux操作系统备份方法介绍(06-06)