你的位置:首页 > 操作系统

[操作系统]QP之QF原理


1.QP简介:

量子平台(Quantum Platform, 简称QP)是一个用于实时嵌入式系统的软件框架,QP是轻量级的、开源的、基于层次式状态机的、事件驱动的平台。

QP包括事件处理器(QEP)、轻量级的事件驱动框架(QF)、任务调度微内核(QK)和实时跟踪调试器(QS)四个部分。

利用QP可以开发出结构清晰的嵌入式应用程序(使用C或C++语言)。
QP
图1.QP总体结构

2.QP之QF简介

QF是QP的核心,可以把QF理解为软件总线(software bus,SBus)。在这个软件总线上连接着很多的AO和硬件中断服务程序ISR,QF负责事件的存贮、分发和回收等功能,也就是事件驱动。

QF是一个事件驱动框架。应用程序可以创建事件实例,放到事件池中,并分发事件到相应注册了这个事件的活动对象(状态机,任务)AO中。应用程序可以注册特定的事件,当有事件发生时,QF就会分发事件到AO中。应用程序是由多个AO组成,每个AO可以认为是一个任务。把硬件中断程序也当做AO看待,只是优先级比较高。

QF量子框架由五个数据结构及操作组成,其数据结构采用了uCOS-II相似的结构。

9f2f070828381f30e47cb316ab014c086e06f023
图2.细化的QF总体结构

3.QF分发事件

如图 1所示,QF是个软件总线,在这个软件总线上连接着AO和ISR。QF中包含5个主要的数据结构(受uCOS II影响很深,要看一下uCOS II内核)。

有两种事件的分发方式:

(1)直接分发事件

一个AO直接分发事件到另一个AO,就是直接投递事件。这种方式分发事件的AO要知道目标AO。

使用void QActive_postFIFO(QActive *me, QEvent const *e) 函数分发事件。

(2)P/S分发事件

利用QF中的AO订阅事件表,以P/S(Publish-Subscribe出版-订阅)方式分发事件,也就是P/S投递事件。 这种方式分发事件AO不用知道目标AO,QF查找AO订阅事件表就知道把事件分发到什么地方。P/S投递方式减少了AO之间的耦合度。

使用void QF_publish(QEvent const *e)函数分发事件。

1ff9d13f2e1bc7db7c1e717e
图3.QF软件总线和两种投递事件方式

框架QF包括活动对象AO,每个AO包含一个AO队列(QEQueue)和状态机。QF中还有5个主要的数据结构表,其中有3个AO相关的数据结构:AO订阅事件表,AO队列状态表,AO注册表;有1个事件池QMPool,用于保存事件实例,其它事件都是对这个事件实例的引用;有1个时间事件链表QtimeEvt,用于定时事件处理。图 2是相应数据表与QF和AO的关系。

c7851ed5042bb4dd51da4bb4
图4.QF框架及五个数据表

4.QF运行

QF运行时,包括的过程有:
(1)QF初始化;
(2)AO和ISR产生事件;
(3)分发事件到AO队列;
(4)循环调度分派事件到状态机。
在把事件放到AO队列中时,会置位AO队列状态表相应位;从AO队列中取出事件时,会清零AO队列状态表相应位。总之,放事件到AO队列或从AO队列取事件,都会修改AO队列状态表。

14b554da063bb7c2b7fd481f
图5.QF运行过程及数据表关系

(1)QF初始化
在QF运行之前,首先要进行初始化,要创建AO、创建事件池、创建AO订阅事件表,创建AO队列等一系统开始工作。

717f7eec7ddfa5c82f2e21a7
图6.QF初始化

(2)AO和ISR产生事件
在AO或ISR中,用Q_NEW()宏可以创建用户事件实例,并放到事件池中。
如用 UserEvt *pe = Q_NEW(UserEvt , UserSig1)
创建了一个用户事件pe。可以分发这个用户事件pe到AO队列中。

其中,UserEvt是增加了参数的用户自定义事件,它是继承自QEvent,UserEvt定义如下,

typedef struct UserEvtTag {         QEvent         super; /* 继承自QEvent */         uint8_t parameter;/*增加的事件参数 */} UserEvt;

UserSig1是用户定义的信号,用枚举来定义,定义如下,

enum UserSignals {    User1_SIG = Q_USER_SIG,/* 用户定义第一个信号 */    User2_SIG, /* 第二个信号 */    User3_SIG,  /* 第三个信号 */      ...      /* 其它信号 */};

(3)分发事件到AO队列

可以用QActive_postFIFO(TargetAO, (QEvent *)pe)直接分发事件或用QF_publish((QEvent *)pe)间接分发事件到目标AO队列中。使用直接分发事件方式时,不需要AO订阅事件表QF_subscrList的参与,而间接分发事件时要用到AO订阅事件表。

这两种分发事件都会修改AO队列状态表QF_readySet_(QK中,用QK_readySet),置位相应位,而在Vanilla调度或QK调度会清除AO队列状态表相应位。

(4)循环调度分派事件到状态机
- 有两种调度方式,一种是超级循环调度Vanilla方式,这种方式的任务是非抢占式的;
- 另一种方式是QK调度方式,QK是一个微调度内核,这种方式任务是抢占式的。

两种调度方式的流程:

a212f3249e5a832a8744f9a2
图7.Vanilla调度流程

b2ba0f46e547d7106b63e587
图8.QK调度流程

5.总结

QF是一个框架,用于事件的产生、保存、分发事件。有两种事件分发方式,并支持两种对任务的调度方式;可以理解QF为一个软件总线,其上安装了很多的AO和ISR。最多可以支持63个AO+ISR。