yidong1981的笔记 https://bbs.21ic.com/?86463 [收藏] [复制] [RSS]

日志

uC/OS-II实时操作系统在嵌入式平台上进行移植的一般方法和技巧

已有 1972 次阅读2006-6-28 14:52 |系统分类:DSP

                             作者:清华大学

引言


---实时操作系统的使用,能够简化嵌入式系统的应用开发,有效地确保稳定性和可靠性,便于维护和二次开发。


μC/OS-II是一个基于抢占式的实时多任务内核,可固化、可剪裁、具有高稳定性和可靠性,除此以外,μC/OS-II的鲜明特点就是源码公开,便于移植和维护。


在μC/OS-II官方的主页上可以查找到一个比较全面的移植范例列表。但是,在实际的开发项目中,仍然没有针对项目所采用芯片或开发工具的合适版本。那么,不妨自己根据需要进行移植。


本文则以在TMS320C6711 DSP上的移植过程为例,分析了μC/OS-II在嵌入式开发平台上进行移植的一般方法和技巧。μC/OS-II移植的基本步骤


在选定了系统平台和开发工具之后,进行μC/OS-II的移植工作,一般需要遵循以下的几个步骤:


● 深入了解所采用的系统核心
● 分析所采用的C语言开发工具的特点
● 编写移植代码
● 进行移植的测试
● 针对项目的开发平台,封装服务函数
(类似80x86版本的PC.C和PC.H)

系统核心

无论项目所采用的系统核心是MCU、DSP、MPU,进行μC/OS-II的移植时,所需要关注的细节都是相近的。

首先,是芯片的中断处理机制,如何开启、屏蔽中断,可否保存前一次中断状态等。还有,芯片是否有软中断或是陷阱指令,又是如何触发的。

此外,还需关注系统对于存储器的使用机制,诸如内存的地址空间,堆栈的增长方向,有无批量压栈的指令等。

在本例中,使用的是TMS320C6711 DSP。这是TI公司6000系列中的一款浮点型号,由于其时钟频率非常高,且采用了超常指令字(VLIW)结构、类RISC指令集、多级流水等技术,所以运算性能相当强大,在通信设备、图像处理、医疗仪器等方面都有着广泛的应用。

在C6711中,中断有3种类型,即复位、不可屏蔽中断(NMI)和可屏蔽中断(INT4-INT15)。可屏蔽中断由CSR寄存器控制全局使能,此外也可用IER寄存器分别置位使能。而在C6711中并没有软中断机制,所以μC/OS-II的任务切换需要编写一个专门的函数实现。

此外,C6711也没有专门的中断返回指令、批量压栈指令,所以相应的任务切换代码均需编程完成。由于采用了类RISC核心,C6711的内核结构中,只有A0-A15和B0-B15这两组32bit的通用寄存器。 

C语言开发工具

无论所使用的系统核心是什么,C语言开发工具对于μC/OS-II是必不可少的。
最简单的信息可以从开发工具的手册中查找,比如:C语言各种数据类型分别编译为多少字节;是否支持嵌入式汇编,格式要求怎样;是否支持“interrupt”非标准关键字声明的中断函数;是否支持汇编代码列表(list)功能,等等。

上述的这样一些特性,会给嵌入式的开发带来很多便利。TI的C语言开发工具CCS for C6000就包含上述的所有功能。

而在此基础上,可以进一步地弄清开发工具的一些技术细节,以便进行之后真正的移植工作。

首先,开启C编译器的“汇编代码列表(list)”功能,这样编译器就会为每个C语言源文件生成其对应的汇编代码文件。

在CCS开发环境中的方法是:在菜单“/Project/Build options”的“Feedback”栏中选择“Interlisting:Opt/C and ASM(-s)”;或者,也可以直接在CCS的C编译命令行中加上“-s”参数。

然后分别编写几个简单的函数进行编译,比较C源代码和编译生成的汇编代码。例如:

void FUNC_TEMP (void)
{
Func_tmp2(); //调用任一个函数
}
在CCS中编译后生成的ASM代码为:
.asg B15, SP // 宏定义
_FUNC_TEMP:
STW B3,*SP--(8) // 入栈
NOP 2
CALL _ Func_tmp2 //-----------
MVKL BACK, B3 // 函数调用
MVKH BACK, B3 //-----------
NOP 3 
BACK: LDW *++SP(8),B3 // 出栈
NOP 4
RET B3 // 函数返回
NOP 5

由此可见,在CCS编译器的规则中,B15寄存器被用作堆栈指针,使用通用存取指令进行栈操作,而且堆栈指针必须以8字节为单位改变。

此外,B3寄存器被用来保存函数调用时的返回地址,在函数执行之前需要入栈保护,直到函数返回前再出栈。

当然,CCS的C编译器对于每个通用寄存器都有约定的用途,但对于μC/OS-II的移植来说,了解以上信息就足够了。

最后,再编写一个用“interrupt”关键字声明的函数:

interrupt void ISR_TEMP (void)
{
int a;
a=0;
}
生成的ASM代码为:
_ISR_TEMP:
STW B4,*SP--(8) // 入栈
NOP 2
ZERO B4 //---------
STW B4,*+SP(4) // a=0
NOP 2 //----------
B IRP // 中断返回
LDW *++SP(8),B4 // 出栈
NOP 4 

与前一段代码相比,对于中断函数的编译,有两点不同:

● 函数的返回地址不再使用B3寄存器,相应地也无需将B3入栈。(IRP寄存器能自动保存中断发生时的程序地址)

● 编译器会自动统计中断函数所用到的寄存器,从而在中断一开始将他们全部入栈保护——例如上述程序段中,只用到了B4寄存器。

编写移植代码

在深入了解了系统核心与开发工具的基础上,真正编写移植代码的工作就相对比较简单了。

μC/OS-II自身的代码绝大部分都是用ANSI C编写的,而且代码的层次结构十分干净,与平台相关的移植代码仅仅存在于OS_CPU_A.ASM、OS_CPU_C.C以及OS_CPU.H这三个文件当中。

在移植的时候,结合前面两个步骤中已经掌握的信息,基本上按照《嵌入式实时操作系统μC/OS-II》一书的相关章节的指导来做就可以了。

但是,由于系统核心、开发工具的千差万别,在实际项目中,一般都会有一些处理方法上的不同,需要特别注意。以C6711的移植为例:

● 中断的开启和屏蔽的两个宏定义为:
#define OS_ENTER_CRITICAL() Disable_int() 
#define OS_EXIT_CRITICAL() Enable_int()

Disable_int和Enable_int是用汇编语言编写的两个函数。在这里使用了控制状态寄存器(CSR)的一个特性——CSR中除了控制全局中断的GIE位之外,还有一个PGIE位,可用于保存之前的GIE状态。

因此在Disable_int中先将GIE的值写入PGIE,然后再将GIE写0,屏蔽中断。而在Enable_int中则从PGIE读出值,写入GIE,从而回复到之前的中断设置。

这样,就可以避免使用这两个宏而意外改变了系统的中断状态——此外,也没有使用堆栈或局部变量,比原作者推荐的方法要好。

● 任务的切换:
前文说过,C6711中没有软中断机制,所以任务的切换需要用汇编语言自行编写一个函数_OSCtxSw来实现,并且
#define OS_TASK_SW() OSCtxSw()
在C6711中需要入栈保护的寄存器包括A0-A15、B0-B15、CSR、IER、IRP和AMR,这些再加上当前的程序地址构成一个存储帧,需要入栈保存。
_OSCtxSw函数中,需要像发生了一次中断那样,将上述存储帧入栈,然后获取被激活任务的TCB指针,将其存储帧的内容弹出,从而完成任务切换。
需要特别注意的是,在这里OS_TASK_SW是作为函数调用的,所以如前文所述,调用时的当前程序地址是保存在B3寄存器中的,这也就是任务重新激活时的返回地址。

● 中断的编写:
如前文所述,如果用“interrupt”关键字声明函数,CCS在编译时,会自动将该函数中使用到的寄存器入栈、出栈保护。
但是,这会导致各种中断发生时,出入栈的内容各不相同。这对于μC/OS-II是会引起严重错误的。因为μC/OS-II要求中断发生时的入栈操作使用和发生任务切换时完全一样的存储帧结构。
因此,在移植时、基于μC/OS-II进行开发时,都不应当使用“interrupt”关键字,而应用如下结构编写中断函数:

void OSTickISR (void)
{
DSP_C6x_Save(); // 服务函数,入栈
OSIntEnter();
if (OSIntNesting == 1) // v2.51版本新增加
{
OSTCBCur->OSTCBStkPtr
=(OS_STK*) DSP_C6x_GetCurrentSP(); // 服务函数
} // 获取当前SP的值
// 允许中断嵌套 则在此处开中断
OSTimeTick();
OSIntExit();
DSP_C6x_Resume(); // 服务函数,出栈
}
DSP_C6x_Save和DSP_C6x_Resume是两个服务函数,分别完成中断的出、入栈操作。它们与OS_TASK_SW函数的区别在于:中断发生时的当前程序地址是自动保存在IRP寄存器的,应将其作为任务返回地址,而不再是B3。此外,DSP_C6x_Resume是一个永远不会返回的函数,在将所有内容出栈后,它就直接跳转回到中断发生前的程序地址处,继续执行。

进行移植的测试
在编写完了所有的移植代码之后,就可以编写几个简单的任务程序进行测试了,大体上可以分三个步骤来进行,相关资料比较详尽,这里就不多作赘述了。

封装服务函数
最后这个步骤,往往是容易被忽视的,但对于保持项目代码的简洁、易维护有很重要的意义。
μC/OS-II的原作者强烈建议将源代码分路径进行存储,例如本文例子中的所有源代码就应按如下路径结构存储:
\uCOS-II
├─SOURCE // 平台无关代码
│ OS_CORE.C
│ ......
└─TI_C6711 // 系统核心
├─CCS // 开发工具
│ OS_CPU.H 
│ OS_CPU_A.ASM
│ OS_CPU_C.C

├─ DSP_C6x_Service // 服务函数
│ DSP_C6x_ Service.H
│ DSP_C6x_ Service.ASM 

└─ TEST // 具体的开发项目代码
OS_CFG.H
INCLUDES.H
TEST.C ......

如上,DSP_C6x_Service中的服务函数,类似于原作者提供的80x86版本中的PC.C和PC.H文件。在本文的例子中,服务函数则包括了上文提及的中断相关函数,以及系统初始化函数DSP_C6x_SystemInit()和时钟初始化函数DSP_C6x_TimerInit()等。
而具体的开发项目代码,则可以分别在“/TI_C6711”路径下新建自己的目录,就如同移植测试的“TEST”项目,而无需再关注μC/OS-II的源代码和服务函数。
如此,就可以避免不必要的编译错误,也便于开发项目的维护。


路过

鸡蛋

鲜花

握手

雷人

发表评论 评论 (2 个评论)

回复 softradio 2006-7-26 13:24
想请教一下,为什么不使用TI的DSP/BIOS,和DSP/BIOS相比较使用uC/OS有什么特别的好处么?
bgh56 2006-8-14 08:43
ss cdma彩铃 彩铃之家 联通彩铃网 我的彩铃 云南移动彩铃 辽宁移动彩铃 手机彩铃免费下载 吉林移动彩铃 动感地带彩铃 江西移动彩铃 彩铃唱作先锋 中国移动通信彩铃 联通彩铃网站 黑龙江移动彩铃 黑龙江彩铃 免费手机彩铃 四川彩铃 中国电信彩铃 湖北移动彩铃 电信彩铃 上海彩铃 山东彩铃 彩铃先锋大赛 江西彩铃 彩铃唱作先锋大赛 北京联通彩铃 湖南移动彩铃 湖南彩铃 湖北彩铃网 天津移动彩铃网站 山西彩铃 集团彩铃 中国移动彩铃业务 移动彩铃网站 四川移动彩铃 广东彩铃业务 天津彩铃 广西移动彩铃 北京移动彩铃 河南彩铃 取消彩铃 彩铃先锋 山西移动彩铃 彩铃制作 浙江彩铃网 移动彩铃网 上海移动彩铃 江苏彩铃 中国移动彩铃网站 彩铃管理 福建彩铃网站 山东移动彩铃 福建彩铃网 安徽彩铃 浙江移动彩铃网 江苏移动彩铃 浙江移动彩铃网站 彩铃设置 广西彩铃 安徽移动彩铃 湖北彩铃 彩铃业务 福建移动彩铃 中国移动彩铃下载 河南移动彩铃 河北移动彩铃 河北彩铃 彩铃大赛 广东移动彩铃业务 移动彩铃下载 中国联通彩铃 中国移动彩铃网 彩铃网 联通彩铃下载 彩铃网站 天津移动彩铃 彩铃乐翻天 浙江彩铃 手机彩铃下载 广东移动彩铃 福建彩铃 免费彩铃下载 搞笑彩铃 广东彩铃 浙江移动彩铃 联通彩铃 中国移动彩铃 手机彩铃 免费彩铃 移动彩铃 彩铃下载 手机铃声下载到电脑 经典手机铃声 七彩铃声 手机铃声编辑器 铃声制作工具 最新手机铃声 adp铃声 移动手机铃声下载 真人真唱铃声下载 短信铃声下载 手机短信铃声 来电铃声 mmf铃声免费下载 钟辉铃声工作室 摩托罗拉铃声 铃声编辑器 真人真唱铃声 如何下载手机铃声 mmf手机铃声 nokia铃声下载 自编铃声 mmf格式铃声下载 nokia铃声 摩托罗拉铃声下载 qd铃声 mp3铃声制作软件 经典铃声 电话铃声 手机铃声制作工具 联通手机铃声 mp3铃声制作 amr铃声下载 移动铃声 mmf格式铃声 比特铃声 免费mp3铃声 mp3超强铃声转换器 搞怪铃声 小灵通铃声免费下载 铃声论坛 三星铃声 三星铃声下载 和弦铃声下载 联通铃声 amr铃声 手机铃声格式 dj铃声 铃声制作软件 中国移动铃声下载 移动铃声下载 搞笑铃声下载 mp3手机铃声下载 诺基亚手机铃声 midi铃声下载 个性铃声 qq铃声 mp3铃声免费下载 mid铃声下载 三星手机铃声 铃声制作 搞笑手机铃声 诺基亚手机铃声下载 诺基亚铃声下载 手机铃声制作软件 诺基亚铃声 和弦铃声 三星手机铃声下载 手机铃声制作 mid铃声 联通铃声下载 mp3手机铃声 midi铃声 手机铃声论坛 特效铃声 mmf铃声下载 mmf铃声 小灵通铃声 短信铃声 mp3铃声下载 小灵通铃声下载 免费手机铃声 搞笑铃声 mp3铃声 手机铃声免费下载 免费铃声 免费铃声下载 铃声下载 手机铃声下载 手机铃声 最便宜的手机彩铃 移动手机彩铃网 手机彩铃免费下 广东移动手机彩铃 手机彩铃服务 手机漫游彩铃 手机彩铃更改 山西手机彩铃 新疆手机彩铃下载 手机彩铃设定 移动手机彩铃设置 联想手机彩铃 cdma手机彩铃下载 诺基亚手机彩铃下载 手机彩铃排行 诺基亚手机彩铃 手机彩铃排行榜 联通免费手机彩铃 免费的手机彩铃下载 铃声下载手机彩铃 如何制作手机彩铃 手机彩铃制作工具 手机彩铃大赛 手机彩铃制作软件 天津移动手机彩铃 手机注册彩铃 手机彩铃下载网 手机来电彩铃 上海移动手机彩铃 山东手机彩铃 免费dj手机彩铃 三星手机彩铃 最新手机彩铃 免费的手机彩铃 手机换彩铃 移动手机搞笑彩铃 lg免费手机彩铃 索爱手机彩铃下载 中国联通手机彩铃 手机彩铃业务 浙江手机彩铃 三星手机彩铃下载 手机彩铃大全 手机彩铃试听 我的手机彩铃 手机彩铃管理 手机彩铃下载网站 移动手机彩铃网站 手机彩铃开通 手机彩铃图片 搞笑手机彩铃下载 怎样下载手机彩铃 福建手机彩铃 移动手机免费彩铃 手机彩铃制作 手机彩铃网站 手机彩铃设置 搞笑手机彩铃 联通手机彩铃下载 手机彩铃网 中国移动手机彩铃 移动手机彩铃下载 联通手机彩铃 移动手机彩铃 手机彩铃免费下载 免费手机彩铃 手机彩铃下载 moto手机铃声下载 手机铃声试听 手机自编铃声 手机铃声之家 怎么下载手机铃声 cdma手机铃声 lg手机铃声 手机铃声网站 nec手机铃声 手机和弦铃声 中国移动手机铃声 手机和弦铃声下载 手机铃声打包下载 手机铃声下载网站 手机铃声免费下 索爱手机铃声下载 amr手机铃声 手机铃声转换工具 cdma手机铃声下载 最新手机铃声下载 飞利浦手机铃声 索爱手机铃声 手机铃声diy dj手机铃声 手机铃声排行 手机来电铃声 lg手机铃声下载 联想手机铃声 个性手机铃声 如何制作手机铃声 midi手机铃声 夏新手机铃声下载 手机铃声排行榜 移动手机铃声 手机铃声软件 nec手机铃声下载 mmf手机铃声下载 手机铃声编辑 手机铃声网 手机铃声下载软件 手机铃声编辑软件 手机铃声图片 韩国手机铃声 手机铃声图片下载 搞笑手机铃声下载 nokia手机铃声下载 手机铃声转换器 免费mp3手机铃声 手机特效铃声 手机铃声下载论坛 联想手机铃声下载 严守一手机铃声 mid手机铃声 手机铃声转换 nokia手机铃声 怎样下载手机铃声 摩托罗拉手机铃声 经典手机铃声 手机铃声编辑器 最新手机铃声 移动手机铃声下载 手机短信铃声 如何下载手机铃声 mmf手机铃声 手机铃声制作工具 联通手机铃声 手机铃声格式 mp3手机铃声下载 诺基亚手机铃声 三星手机铃声 搞笑手机铃声 诺基亚手机铃声下载 手机铃声制作软件 三星手机铃声下载 手机铃声制作 mp3手机铃声 手机铃声论坛 免费手机铃声 手机铃声免费下载 手机铃声下载 手机图铃下载 手机铃音下载 手机音乐下载 手机图片下载 彩信下载 免费手机图片 移动彩铃主页 宁夏移动彩铃 海南移动彩铃 移动彩铃管理 上海移动彩铃业务 中国移动手机彩铃 天津移动彩铃业务 移动手机彩铃下载 浙江移动12350彩铃 移动彩铃网址 贵州移动彩铃 深圳移动彩铃 重庆移动彩铃 中国移动免费彩铃 广东移动12350彩铃 内蒙古移动彩铃 移动彩铃设置 中国移动12350彩铃 新疆移动彩铃 移动免费彩铃 广州移动彩铃 移动手机彩铃 甘肃移动彩铃 云南移动彩铃 辽宁移动彩铃 吉林移动彩铃 江西移动彩铃 中国移动通信彩铃 黑龙江移动彩铃 湖北移动彩铃 湖南移动彩铃 四川移动彩铃 广西移动彩铃 北京移动彩铃 山西移动彩铃 移动彩铃网 上海移动彩铃 山东移动彩铃 江苏移动彩铃 安徽移动彩铃 福建移动彩铃 河南移动彩铃 河北移动彩铃 移动彩铃下载 天津移动彩铃 广东移动彩铃 浙江移动彩铃 中国移动彩铃 彩票ll