2065|1

32

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

[MsgOS]高效的延时处理机制 [复制链接]

[MsgOS]发个自己写的cortex-m单片机专用的操作系统
https://bbs.eeworld.com.cn/forum. ... &fromuid=703533
(出处: 电子工程世界-论坛)


[MsgOS]让系统跑起来
https://bbs.eeworld.com.cn/forum. ... &fromuid=703533
(出处: 电子工程世界-论坛)


[MsgOS]shell初体验
https://bbs.eeworld.com.cn/forum. ... &fromuid=703533
(出处: 电子工程世界-论坛)

[MsgOS]hello world!
https://bbs.eeworld.com.cn/forum ... 2701&fromuid=703533
(出处: 电子工程世界-论坛)


因为MsgOS发送消息时具有延时选项,具备其他系统里软硬件timer的功能,也就不再有单独的timer组件了。
当msg_send函数中的time参数不为0时,说明该消息要延时发送,单位为1毫秒,误差为一个单位,由于time为无符号32位数,则可延时的范围为1毫秒到约49天,无论定时精度还是跨度都是很出众的。当opt参数具备MSG_OPT_PERIODIC或MSG_OPT_REPEAT属性时,定时将会是周期性的(二者区别后面再讲),否则为单次定时。
定时检查处理是在系统滴答定时器的中断中进行的,MsgOS系统心跳周期固定为1毫秒,而其他家系统一般是可变的,1毫秒的系统心跳既有足够的分辨精度又不至于占用太多CPU时间,最关键的是所有基于MsgOS的应用代码心跳都是1毫秒非常便于代码阅读和移植。


最初的定时实现方式是每次心跳中断都检查所有消息块,看计时值是否为0,不为0则减减处理,减减后若为0则说明计时时间到,调用相关处理。这种方式原理很简单但时间复杂度为O(n),消息块越多检查耗时越多。
后来又改为了需要延时处理的消息块放在数组前面,每次心跳中断只对前面的延时消息快进行逐个判断。这样时间消耗明显减小,但当时对消息块数组进行排列插入操作的实现较为复杂。
后来系统从Linux源码中借鉴了双向循环链表的处理方法,消息块的插入删除等操作就变得简单高效了。
此后看到了别人的一种软件定时处理方法,基本思路是这样的:
1.添加第一个定时器(TA)时,计时时间就是参数输入值,如TA=100,然后每次心跳中断减减直到为0
2.添加第二个定时器(TB),如果延时时间小于当前第一个的值,如延时为TB=40,此时第一个计时已为TA=80,则将其插入到第一个前面,计时为TB=40,而TA=80-40。如果TB延时时间小于当前第一个的值,如TB=120,TA=80,则将TB排在TA后面,此时TA=80,TB=120-80.
3.再有新定时器添加时类似上面处理,即根据当前延时值从小到大排列进行插入处理,并对队列后面的定时值进行修正。
4.每次心跳中断都只对第一个定时块进行计时减减处理,直到其减到为0定时时间到,删除该块把下一个块作为队列头继续处理。
这样处理的好处是心跳中断时间复杂度为O(1),每次耗时都很短且和延时任务数目无关。但每次在添加定时时需要进行一次队列比较和插入处理,还要修改其他定时块的计时值。


结合上面这一思路,MsgOS目前的计时处理又进化成了这样。
有一个64位的计时值clock从0开始,每次心跳中断加1处理,对于一个64位单位为1毫秒的计时值来讲,要到576584650年后才能溢出,所以我对其溢出后的错误处理采取了不处理的严谨做法
同时对这个64位数据还要按照高32位和低32位来访问,低32位表示此次计时周期中当前系统时间,高32位表示低32位计时溢出次数。
为了方便,构造一个联合体对此数据进行访问,如下所示
  1. union
  2.         {
  3.                 uint64    total;
  4.                 struct
  5.                 {
  6.                         uint32 current;
  7.                         uint32 overflow;
  8.                 }part;   
  9.         }clock;
复制代码
再定义两个定时链表timer[0]和timer[1],用于接收添加的定时消息块。且以计时周期溢出次数的0位值来指示哪个链表是当前延时链表,也就是在每次计时溢出后都会切换一次当前延时链表。
游客,如果您要查看本帖隐藏内容请回复



  1. void  msg_irq(void)
  2. {
  3.         msg_st    *msg;
  4.         link_st   *link;
  5.         link_st   *node;

  6.         scb.mcb.clock.total++;
  7.         link =&scb.mcb.timers[scb.mcb.clock.part.overflow & 0x01];   

  8.         while(!link_isempty(link))
  9.         {
  10.                 node = link->next;      
  11.                 msg =(msg_st  *)node;         
  12.                 if(msg->tick <= scb.mcb.clock.part.current)
  13.                 {            
  14.                         link_remove(node);
  15.                         if(msg->opt & MSG_OPT_IRQ)
  16.                         {
  17.                                 msg->state=MSG_STATE_RUNING;
  18.                                 (msg->msgf)(msg->data,msg->ptr);
  19.                                 if(msg->opt & MSG_OPT_PERIODIC)
  20.                                 {              
  21.                                         msg_enqueue_delay(msg);                                                         
  22.                                 }
  23.                                 else
  24.                                 {
  25.                                         link_insert_before(&scb.mcb.free,node);
  26.                                         msg->state=MSG_STATE_FREE;
  27.                                 }
  28.                         }
  29.                         else
  30.                         {
  31.                                 msg_enqueue_thread(msg);                                                        
  32.                         }
  33.                 }
  34.                 else
  35.                 {
  36.                         break;
  37.                 }                           
  38.         }   
  39. }
复制代码










此帖出自stm32/stm8论坛

最新回复

汇总帖在此: [MsgOS]——by 科技猎人 https://bbs.eeworld.com.cn/forum ... 3237&fromuid=536508  详情 回复 发表于 2016-6-23 15:17
点赞 关注
 

回复
举报

1万

帖子

203

TA的资源

管理员

来自 2楼
 
汇总帖在此:
[MsgOS]——by 科技猎人
https://bbs.eeworld.com.cn/forum ... 3237&fromuid=536508
此帖出自stm32/stm8论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
个人签名玩板看这里:
https://bbs.eeworld.com.cn/elecplay.html
EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表