构造一个51单片机的实时操作系统

发布者:科技奇思最新更新时间:2006-10-18 来源: 单片机与嵌入式系统ic网关键字:容量  嵌入式  重入 手机看文章 扫描二维码
随时随地手机看文章
目前,大多数的产品开发是在基于一些小容量的单片机上进行的。51系列单片机,是我国目前使用最多的单片机系列之一,有非常广大的应用环境与前景,多年来的资源积累,使51系列单片机仍是许多开发者的首选。针对这种情况,近几年涌现出许多基于51内核的扩展芯片,功能越来越齐全,速度越来越快,也从一个侧面说明了51系列单片机在国内的生命力。

多年来我们一直想找一个合适的实时操作系统,作为自己的开发基础。根据开发需求,整合一些常用的嵌入式构件,以节约开发时间,尽最大可能地减少开发工作量;另外,要求这个实时操作系统能非常容易地嵌入到小容量的芯片中。毕竟,大系统是少数的,而小应用是多数而广泛的。显而易见,μC/OS—II是不太适合于以上要求的,而Keil C所带的RTX Tiny不带源代码,不具透明性,至于其FULL版本就更不用说了。

1 KeiI C51与重入问题

说到实时操作系统,就不能不考虑重入问题。对于PC机这样的大内存处理器而言,这似乎并不是一个很麻烦的问题,借用μC/OS—II RTOS的说法,即要求在重入的函数内,使用局部变量。但5l系列单片机堆栈空间很小,仅局限在256字节之内,无法为每个函数都分配一个局部堆空间。正是由于这个原因,Keil C51使用了所谓的可覆盖技术:
  ①局部变量存储在全局RAM空间(不考虑扩展外部存储器的情况);
  ②在编译链接时,即已经完成局部变量的定位;
  ③如果各函数之间没有直接或间接的调用关系,则其局部变量空间便可覆盖。

正是由于以上的原因,在Keil C51环境下,纯粹的函数如果不加处理(如增加一个模拟栈),是无法重人的。那么在Keil C5l环境下,如何使其函数具有可重人性呢?下面分析在实时操作系统下面,任务的基本结构与模式:

vold TaskA(void*ptr){
UINT8 vaL_a;
//其他一些变量定义
do{
//实际的用户任务处理代码
}while(1);
}
void TaskB(void*ptr){
UINT8 vaLb;
//其他一些变量定义
do{
Funcl();
//其他实际的用户任务处理代码
)while(1);
void Funcl(){
UlNT8 v al_fa;
//其他变量的定义
//函数的处理代码
}

在上面的代码中,TaskA与TaskB并不存在直接或间接的调用关系,因而其局部变量val_a与val_b便是可以被互相覆盖的,即其可能都被定位于某一个相同的RAM空间。这样,当TaskA运行一段时间,改变了val_a后,TaskB取得CPU控制权并运行时,便可能会改变val_b。由于其指向相同的RAM空间,导致TaskA重新取得CPU控制权时,val—a的值已经改变,从而导致程序运行不正确,反过来亦然。另一方面,Funcl()与TaskB有直接的调用关系,因而其局部变量val_fa与val_b不会被互相覆盖,但也不能保证其局部变量val_fa不会与TaskA或其他任务的局部变量形成可覆盖关系。

将val_a、val_b以及val_fa等局部变量定义为静态变量(加上static指示符)可以解决这一问题。但问题是,定义大量的static类型变量,将导致RAM空间的大量占用,有可能直接导致RAM空间不够用。尤其是在一些小容量的单片机内,一般只有128或256字节,大量的静态变量定义,在如此小的RAM资源状况下显然就不太合适了。由此而有了另一种的解决方法,如下代码所示:

void TaskC(void){
UINT8 x,v;
whlk(1){
OS_ENTER_CRITICAL();
x=GetX(); (1)
y=GetY(); (2)
//任务的其他代码
OS_EXIT_CRITICAL(); (3)
0SSleep(100); (4)
}
}

以上代码TaskC中使用了临界保护的方法来保护代码不被中断占先,确实有效地解决了RAM空间太小,不宜大量定义静态变量的问题。然而如果每个任务都采用此种结构,任务一开始,就关闭中断,将使实时性得不到保证。事实证明,这种延时是相当可观的。用一个实例来说明,如果想在系统中使用一个动态刷新的LED显示器,就难以保证显示的稳定与连续,哪怕在系统中是使用一个单独的定时器来做这一工作(进入临界区后,EA=0)。其次,这种结构事实上将占先的任务调度转化为非占先的任务调度。实际上如果在(3)与(4)之间没有碰巧发生中断并导致一个任务调度,那就可以理解为是任务主动放弃CPU的控制。如果在(3)和(4)之间碰巧产生了一个中断并导致了一个任务调度,只是执行了一次多余的任务调度而已,而且并不希望在(3)之后发生2次甚至多次的任务调度,相信读者也有这一愿望。

除此之外,还可以发现任务的一个特点:当任务从(1)重新开始时,局部变量x和y是一个什么值并不在乎,即x和y即使在(3)之后改变了,也已经不再重要,不会影响程序的正确性。其实这一特点也是大部分任务,至少是太部分任务的大部分局部变量的一个共性——如果任务在整个执行过程中,不会(被占先)放弃CPU控制权,则其局部变量大多数并不需要进行特别的保护,即其作用域只是任务的当次执行,针对上面的代码,就是临界保护区内的代码区域。

2 实时操作系统要不要占先

由上面的分析,如果要保持一个函数可重人,就得使用静态变量,系统的RAM资源将是一个严峻的考验;如果使用临界区来保护运行环境,系统的实时性又得不到保证,而且有将占先式任务调度转为非占先任务调度之虞。显然,使用静态变量简单,但有更多的不适用性,对将来功能的调整也是一个阻碍,一般不被采用。那么,就只能从环境保护上来下功夫了,但是果真只能以进入临界区牺牲系统的实时性来保证任务不被占先?下面看看临界保护这一方法的基本思路:

  ①在一个任务中,如果局部变量在其作用域内不被占先切换,则这些变量在任务被剥夺了CPU控制权后,不关心其值也不会影响任务的正确执行;
  ②使用临界区保护,可以达到上面所提到的要求;
  ③由此导致的实时性能与占先切换的减弱可以接受。由此可知,不被占先是任务保护局部变量的关键。既然如此,何不舍弃占先式的任务调度?这不失为一个好的出发点。针对Keil C51,非占先式任务调度,可能是一种更好的方法,更能协调51系列单片机的既定资源。下面编写这样一个系统:
  
  ①使用非占先式任务调度;
  ②可以在小容量的芯片中使用,开发目标是,即使是8051这样小的芯片,也可使用这个实时操作系统;
  ③支持优先级调度,尽可能保证其实时性。

3 实时操作系统的实现

  基于以上的分析与目的,近日完成了这个操作系统。在堆栈上借用RTx的管理方法,即当前任务使用全部的堆空间,如图1所示。

3.1 堆栈的初始化与任务的创建

  堆栈的初始化实际是初始化0STaskStackBotton数组,并将当前任务指定为空闲任务,下一个运行任务指定为最高优先级任务,即优先级为零的任务。初始化时,将SP的值存人OSTaslkStackBotton[O],SP+2的值存入OSTaskStacKBotton[1],依此类推。而任务是调用0STa-skCreate函数建立的。实际上只是将任务(假设为n号任务)的地址填人到对应OSTaskStackBotton[n]所指向的位置,并将SP向后移动2个字节,如图2所示。


为什么要以这样一种规律而不是其他的方式呢?这是由于在任务建立后,还未进行任务调度之前,各任务的堆栈实际上是它们自身的地址,因而其堆栈深度为2,为了程序的简便而直接填入。

void main(void){
OSInit(); /*初始化OSTaskStackBcBotton队列*/
TMOD=(TMOD&0XFO)│ 0XOl;
TL0=0xBF;
TH0=0xFC;
TRO=1;
ETO=1;
TFO=O:
OSTaskCreate(TaskA,NULL,0);
OSTaskCreate(TaskB.NULL,1);
OSTaskCreate(TaskC,NULL,2);
OSStart();

上面这段代码中,所有任务建立后,便调用OSStart()开始任务调度。OSStart()是一个宏定义,如下所示:

#deflne OSStart() d0{\
OSTaskCreate(TaskIdle,NULL,OS_MAX_TASKS);\
EA=l:\
return;\
}while(O)

首先,它创建了一个空闲任务并打开中断,然后便返回。返回到哪里了呢?我们知道,空闲任务是优先级最低的任务,当调OSTaskCreate建立时,会将其地址填人到SP的位置,并把SP向后移动2个字节(见图2及说明),因而此时处在堆栈顶端的,一定是空闲任务Taslddle。这就使得这里的return一定会返回到空闲任务。至此,系统进入正常运行状态。

3.2 任务的切换


任务的切换分两种情况,在当前任务优先级低于下一个取得CPU控制权的任务时,将下一个取得CPU控制权的任务的栈顶到当前任务的栈顶之间的内容向RAM空间的高端搬移,以空出全部的RAM空间作下一个任务的堆空间,同时更新对应的OSTaskStackBotton,使其指向新的正确任务的堆栈栈底。如果当前任务的优先级高于下一个任务的优先级,则作相反的搬移,如图3与图4所示。

所有任务必须主动调用OSSleep,放弃CPU的控制权。任务调用OSSleep后,将选择优先级最高的就绪任务运行。

结 语

系统完成后,内核的代码量在400多个字节左右,占用1个定时器中断及小量的内存空间。系统设置容量为8个任务,用户实际可用任务为7个,能够满足一般需求,也达到了在小容量芯片中应用的开发要求。由于没有采用占先式的任务调度,除开全程相关的个别任务的一些局部变量外,其他局部变量已经不存在覆盖关系,由于是任务主动放弃CPU控制权,对于个别需要保护的变量单独进行处理也变得容易。在系统中,全程不需要反复地开关中断,实时性能也很好。对个别时序要求严格的外设(如DSl8820)除外。

关键字:容量  嵌入式  重入 引用地址:构造一个51单片机的实时操作系统

上一篇:Cygnal在片系统单片机的特点与应用
下一篇:EM78P447S单片机及其在直流电机红外遥控系统中的应用

推荐阅读最新更新时间:2024-03-16 12:18

嵌入式系统的无线互联技术”主题讨论会圆满结束
嵌入式系统联谊会“嵌入式系统的无线互联技术”主题讨论会,于2012年4月22日在北京航空航天大学新主楼会议中心顺利举行。 本次会议邀请了业内学者、教师、科研人员和企业代表,就嵌入式系统无线互联技术的现状和未来应用发展前景、相关的新技术新产品,以及设计和应用的经验,进行了热烈的交流讨论。嵌入式系统联谊会自09年开始至今已经召开了10次主题讨论会,议题涉及嵌入式系统和IT 领域多个方面,在业界产生了深远的影响。 在互联网、云计算和物联网快速发展的背景下,支持嵌入式设备近距离直接通信的无线互联技术,正处于一个迅速发展时期。这些无线互联技术包括ZigBee、WiFi、蓝牙、RFID和NFC等,每一项技术具有各自不同的特点,没有一种技术
[嵌入式]
中兴新支点嵌入式操作系统出货2亿套
在OS系统领域,国产厂商终于有所突破——中兴高管吕钱浩表示中兴新支点嵌入式操作系统出货量已经超过两亿套。 据他所说,新支点嵌入式操作系统出货量每年的发货量在两千万套左右,目前已经在350公里时速的复兴号高铁上规模商用了。 据介绍,新支点是一款多场景、分布式、多协同、高效能、高可靠的嵌入式操作系统,符合欧标CGL5.0标准认证、荣获中国工业大奖、申请国内外上百项发明专利。 中兴表示,其支持嵌入式底层虚拟化、支持容器技术。提供高实时性、高稳定性、高安全性、高易用等特性,支持多核、多架构、多驱动。提供高度定制的技术服务,包括系统性能优化,驱动定制开发,驱动调优等。 目前广泛应用于通信行业、智能电力行业、智能汽车电子行业、
[嵌入式]
中兴新支点<font color='red'>嵌入式</font>操作系统出货2亿套
科大讯飞的嵌入式语音识别软件
语音激活的消费类和IoT电子设备的紧密集成解决方案 CEVA,全球领先的智能和互连设备的信号处理IP授权许可厂商 (纳斯达克股票交易所代码:CEVA)宣布,科大讯飞的语音识别软件套装已经可以提供为CEVA的音频/语音DSP优化的版本。这种紧密集成的解决方案已经可提供给客户,并已嵌入到为消费类电子产品设计的量产超低功耗语音处理器。 由于语音处理和人工智能的进步,语音识别正快速成为消费类电子、智能家居、移动和可穿戴设备、监控、汽车和IoT设备的人机界面(HMI)的理想选择。科大讯飞是中国顶尖的语音识别解决方案提供商,也是基于语音的人工智能技术的全球领先者。科大讯飞和CEVA开展合作,为CEVA的先进音频/语音DSP优化科大讯飞
[嵌入式]
适用于嵌入式摄像机模块的三通道电源管理单元
      日前,德州仪器 (TI) 宣布推出外形小巧的电源管理单元 TPS657051,其可支持便携式消费类电子产品以及空间狭小的应用领域,如网络摄像机或低热量/低噪声嵌入式摄像机模块等。该器件采用 2 毫米 x 2 毫米 WCSP 封装,具有 2 个 400 mA 降压转换器、1 个 200 mA 低压降线性稳压器 (LDO) 以及其它支持功能。 主要特性与优势 • 2 个 400 mA 降压转换器; • 效率高达 92%; • DC/DC 转换器的输入电压范围为 3.3 V 至 6 V; • 2.25 MHz 固定频率; • 自动 PFM/PWM 操作; • 轻负载电流下的节电模式; • PWM 模式下的输出电
[电源管理]
适用于<font color='red'>嵌入式</font>摄像机模块的三通道电源管理单元
Cache在嵌入式处理器中的使用问题
随着嵌入式计算机应用的发展,嵌入式CPU的主频不断提高,这就造成了慢速系统存储器不能匹配高速CPU处理能力的情况。为了解决这个问题,许多高性能的嵌入式处理器内部集成了高速缓存Cache。其中,三星公司的S3C44B0X内部就集成了8 KB空间统一的指令和数据Cache。   Cache即高速缓冲存储器,是位于CPU与主存之间一种容量较小,但速度很高的存储器。由于CPU在进行运算时,所需的指令和数据都是从主存中提取的,而CPU运算速度要比主存读写速度快得多,这样极其影响整个系统的性能。采用Cache技术,即在Cache中存放CPU常用的指令和数据,然后将这些数据和指令以一定的算法和策略从主存中调入,使CPU可以不必等待主存数据而保持
[应用]
基于Geode TMGX1的嵌入式系统设计
摘要:介绍国家半导体公司(NS)的Geode TMGX1处理器及协同芯片,说明如何利用该芯片组进行嵌入式系统设计,并讨论一些设计难点的处理。 关键词:信号完整性 信息家电 阻抗匹配 引言 近些年,嵌入式技术迅速发展, 嵌入式应用深入金融、航空航天、电信、网络、工业控制等各个领域,并进一步渗透到日常生活领域——信息家电。信息家电市场的日益发展需要高效、灵活的嵌入式解决方案。 美国国家半导体公司(NS)的Geode TMGX1处理器是一款专门针对信息家电市场的集成处理器,具有低功耗、高性能、低价格及X86体系的兼容性与可扩展能力。GX1与其协同芯片为瘦客户机、交互式机顶盒以及个人Internet接入等信息家电应用提供了灵活
[嵌入式]
基于嵌入式PC与GPRS的SCADA在油田中的应用
   1 引言   随着电子计算机及网络通信技术的迅猛发展,许多生产过程中的数据采集和监控系统功能也在不断增强。本文针对的某油田采油区较为分散的实际情况,探索应用相应的测控系统。由于存在着单井作业或数台甚至十台以上抽油机排列在一起,形成一个或数个井排,同时在其周围相距几百米分布着一些中转原油的储油罐和其他设备,为了提高采油效率,保障安全生产,需要采集各个抽油机、油罐、电机和油泵等的实时数据,如温度、压力、流量、油罐的液位和储油量、电压、电流等。为了使采油厂的生产管理调度部门及时掌握一线生产情况,必须将数据及时上传。但工作现场环境十分恶劣,无法昼夜值守,又无通讯线路,因此,给生产管理带来极大不便。   针对上述问题,本文讨论
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

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

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