[原创] [MsgOS]多平台下按键任务框架

科技猎人   2016-6-26 17:30 楼主
在其他论坛上的一次问答,现摘录为贴。
/***************************************************************************/
问:
我们目前已知道:
1) 如何创建一个任务(暂且叫他任务吧, 它的形式上只是一个被消息触发来调用的函数):
如 msg_send(hello_world,0,NULL,1000,0,MSG_OPT_REPEAT);  // hello_world函数 被1秒周期触发调用

-------------------------------------------------------------------------------------------------------------------------------------------
再深入一点儿(PS: 这段时间我还没仔细认真的去看源码)

这样说吧:  来举一个非常简单的例子
假设有两个任务: A.按键任务, B.打印输出(显示)任务
当按键K1按下时, 通过消息触发, 让打印输出 " K1 press!"
当按键K2按下时, 通过消息触发, 让打印输出 " K2 press!"

如何通这个系统架构来实现, 基于消息来触发, 即打印任务没有被消息触发时,处于等待状态的;
当消息来了, 立即输出相应信息。

即: 1) 如何等待消息, 2) 如何发出消息。


/***************************************************************************/
答:
这个问题好!

设有以下几个函数已知
int key_read(void);//单纯的读取键按键值,包括了消抖等处理
void  printout(char *str);//显示函数,可能是串口打印也可能是屏幕显示,总之是显示一个字串
void init(void);//相关的所有初始化


如果是前后台框架会这么写


void main(void)
{
        int key;

        init();

        while(1)//系统主循环
        {
                key=key_read();
                if(key==K1)
                {
                        printout("K1 press!");
                        
                }
                else if(key==K2)
                {
                        printout("K2 press!");
                }

                ....
        }
}

原理很简单,在死循环中不断检查按键值,按键值有效则直接调用输出函数。如果系统就这么简单用这种方式也还好,但如果再有其他功能,也是类似于这样在这同一个主循环中需要不断检查,一旦其中一个任务在执行时耗时较长都将影响整个系统的实时处理。


其他rtos处理方式

为了提高按键驱动效率,可以在软硬件定时器中对按键进行检查,按键有效时发送一个消息邮箱或消息队列,
专门有一个线程来等待接收这个消息,平时因没有消息而阻塞,


void  key_irq(void)//设按键在定时中断中执行
{
        int key;
        key=key_read();//读取按键值
        if(key)//按键值有效
        {
                msg_send(key);//发送消息,同事携带按键值
        }
}


void task_key(void)//按键消息处理线程
{
     int key;        

        while(1)//每个线程都是个死循环,
        {
                msg_wait(&key);//等待按键消息到来,无消息时线程会被阻塞在这个位置,儿释放CPU
                if(key==K1)
                {
                        printout("K1 press!");
                        
                }
                else if(key==K2)
                {
                        printout("K2 press!");
                }
        }
}

这样做运行效率和实时性都得到了提升

MsgOS处理方式
如果用MsgOS整体思路和其他rots接近,但不用为按键处理单独建立一个线程,编写好按键处理函数等待系统调用即可。

void  key_irq(void)//设按键在定时中断中执行
{
        int key;
        key=key_read();//读取按键值
        if(key)//按键值有效
        {
                msg_send(key_process,key,NULL,0,0,0);//发送消息,同事携带按键值
        }
}


void   key_process(uint32 key,void *ptr)//按键处理消息回调函数,不能是死循环
{
                    if(key==K1)
                {
                        printout("K1 press!");
                        
                }
                else if(key==K2)
                {
                        printout("K2 press!");
                }
}
代码写起来更简单高效,因为不用建立按键处理线程,会节省不少的ram空间,时间耗费及实时性和其他rtos基本一致。

回复评论 (5)

科技猎人,你好
一直觉得写个OS不容易的,
要相像各种应用场景,还要让OS能尽量满足他们,又要保证OS简单清晰高效

要是一个消息,要触发多线程都要用怎么办,
是不是 触发记录一个global_key, 各个线程自己去polling
MicroPython中文社区https://micropython.org.cn/forum/  
点赞  2016-6-26 19:23
引用: 5525 发表于 2016-6-26 19:23
科技猎人,你好
一直觉得写个OS不容易的,
要相像各种应用场景,还要让OS能尽量满足他们,又要保证OS简 ...

小魔女你好
一次消息发送只能发送到一个线程中去执行,也可以在中断中执行。当然你也可以多发送几次发送到不同的线程上执行。不过我还想不到什么情况下需要发送一个消息到多个线程的应用情景。
MsgOS在应用开发上和其他rtos还是也些区别的,默认的只有一个工作线程,用来处理消息队列,这时为协作式系统,不存在任务级抢占,但会比一般前后台结构系统高效方便的多。如果额外创建其他线程,默认的新线程也是用来处理消息队列,即为系统新加了高优先级的消息执行空间,使得消息执行具有抢占特性。
点赞  2016-6-26 22:00
这个项目里面经常有,一个消息变化后,多个进程要做相应的处理,
汽车里面用的跟多了。

我理解OS和网络,软件和硬件都有相通的 基本哲学理论
一对一,一对多,多对一,多对多
如果把这个做到OS里面,很多应用就可以直接上,不知道你有没有研究过autosar
MicroPython中文社区https://micropython.org.cn/forum/  
点赞  2016-6-26 22:07
引用: 5525 发表于 2016-6-26 22:07
这个项目里面经常有,一个消息变化后,多个进程要做相应的处理,
汽车里面用的跟多了。

我理解OS和网 ...

这个确实不了解,不过同一效果总是能用不同方式实现的。MsgOS的思路就是线程最好是因为没有消息需要执行而挂起,而不是因为获取不到某些资源或同步信号而阻塞。
点赞  2016-6-26 22:51
汇总帖在此:
[MsgOS]——by 科技猎人
https://bbs.eeworld.com.cn/forum. ... 3237&fromuid=536508
玩板看这里: https://bbs.eeworld.com.cn/elecplay.html EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!
点赞  2016-6-27 09:00
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复