嵌入式操作系统是嵌入式应用的基础和核心。随着应用系统的不断复杂化和系统实时性需求的不断提高,对相应软件的逻辑结构、稳定性、实时性也提出了更高的要求,以传统的前后台编程模式编制软件将更加困难,而且容易出错,因此,嵌入式实时操作系统(简称RTOS)就成为一个比较好的解决方法。使用RTOS作为应用程序的运行平台,它将应用程序分解为多个任务,负责各个任务调度、资源管理、任务通信等,可使系统更加稳定可靠,程序易于扩展、移植和维护。[1]

μC/OS-Ⅱ是一个源码公开的、非商业用途时免费的嵌入式实时操作系统,它有许多方面可与商业的实时内核相媲美。它是一个基于优先级的多任务实时操作系统,包含了实时内核、任务管理、时间管理、任务间通信和内存管理等功能,具有很强的可裁剪性和可移植性,可以适应不同系统的要求灵活地进行配置。本文以Silicon Laboratories公司高性能单片机C8051F060为硬件平台,在成功移植了μC/OS-Ⅱ操作系统的基础上,并针对实际的工程项目建立了多任务操作系统。该系统已应用于智能碳硫分析仪控制器中,通过现场的调试,系统运行准确可靠。

2. μC/OS-Ⅱ的工作原理

μC/OS-Ⅱ是一个基于优先级的多任务实时操作系统,即系统的调度是以优先级为基础的,每一个任务根据其重要性分配有一个优先级,系统总是运行处于就绪态下的优先级最高的任务。每个任务通常都是一个无限的循环,都会处在以下5种状态之一:睡眠态、就绪态、运行态、等待态和中断服务态,任务的状态转换图如图1所示。[2] 

在μC/OS-II 中把睡眠态中的任务交给内核管理是通过调用函数OSTaskCreat()或者OSTaskCreatExt()来实现的。任务建立时,用户可以给任务分配优先级和栈空间等。任务一旦建立,这个任务就进入就绪状态准备运行。内核通过任务调度,使得就绪态中优先级最高的任务开始运行,任何时刻只能有一个任务处于运行态。正在运行的任务可以通过延时或等待某个事件的发生进入等待状态,这时该任务的CPU使用权被剥夺,只有当延时时间到或者收到等待的消息,任务才可以进入就绪态,等待下一次的任务调度。处于运行态、等待态和就绪态的任务可以调用内核函数将自己删除,即该任务重返睡眠态。正在运行的任务可以被中断而挂起,这时中断服务子程序控制了CPU的使用权,中断结束时内核会进行任务调度。当μC/OS-II 决定运行另外的任务时,它就会将当前任务的运行状态,即处理器所有寄存器的内容,保存在该任务堆栈或系统中断堆栈之中,然后把下一个将要运行的任务当前状态从该任务栈区中重新装入处理器的寄存器,并开始运行。

3.  C8051F060功能简介

C8051FXXX系列单片机是完全集成的混合信号系统级芯片,其指令集与MCS-51系列单片机完全兼容。除了具有标准8051的数字外设部件外,片内还集成了数据采集和控制系统中常用的模拟部件和其它数字外设及功能部件。与传统的MCS-51相比,该单片机的CPU采用流水线结构的CIP-51内核,最高系统时钟频率可达25MHz,70%的指令执行是在一个或两个系统时钟周期内完成。[3]本系统中使用C8051F060单片机作为现场控制器件,该器件采用100引脚TQFP封装,具有丰富的I/O接口资源,各个I/O端口的功能可通过片内的优先权交叉开关译码器进行配置;内含两个16 位分辨率的A/D转换器,转换速率可编程,最大为1Mbps;同时含有4352×8位数据RAM和64K×8位FLASH存储器,可在系统编程。

具体移植

4.1 编译工具及运行环境

实现μC/OS-Ⅱ的移植,要求所使用的C编译器支持混合编程。KEIL C51可以为众多的8051派生器件编程,我们选用的是KEIL7.06,运行环境是Silicon Laboratories IDE Version 2.4,也可以在Keil uVision2 IDE 中调试C8051F 系列单片机,必须安装动态链接库。适配器使用Silicon Lab 公司的EC2,通过JTAG接口,可以在线编程调试。μC/OS- II 内核使用了V2.52 版本。

4.2移植过程

移植过程中需要修改与处理器相关的四个文件:启动代码STARTUP.A51、头文件OS_CPU.H 、C语言文件OS_CPU_C.C及汇编语言文件OS_CPU_A.ASM。

启动代码STARTUP.A51

由于选择KEIL C51 在大模式下编译,所以设置XBPSTACK EQU 1,而设置IBPSTACK EQU 0。C8051F060MCU自带4KRAM,故设置XBPSTACKTOP EQU 0FFFH+1。

头文件OS_CPU.H

这个文件包括了用#define语句定义的、与处理器相关的常数、宏以及类型。其中需改动的部分如下:

typedef unsigned char OS_STK   /* 堆栈入口宽度为8位*/

#define OS_STK_GROWTH   0 /*堆栈增长方向*/

#define OS_ENTER_CRITICAI ()   EA=0  /*关中断*7

#define OS_EXIT_CRITICAI  ()   EA=1  /*开中断*/

#define OS_TASK_Sw()  OSCtxSw()  /*任务调度*/

在C8051F060MCU中,数据宽度和堆栈宽度都是8位,所以将OS_STK定义成unsigned char型,它的堆栈是从下向上递增的,定义OS_STK_GROWTH为0。μC/OS-Ⅱ在进入系统临界代码区之前要关中断,等到退出临界区后再打开,以保护核心数据不被多任务环境下的其它任务或中断破坏。内核提供了3 种处理临界代码的方法,这里使用第一种,即通过对寄存器EA 开关中断。由于51指令集中没有软中断指令,所以任务切换用函数0SCtxSw()代替。

C语言文件OS_CPU_C.C

当某个任务建立时,用户都要为任务分配一个堆栈空间,用来存放任务的起始地址、处理器状态、中断返回地址和一些参数。一般函数调用时函数堆栈的操作过程是编译器自动完成的,而任务切换时需要模拟一个和编译器类似的任务堆栈的操作过程。实际上,μC/OS-Ⅱ的移植工作主要就是解决这个问题,OSTaskStkInit ( ) 是完成任务堆栈初始化工作,后面介绍的OS_CPU_A..ASM文件完成3 种不同状态下的任务切换操作。

在文件OS_CPU_C.C中,主要要求用户编写OSTaskStkInit()函数,下面列出了该函数编写情况。

void *OSTaskStkInit(void (*task)(void*pd), void *ppdata, void *ptos, INT16U opt) REENTRANT

{ OS_STK *stk;

ppdata = ppdata;                             /*防止警告  */

opt= opt;

stk= (OS_STK *)ptos;/*栈底           */

*stk++ = (0xFF + 1); /*仿真堆栈    */

*stk++ = 2 + 14;                 /* 2字节返回地址和14个字节寄存器*/

*stk++ = (INT16U)task & 0xFF;/*返回地址地位   */

*stk++ = (INT16U)task >> 8;   /*返回地址高位      */

*stk++ = 0x84;  /* SFRPAGE */

*stk++ = 0xE0;  /* ACC */

*stk++ = 0xF0;  /* B          */

*stk++ = 0x83;  /* DPH */

*stk++ = 0x82;  /* DPL */

*stk++ = 0xD0;  /* PSW */

*stk++ = 0x00;  /* R0  */

*stk++ = 0x01;  /* R1  */

*stk++ = 0x02;  /* R2  */

*stk++ = 0x03;  /* R3  */

*stk++ = 0x04;  /* R4  */

*stk++ = 0x05;  /* R5  */

*stk++ = 0x06;  /* R6  */

*stk++ = 0x07;  /* R7  */

return ((void *)ptos);                      /*返回栈顶地址*/

}

在OSTaskStkInit()函数中,处理器的入栈地址一定要正确无误,否则移植后的程序在运行时会出现一些未知错误。这里,需要指出寄存器SFRPAGE的用途,特殊功能寄存器SFR的地址在片内内存0x80~0xFF,而C8051F060具有超过128个特殊寄存器,两者是矛盾的。为了解决这个问题,C8051F060采用了分页技术,将寄存器放于不同的页,所以SFRPAGE这个寄存器必须在用户堆栈中保存。

汇编语言文件OS_CPU_A.ASM

这个文件要编写4个的汇编语言函数:OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()和OSTickISR()。除了OSTickISR(),每一个函数都需要用PUBLIC声明为可以被外部模块调用。在大模式下,函数声明的固定格式为?PR?函数名?模块名 SEGMENT CODE,如?PR?OSStartHighRdy? OS_CPU_A SEGMENT CODE。模块中还需要引用4个外部可重入函数:OSIntEnter()、OSTaskSwHook()、OSIntExit()、OSTimeTick(),声明格式为EXTRN CODE (_?OSTaskSwHook)等;5个外部全局变量:OSTCBCur、OSTCBHighRdy、OSRunning、OSPrioCur、OSPrioHighRdy,申明格式为EXTRN IDATA (OSTCBCur)等。

另外,由于任务切换需要寄存器频繁的进栈和出栈;因此,将进栈、出栈操作定义为宏以减少代码编写量。入栈是将寄存器PSW、ACC、B、DPL 、DPH、R0~R7、SFRPAGE依次压入堆栈,出栈的顺序则刚好相反。

OSStartHighRdy()是由任务启动函数OS_Start()调用来使就绪态任务中优先级最高的任务开始运行。任务级的切换由函数OSCtxSw()完成,而中断级的任务切换用OSIntCtxSw()实现。当中断调用结束后,系统将判断是否有更高优先级的任务处于就绪态,如果有比被中断的任务优先级更高的任务,则系统将进行任务调度,以运行处于就绪态的优先级最高的任务,否则就返回被中断的任务。OSIntCtxSw()的代码与OSCtxSw()非常相似,唯一的区别是OSIntCtxSw()不需再保存寄存器,保存寄存器的工作已由中断服务程序完成。μC/OS-Ⅱ运行需要一个周期性的时钟源,用于时间延迟和确认超时。本文使用定时器T0来产生时钟节拍,定时中断服务程序由OSTickISR()完成[1]

5应用

本文在C8O51F060的硬件平台上实现了μC/OS-Ⅱ的移植,并将其应用在碳硫分析仪的控制器中。碳硫分析仪主要应用在冶金钢铁行业,用来分析钢铁等金属中的碳、硫含量。针对应用系统所要实现的功能,将整个系统划分为五个并行执行的任务,按其优先级从高到低顺序排列依次是:系统监视任务、通讯显示任务、过程控制任务、采集处理任务和打印结果任务。[4]当系统上电复位后,首先进行C8O51F060及外设初始化;接着进行嵌入式操纵系统μC/OS-Ⅱ初始化;上面准备工作做好后,开始创建多任务,并且分配任务的优先级,建立任务间通信的信号量、消息邮箱;启动多任务调度,系统程序从优先级最高的任务开始执行。主程序流程图如图2所示。

多任务启动后,系统监视任务优先权最高,所以最先进入运行态。它是用来监视系统状态的,用于判断是否有升炉信号到,如果没有则直接调用函数OSTaskSuspend()将自身挂起,如果收到信号则发送消息给过程控制任务后将自身挂起。按优先权级别顺序,与触摸屏的通讯显示任务将由就绪态转为运行态,该任务用于实时刷新系统当前所处的状态。按手动触摸按键反应时间而定,约为120 ms,所以任务每次执行完都会调用函数OSTimeDlyHMSM()将自身延时100ms,暂时退出就绪态。接着过程控制任务进入运行态,它首先判断有没有收到升炉信号,如果有则按照分析过程要求依次执行准备、通氧、对零、吸收和回复动作。该任务会在执行相应动作时发送消息给数据采集处理任务和打印任务,然后自身延时,交出CPU 使用权。数据采集处理任务和打印任务在收到过程控制任务的消息后执行相应动作,在调用OSSemPend()后将自身挂起。过程控制任务在整个动作结束时调用OSTaskResume()将系统监视任务唤醒。由于C8051F060的处理器速度足够快,所有任务可以在满足时序的前提下顺利执行。

结论

本文作者的创新点:在C8O51F060的硬件平台上实现了μC/OS-Ⅱ的移植,并将其应用在智能碳硫分析仪的控制器中。与传统前后编程模式相比,嵌入式实时操作系统的应用大大提高嵌入式系统开发的效率,改变以往嵌入式软件设计只能针对具体的应用从头做起的状况。在实时操作系统上进行开发减少了系统开发的工作量,增强了软件的可移植性,提高了系统的实时性,使嵌入式系统的开发方法更具科学性。

参考文献

[1]  郭雨梅,闫磊著.嵌入式实时操作系统μC/OS-II在C8051F020上的移植[J].沈阳工业大学学报,2005, 27(1):59-62

[2]  Jean J.Labrosse著,邵贝贝译.嵌入式实时操作系统μC/OS-Ⅱ[M].北京:北京航空航天大学出版,2003.

[3]  潘琢金,施围君著.C8051FXXX高速SOC单片机原理及应用[M],第1版.北京:北京航空航天大学出版,2002

[4]  杨华,殷承良. μC/OS-Ⅱ在混合动力汽车总控制中的应用[J].微计算机信息,2007,23(5):262-264

 

μC/OS-Ⅱ在C8051F060上的移植及其应用的更多相关文章

  1. KEIL MDK环境下uCOS-II在LPC17xx上的移植实例

    1. 知识准备 要想对ucos-ii的移植有较深的理解,需要两方面知识: (1)目标芯片,这里是lpc17xx系列芯片,它们都是基于ARMv7 Cortex-M3内核,所以这一类芯片的ucos-ii移 ...

  2. 怎样把UCos-ii_在STM32上的移植

    下载代码 stm32 标准外设库是 stm32 全系列芯片的外设驱动,有了它能够大大加速我们 开发 stm32. 首先从 st 公司的站点下载最新的 stm32 标准外设库,写本文时最新的版本号是 V ...

  3. 国内操作系统OS分析(上)

    国内操作系统OS分析(上) 一.操作系统(OS)概述 操作系统(OS,Operating System),是管理.控制计算机软硬件资源的计算机程序,并为用户提供一个与系统交互的操作界面.OS是配置在计 ...

  4. Qt4.8.5在ARM9上的移植

    Qt4.8.5在ARM9开发板上的移植 以前移植过qtopia-embedded-2.2.0,俗称Qt/E,在早期的Qt框架中是使用X11桌面服务器系统,无法应用于嵌入式平台,为此产生了qtopia, ...

  5. mac os 10.10上安装my eclipse显示virtual memory不足,解决方案

    mac os 10.10上安装my eclipse显示virtual memory不足,安装失败. 自从把OS 升级到10.10 之后, 各种问题, 安装的时候向导提示提示我们说没有足够的虚拟内存, ...

  6. OpenCV在ARM上的移植

    OpenCV在ARM上的移植 与X86 Linux类似,请参考:Linux 下编译安装OpenCV 本文在此基础上进行进一步操作. 网络上很多移植编译的方法比较老,多数针对OpenCV 1.0,而且方 ...

  7. UCOSII在STM32F1上的移植

    UCOSII在STM32F1上的移植 首先准备好一份STM32F1的工程.UCOSII源码. 在准备好的工程中新建一个"UCOSII"文件夹(或者取其它名字也行): UCOSII文 ...

  8. SPI在linux3.14.78 FS_S5PC100(Cortex A8)和S3C2440上驱动移植(deep dive)

    由于工作的原因,对SPI的理解最为深刻,也和SPI最有感情了,之前工作都是基于OSEK操作系统上进行实现,也在US/OS3上实现过SPI驱动的实现和测试,但是都是基于基本的寄存器操作,没有一个系统软件 ...

  9. 苹果快速的修复了Mac OS High Sierra 上出现了root的漏洞

    最近苹果因为Mac最新系统 Mac OS High Sierra 上出现了root的漏洞走上了风口浪尖,不过还好,在一封苹果给科技媒体'9to5 Mac'的回复中得知,苹果在接收到报告之后,立即展开修 ...

随机推荐

  1. Java多线程之ThreadLocal总结

    原贴地址:http://www.cnblogs.com/zhengbin/p/5674638.html 阅读目录 官方对ThreadLocal的描述: <Thinking in Java> ...

  2. 在HL引擎中制作自定义高清贴花

    你是不是想过要做自定义的子弹孔.喷漆或者一些自定义的痕迹呢? 如果按照HL引擎的基本FA,首先要在decals.wad里加入我们自定义的纹理,然后利用gEngfuncs.pEfxAPI->R_D ...

  3. False Ordering LightOJ - 1109(暴力。。唉,。又是一个水题。。)

    We define b is a Divisor of a number a if a is divisible by b. So, the divisors of 12 are 1, 2, 3, 4 ...

  4. BZOJ 3282: Tree

    3282: Tree Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1714  Solved: 765[Submit][Status][Discuss ...

  5. 浅谈Tarjan算法及思想

    在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连 ...

  6. 【Cf #503 C】Sergey's problem(有趣的构造)

    感觉这种构造题好妙啊,可我就是想不到诶. 给出一张无自环的有向图,回答一个独立集,使得图中任意一点都可以被独立集中的某一点两步之内走到. 具体构造方案如下: 下标从小到大枚举点,如果该点没有任何标记, ...

  7. 【cdq分治】【P4390】[BOI2007]Mokia 摩基亚

    Description 给你一个 \(W~\times~W\) 的矩阵,每个点有权值,每次进行单点修改或者求某子矩阵内权值和,允许离线 Input 第一行是两个数字 \(0\) 和矩阵大小 \(W\) ...

  8. 简例 - robot case格式

    注意robot的case格式 # *** Variables *** # *** Settings *** # Library String # Library Selenium2Library ** ...

  9. 第一天:简单工厂模式与UML类图

    何为简单工厂模式:     通过专门定义一个类,来负责创建其他类的实例,这些其它类通常具有共同的父类.   简单工厂模式的UML类图:       简单工厂模式中包含的角色和相应的职责如下:     ...

  10. ElasticStack系列之十五 & query cache 引起性能问题思考

    问题描述 一个线上集群,执行的 Query DSL 都是一样的,只是参数不同.统计数据显示 98% ~ 99% 的查询相应速度都很快,只需要 4 ~ 6ms,但是有 1% 左右的查询响应时间在 100 ...