您的位置 首页 FPGA

51单片机多任务操作系统的原理与完成

前言想了很久,要不要写这篇文章?最后觉得对操作系统感兴趣的人还是很多,写吧.我不一定能造出玉,但我可以抛出砖.包括我在内的很多人都对51使用操作系统呈悲观态度,因为51的片上资源太少.但对

  前语

  想了好久,要不要写这篇文章?最终觉得对操作体系感兴趣的人仍是许多,写吧.我纷歧定能造出玉,但我能够抛出砖.

  包含我在内的许多人都对51运用操作体系呈失望情绪,由于51的片上资源太少.但关于许多要求不高的体系来说,运用操作体系能够使代码变得更直观,易于保护,所以在51上仍有操作体系的生计时机.

  盛行的uCos,Tiny51等,其实都不合适在2051这样的片子上用,占资源较多,唯有自已着手,以不变应万变,才能让51也有操作体系可用.这篇贴子的意图,是教会咱们怎么现场写一个OS,而不是给咱们供给一个OS版别.供给的一切代码,也都是示例代码,所以不要由于它没什么功用就说LAJI之类的话.假如把功用写全了,一来估量你也不想看了,二来也失掉灵活性没有价值了.

  下面的贴一个示例出来,能够清楚的看到,OS自身只需不到10行源代码,编译后的方针代码60字节,使命切换耗费为20个机器周期.相比之下,KEIL内嵌的TINY51方针代码为800字节,切换耗费100~700周期.仅有不足之处是,每个使命要占用掉十几字节的仓库,所以使命数不能太多,用在128B内存的51里有点难度,但关于52来说问题不大.这套代码在36M主频的STC12C4052上实测,切换使命仅需2uS.

  #include

  #define MAX_TASKS 2 //使命槽个数.有必要和实践使命数一至

  #define MAX_TASK_DEP 12 //最大栈深.最低不得少于2个,保存值为12.

  unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP]; //使命仓库.

  unsigned char task_id; //其时活动使命号

  //使命切换函数(使命调度器)

  void task_switch(){

  task_sp[task_id] = SP;

  if(++task_id == MAX_TASKS)

  task_id = 0;

  SP = task_sp[task_id];

  }

  //使命装入函数.将指定的函数(参数1)装入指定(参数2)的使命槽中.假如该槽华夏来就有使命,则原使命丢掉,但体系自身不会产生过错.

  void task_load(unsigned int fn, unsigned char tid)

  {

  task_sp[tid] = task_stack[tid] + 1;

  task_stack[tid][0] = (unsigned int)fn & 0xff;

  task_stack[tid][1] = (unsigned int)fn >> 8;

  }

  //从指定的使命开端运转使命调度.调用该宏后,将永不回来.

  #define os_start(tid) {task_id = tid,SP = task_sp[tid];return;}

  /*======================以下为测验代码======================*/

  void task1()

  {

  static unsigned char i;

  while(1){

  i++;

  task_switch(); //编译后在这儿打上断点

  }

  }

  void task2()

  {

  static unsigned char j;

  while(1){

  j+=2;

  task_switch(); //编译后在这儿打上断点

  }

  }

  void main()

  {

  //这儿装载了两个使命,因此在界说MAX_TASKS时也有必要界说为2

  task_load(task1, 0); //将task1函数装入0号槽

  task_load(task2, 1); //将task2函数装入1号槽

  os_start(0);

  }

  这样一个简略的多使命体系尽管不能称得上真实的操作体系,但只需你了解了它的原理,就能轻易地将它扩展得十分强壮,想知道要怎么做吗?

  一.什么是操作体系?

  人脑比较容易承受"类比"这种表达方式,我就用"公交体系"来类比"操作体系"吧.

  当咱们要处理一个问题的时分,是用某种处理手法去完结它,这便是咱们常说的"方法",计算机里叫"程序"(有时分也能够叫它"算法").

  以出行为例,当咱们要从A地走到B地的时分,能够走着去,也能够飞着去,能够走直线,也能够绕弯路,只需能从A地到B地,都叫作方法.这种从A地到B的需求,相当于计算机里的"使命",而完成从A地到B地的方法,叫作"使命处理流程"

  很显然,这些走法中,并不是每种都合理,有些傻子都会选用的,有些是傻子都不采会用的.用计算机的话来说便是,有的使命处理流程好,有的使命处理流程好,有的处理流程差.

  能够概括出这么几种真实算得上方法的方法:

  有些走法比较快速,合适于赶时刻的人;有些走法比较省劲,合适于懒人;有些走法比较廉价,合适于贫民.

  用计算机的话说便是,有些省CPU,有些流程简略,有些对体系资源要求低.

  现在咱们能够看到一个问题:

  假如全世界一切的资源给你一个人用(单使命独占悉数资源),那最合适你需求的方法便是好方法.但事实上要外出的人许多,例如10个人(10个使命),却只需1辆车(1套资源),这叫作"资源争用".

  假如每个人都要运用最合适他需求的方法,那司机就只好给他们一人跑一趟了,而在任一时刻里,车上只需一个乘客.这叫作"次序履行",咱们能够看到这种方法对体系资源的糟蹋是严峻的.

  假如咱们没有法力将1台车变成10台车来送这10个人,就只好拟定一些机制和约好,让1台车看起来像10台车,来处理这个问题的方法想必咱们都知道,那便是拟定公交线路.

  最简略的方法是将一切旅客需要走的起点与结尾串成一条线,车在这条线上开,乘客则自已决议上下车.这便是最简略的公交线路.它很差劲,但最少处理客人们对车争用.对应到计算机里,便是把一切使命的代码混在一同履行.

  这样做既不优异雅,也没功率,所以司机想了个方法,把这些客户叫到一同商议,将一切客人出行的起点与结尾罗列出来,计算这些线路的运用频度,然后拟定出公交线路:有些道路能够兼并起来成为一条线路,而那些不能兼并的道路,则另行拓荒行车车次,这叫作"使命界说".其他,关于人多道路,车次排多点,时刻上也优先组织,这叫作"使命优先级".

  通过这样的组织后,尽管仍只需一辆车,但运载才能却大多了.这套车次/道路的按排,便是一套"公交体系".哈,知道什么叫操作体系了吧?它也便是这么样的一种约好.

  操作体系:

  咱们先回过头概括一下:

  轿车 体系资源.首要指的是CPU,当然还有其它,比方内存,定时器,中止源等.

  客户出行 使命

  正在走的道路 进程

  一个一个的运送旅客 次序履行

  一起运送一切旅客 多使命并行

  按不同的运用频度拟定道路并优先跑较繁忙的道路 使命优先级

  计算机内有各种资源,单从硬件上说,就有CPU,内存,定时器,中止源,I/O端口等.并且还会派生出来许多软件资源,例如音讯池.

  操作体系的存在,便是为了让这些资源能被合理地分配.

  最终咱们来总结一下,所谓操作体系,以咱们现在权宜的了解便是:为"处理计算机资源争用而拟定出的一种约好".

  二.51上的操作体系

  关于一个操作体系来说,最重要的莫过于并行多使命.在这儿要弄清一下,不要拿当年的DOS来说事,年代不同了.何况当年IBM和小比尔着急将PC搬上市,所以才抄袭PLM(好象是叫这个名吧?记不太清)搞了个今日看来很"偷工减料"的DOS出来.看看其时真实的操作体系—UNIX,它还在纸上时就已经是多使命的了.

  关于咱们PC来说,要完成多使命并不是什么问题,但换到MCU却很头痛:

  1.体系资源少

  在PC上,CPU主频以G为单位,内存以GB为单位,而MCU的主频一般只需十几M,内存则是Byts.在这么少的资源上一起运转多个使命,就意味着操作体系有必要尽可能的少占用硬件资源.

  2.使命实时性要求高

  PC并不需要太关怀实时性,由于PC上简直一切的实时使命都被专门的硬件所接纳,例如一切的声卡网卡显现上都内置有DSP以及许多的缓存.CPU只需坐在那里指手划脚告知这些板卡怎么敷衍实时信息就行了.

  而MCU不同,实时信息是靠CPU来处理的,缓存也十分有限,乃至没有缓存.一旦信息抵达,CPU有必要在极短的时刻内呼应,不然信息就会丢掉.

  就拿串口通讯来举例,在规范的PC架构里,巨大的内存答应将信息保存满足长的时刻.而关于MCU来说内存有限,例如51仅有128字节内存,还要扣除去寄存器组占用掉的8~32个字节,所以一般都仅用几个字节来缓冲.当然,你能够将数据的接纳与处理的进程兼并,但关于一个操作体系来说,不引荐这么做.

  假定以115200bps通讯速率向MCU传数据,则每个字节的传送时刻约为9uS,假定缓存为8字节,则串口处理使命有必要在70uS内呼应.

  这两个问题都指向了同一种处理思路:操作体系有必要轻量轻量再轻量,最好是不占资源(那当然是做梦啦).

  可用于MCU的操作体系许多,但合适51(这儿的51专指无扩展内存的51)简直没有.前阵子见过一个"圈圈操作体系",那是我所见过的操作体系里最轻量的,但仍有改善的地步.

  许多人以为,51底子不合适运用操作体系.其实我对这种说法并不彻底承受,不然也没有这篇文章了.

  我的观点是,51不合适选用"通用操作体系".所谓通用操作体系便是,不论你是什么样的使用需求,也不论你用什么芯片,只需你是51,通通用同一个操作体系.

  这种主意关于PC来说没问题,关于嵌入式来说也不错,对AVR来说还将就,而关于51这种"赤贫型"的MCU来说,不可.

  怎样行?因地制宜,现场依据需求构建一个操作体系出来!

  看到这儿,估量许多人要翻白眼了,大体上两种:

  1.操作体系那么杂乱,说造就造,当自已是神了?

  2.操作体系那么杂乱,现场造一个会不会出BUG?

  哈哈,看清楚了?问题出在"杂乱"上面,假如操作体系不杂乱,问题不就处理了?

  事实上,许多人对操作体系的了解是片面的,操作体系纷歧定要做得很杂乱很全面,就算仅个多使命并行管理才能,你也能够称它操作体系.

  只需你对多使命并行的原理有所了解,就不难现场写一个出来,而一旦你做到了这一点,为各使命间组织通讯约好,使之开展成一个为你的使用体系量身定做的操作体系也就不难了.

  为了加深对操作体系的了解,能够看一看<<演化>>这份PPT,让你充沛了解一个并行多使命是怎么一步步从次序流程演化过来的.里边还提到了许多人都在用的"状态机",你会发现操作体系跟状态机从原理上其实是多么类似.会用状态机写程序,都能写出操作体系.

  三.我的第一个操作体系

  直接进入主题,先贴一个操作体系的演示出来.咱们能够看到,本来操作体系能够做得么简略.

  当然,这儿要声明一下,这玩意儿其实算不上真实的操作体系,它除了并行多使命并行外底子没有其他功用.但凡事都从简略开端,搞懂了它,就能依据使用需求,将它扩展成一个真实的操作体系.

  好了,代码来了.

  将下面的代码直接放到KEIL里编译,在每个task?()函数的"task_switch();"那里打上断点,就能够看到它们的确是"一起"在履行的.

  #include

  #define MAX_TASKS 2 //使命槽个数.有必要和实践使命数一至

  #define MAX_TASK_DEP 12 //最大栈深.最低不得少于2个,保存值为12.

  unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//使命仓库.

  unsigned char task_id; //其时活动使命号

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/fpga/114985.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部