嵌入式开发事件驱动模型--AO事件调度器

1. 背景

在之前的一篇博客中曾经提出一种嵌入式开发的事件调度器1,事件调度器的初衷是为了沟通mcu中断和主任务之间的事件传递,并且将引入周期性事件,替代原来mian函数中while的所有功能。后来我们项目的SE沟通之后,他认为这对于我们裸机项目开发非常重要,希望我可以推进在这一方面的研究。在之后一段时间,也是留意事件调度器的相关内容,后来在阅读敏捷软件开发时,接触到ActiveObject模式,在书中介绍,Active Object模式常常与Command模式搭配使用,或辅以状态机,来实现一些复杂的一些操作。除此之外也了解到QuantumLeap的QPC项目,QPC其实也是一种事件调度器,并使用更为抽象的分层状态机,我也是花了一些时间来学习理解QPC项目的理念和机制。在此基础之上我也提出比当初更为完善和理论更进一步的事件调度器。

2. 嵌入式开发理念–事件驱动模型

在linux操作系统内核中,曾提到用户程序想要与内核进行交互,需要使用系统调用来进入内核态,从而实现系统的需求,那所谓的系统调用其实就是中断,包括硬件的交互,比如,在键盘上按下一个按键,那么外设会触发一个中断,从而调用系统的驱动程序,那么linux系统就是正常会在用户态运行,靠中断事件来进入内核态,处理相应的请求,所以linux系统也是靠中断事件调度。在mcu嵌入式领域也是这样的模式,也靠中断事件来驱动各种请求。linux系统处理用户请求有系统调用,处理外设中断有各种对应的驱动模块,但是在嵌入式领域,尤其是裸机开发领域,并没有一个相对完善的机制来处理,往往靠各自的开发人员来处理相应这样的问题,这也使得各自的实现方式良莠不齐。

我在B站曾看到一种称为伪操作系统的实现方式,其实就是设置了一个事件数组,然后遍历执行所有的事件,这种处理方式,其实离操作系统差之甚远,其实就是一个while的死循环,没有事件退出机制,没有事件调度,各个事件都是平等的,这样的事件处理方式太过原始,不能满足事件差异化要求。在我们裸机项目中也有一个事件处理机制,称为软件计时器,原理也是类似,也是有一个事件数组,大概是60个,通过注册事件,向事件处理器,注册定时事件,当然注册时需要指定一个周期时间,由于也是普通数组,静态存储,使得事件处理方式只是遍历所有事件而已,虽然也给了事件一个优先级,但是在遍历所有事件的情况下,优先级的作用就失去了。

3. 事件驱模型动机制

在裸机开发中,通过对mcu中断资源和主任务进行配置,划分出前后台,各种外设中断为前台,负责接待各种到来的事件,如果事件较为简单,用时较短,就不用发往后台,在前台就地解决,如果事件较为复杂,用时较长,而中断不宜停留过长,就需要把事件发放后台。事件调度器同样可以应用于有操作系统的项目,那么后台就是各个线程和紧急事件中断(最低优先级)。前后台机制如下图。
在这里插入图片描述

4. 事件调度器设计架构

在这里插入图片描述

5. 事件是事件处理器

事件和线程的在处理事件上的区别是事件要运行到结束(RTC,Run To Complete),而线程可以不结束时,进行线程调度,处理其他事情。事件可分为周期事件和单次事件,在主任务事件处理器中,单次事件还进行了优先级划分,分为高有限事件和普通事件,实现一个简单的调度机制,在单次轮询中,将执行所有的高优先级事件,普通事件最多处理3个。周期事件中内置一个计数器,每次沦陷都会判断事件是否到事件,到事件才会处理对于的事件。

在裸机开发中,程序后台一般组成为主任务和最低优先级的中断,这里的中断是软件触发的中断,之前的一篇文章中有详细提及软件中断2,也就是所有两个地方可以处理事件,我们可以在这两个地方都设置一个事件处理器,而中断的处理器是可以打断主任务的事件处理器,其实相当于,在裸机程序中,实现了多线程操作。中断中的事件处理器,可以作为紧急事件的处理器,而普通事件可交由主任务的事件处理器。

6. Active Object 模式和状态机

此次事件调度器引入Active Object模式,以及状态机,可以将单次事件进行挂起,重新加入到事件队列中,也就是说,单次事件可以选择在指定条件下,再次执行,等到结束条件满足时,在结束本次事件。而周期事件也可以进行暂停或者Kill,在合适的情况下将暂停的周期事件重新唤醒。单次事件和周期性事件由于引入了状态机,可以进行各种状态之间的轮转处理。

7. 事件发布的全局资源问题

由于事件的发布往往是在中断中,而事件队列作为全局资源,有被主任务和中断同时修改的问题,在之前一篇文章中有提到中断中修改数据的问题3,在这种情况无法避免,所以裸机开发中需要在临界区中发布和注销事件,而在嵌入式操作系统和中需看情况,若发布方和执行方都是线程,那么使用互斥锁就可以实现,若有一方为中断,则需要进入临界区,若是在通用操作系统中,只需要使用互斥锁就足够了。

8. QPC项目

QPC项目发展多年,机制已相当完善,尤其是使用的分层状态机,使得状态处理的抽象性进一步提升。本文的事件调度器仅仅使用了传统的有限状态机,也是由于本文的事件处理的事件的场景较为有限。本文中的事件调度器仅仅相当于QPC中的QV和QK内核,而QXK内核实现了一种非操作系统的基于事件的多线程方案。但是QPC作为开源项目,开源协议为GPL3,开源协议具有传染性,而我们的项目是闭源项目,所以就为直接使用QPC,当然也有吸收QPC的一些优秀理念。

更多关于QPC的内容可以查询官网手册4

9.总结

本文中的事件调度器,使得嵌入式开发在处理业务事件更加游刃有余。除此之外,使得有操作系统项目和裸机项目的差异性大幅缩小,事件的发布方,紧紧需要想对映的事件队列注册事件,而不用管执行单位是主任务还是线程,或是中断。这也使得裸机项目和有操作系统的项目的差异大幅缩小,甚至可以将有操作系统项目和裸机项目统一,无感切换。


  1. 嵌入式程序普通事件调度-CSDN博客 ↩︎

  2. ARM Cortex-M内核软件中断触发方式-CSDN博客 ↩︎

  3. 嵌入式全局数据中断访问问题-CSDN博客 ↩︎

  4. QP/C: Overview (state-machine.com) ↩︎

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值