uC/OS-II实时操作系统移植的一般方法和技巧

发布者:ArtisticSoul最新更新时间:2009-01-21 来源: 今日电子关键字:实时操作系统  移植  嵌入式系统 手机看文章 扫描二维码
随时随地手机看文章

引言

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

      μ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的源代码和服务函数。
如此,就可以避免不必要的编译错误,也便于开发项目的维护。

关于μC/OS-II系列软件版权的说明

      Micrium 公司产品包括μC/OS-II,μC/GUI,uC/FS,μC/TCP-IP,μC/USB等。Micrium 公司提供嵌入式系统应用方面的产品,并对其软件拥有知识产权。Micrium花费了大量的时间和财力为嵌入式领域提供高质量的软件产品。所有上述产品都以源代码的形式提供给客户,具有极大的适用性。产品不是免费软件,也不是开放源码的软件,因此,不能免费使用,需要清楚的阐明μC/OS-II和系列的软件不是开放源码的免费软件,这是和Linux完全不一样的。

      开发和研究者可以通过购买Micrium公司的Jean先生的μC/OS-II的书籍,而得到μC/OS-II源代码,但是仅可以作为个人和学校学习使用,所有和μC/OS-II直接和间接相关的商业目的行为,必须购买使用μC/OS-II及系列产品的商业授权,包括芯片/单板/系统厂家的任何参考设计,教学设备和最终的产品,如果没有得到Micrium公司Jean先生签字的合法授权都是不合法的使用, 这在μC/OS-II的书籍Micrium公司(www.micrium.com)和中国代理商-北京麦克泰软件公司网站(www.bmrtech.com)上面中有明确规定。

      Micrium公司其它软件如μC/GUI,μC/FS,μC/TCP-IP,μC/USB 等的销售模式与μC/OS-II不同,如果没有购买使用授权,完全不可以拥有该源代码,也不能将源代码用于产品的设计,培训,教学和生产。

      μC/OS-II, μC/GUI,μC/FS,μC/TCP-IP,μC/USB 等授权方式有:单个产品、产品线(系列)、按照CPU 划分的产品三种形式,μC/OS-KA,μC/OS-VIEW 等工具是按照使用人的数目收取费用的,相对起传统的RTOS 动辄2-3万美圆的开发费用和每块单板的使用费(根据数量从数百到几个美圆),μC/OS-II及系列产品是采用一次性的收费方式,应该只是大约相当于传统RTOS 的10-20% 的总体费用。

关键字:实时操作系统  移植  嵌入式系统 引用地址:uC/OS-II实时操作系统移植的一般方法和技巧

上一篇:基于JTAG的DSP外部FLASH在线编程与引导技术
下一篇:基于ADS1274的可控式高精度数据采集系统

推荐阅读最新更新时间:2024-05-02 20:45

掉电保护在嵌入式系统中的设计应用
    中心议题: 掉电保护在嵌入式系统中的设计应用 基于掉电保护方案的硬件设计     解决方案: 在S3C4510B和μClinux构建的嵌入式平台实现 使用5V和3.3V的直流稳压电源 采用守候进程的方式     在嵌入式系统设计过程中,系统的掉电保护越来越受到重视。本文介绍的方法是在用ARM7系列芯片S3C4510B和μClinux构建的嵌入式平台上实现的。整个掉电保护实现的基本思路是:产生掉电信号,捕捉掉电信号和处理掉电信号。重点介绍这个过程的具体实现。     系统防掉电设计的目的是:采用一种机制,使得系统在意外失去供电的情况下,可以保证系统运行状态的确定性以及记录数据的完整性;
[电源管理]
掉电保护在<font color='red'>嵌入式系统</font>中的设计应用
μCOS-II在ATmega128单片机上的移植与开发
  引 言   本文介绍μC/OS-Ⅱ移植到ATMEL公司的8位微控制器ATmega128上的过程。所谓移植,就是使一个实时内核可以在某个微处理器上运行,并在此基础上进行驱动程序开发,使之成为一个实用的嵌入式系统。嵌入式系统包括了硬件和软件两部分,由于系统硬件资源的限制和实际应用的要求,应用系统对软件的基本要求是体积小,执行速度快,具有较好的裁减性和可移植性。   嵌入式系统的软件一般由嵌入式操作系统和应用软件组成,通过在操作系统之上开发应用软件,可以屏蔽掉很多底层硬件细节,使得应用程序调试方便,移植简单,易维护,同时开发周期也短。多数实时操作系统为用户提供一些标准的API函数,程序开发人员可以利用这些API函数进行应用程序
[单片机]
加速物联网设备开发,瑞萨电子MCU支持Microsoft Azure RTOS
全球领先的半导体解决方案供应商瑞萨电子株式会社宣布助力IoT(物联网)设计人员简化从设备到云端的开发。瑞萨充分利用在安全嵌入式设计领域的丰富经验,在微控制器(MCU)和微处理器(MPU)产品上支持Microsoft Azure RTOS,为用户提供快速、无缝、开箱即用的开发体验。 该合作将有助于提供基于瑞萨智能、安全的芯片以及Microsoft Azure 物联网模块(包括Azure RTOS、面向C语言的Azure IoT设备SDK、IoT Plug and Play、IoT Central及IoT Hub)的完整的芯片到云端的IoT解决方案。 作为在全球MCU产品中广为部署的RTOS之一,Azure RTOS(原Thr
[物联网]
浅谈嵌入式系统在印刷设备中的解决方法
一、什么是嵌入式系统呢   目前一些先进的PDA在显示屏幕上已实现汉字写入、短消息语音发布,日用范围也将日益广阔。对于企业专用解决方案,如物流管理、条码扫描、移动信息采集等,这种小型手持嵌入式系统将发挥巨大的作用。自动控制领域,不仅可以用于ATM机,自动售货机,工业控制等专用设备,和移动通讯设备结合、GPS、娱乐相结合,嵌入式系统同样可以发挥巨大的作用。近期长虹推出的ADSL产品,结合网络,控制,信息,这种智能化,网络化将是家电发展的新趋势。   随着信息化,智能化,网络化的发展,嵌入式系统技术也将获得广阔的发展空间。美国着名未来学家尼葛洛庞帝99年1月访华时预言,4~5年后嵌入式智能(电脑) 工具将是PC和因特网之后最伟大的
[工业控制]
mini2440上一步步实现将ADS工程移植到keilMDK
从买板子到现在,想想也有2个月啦,开始就想跑裸奔的,可是工程都是在ADS下,win7系统根本不能用,于是就想着怎么在MDK跑,可是MDK上s3c2440的启动文件是不完整的,因此不推荐使用,为此蛋疼聊好长一段时间,查了很多资料都不成功,可能是我太笨啦,为此,今天把我自己的方法写给和我一样的想用MDK的童靴们吧。 首先新建一个文件夹,然后在里面新建startcode和source两个文件夹,如下 接着打开MDK新建工程,启动文件不选,如下 接着复制光盘中的启动文件2440init.s option.inc memcfg.inc 2440addr.inc到startcode,如下 然后在MDK左侧栏新建两个文件夹,分
[单片机]
mini2440上一步步实现将ADS工程<font color='red'>移植</font>到keilMDK
Linux2.6.36移植到飞凌S3C6410开发板 步骤
今天终于让linux内核在飞凌ok6410的板子上跑起来了,想来也是艰辛,为了移植成功,断断续续做了将近两个月的努力,期间郁闷不可言语形容啊, 了解其中艰辛,将自己移植步骤与心得与大家分享,希望对初踏次领域之人有所帮助,我所写的成果一部分也是网上前辈的所作,并非本人原创。 一、 移植环境 主 机:VMWare-Ubuntu 开发板:飞凌OK6410 nandflash,Kernel:2.6.36.2 编译器:arm-linux-gcc-4.3.2.tgz u-boot:u-boot-1.1.6 注:编译器和u-boot 都是飞凌开发板自带的 二、 源码获得 内核源码到http://www.all.kernel.org
[单片机]
FreeModbus 移植于STM32 实现Modbus RTU通信
毕业设计自己要做个基于STM32的PLC能直接跑语句表的,现在看来好像没有什么创新的地方,不过实现的方式绝对够创新的了...呵呵。自己写的开题报告中说了要有高级的通信功能。现在做以太网有点来不及了,CAN又感觉不搭调,硬件上也没准备。串口上跑Modbus感觉不错。本来西门子的S7-200就能跑Modbus,STM32-PLC当然也要支持Modbus 什么 组态软件,触摸屏都可以连上,不过FreeModbus只支持从机有点可惜,当然本来协议也不难而且也必要实现全协议栈。 Modbus中文协议.PDF STM32移植FreeModbus的步骤: 首先去 http://www.freemodbus.org 下载文件 一定要是
[单片机]
FreeModbus <font color='red'>移植</font>于STM32 实现Modbus RTU通信
嵌入式实时操作系统的RAM盘扩展
    摘要: 介绍了一种在嵌入式实时操作系统内核(以下简称实时内核)上实现RAM盘的方法,配合接受用户命令的Shell任务,可实现嵌入式系统的多任务动态加载和监控,扩展了实时内核的应用领域。实时内核采用目前十分流行的免费内核μC/OS-Ⅱ,硬件不台为通用现场总线控制器系统。     关键词: μC/OS-Ⅱ内核 嵌入式系统 通用现场总线控制器(GPFC) ColdFire 1 嵌入式RTOS 目前,嵌入式RTOS的应用领域越来越广泛。已经有80多个RTOS厂商生产面向8位、16位、32位、甚至64位微处理器的RTOS产品。商业的实时操作系统如VxWorks,pSOS,VRTX,WindowsCE等功能完
[应用]
小广播
最新嵌入式文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved