上帝视角 | QPC代码框架是什么样的?

李肖遥

共 2933字,需浏览 6分钟

 ·

2021-05-10 15:15

关注、星标公众号,直达精彩内容

来源:技术让梦想更伟大

作者:李肖遥


本文介绍一些QP的代码结构以及特点,帮助我们对QP的代码框架有一定了解。

QP/C代码框架

打开QPC代码路径,其目录与文件如下:

  • doxygen

里面包含了一些图片和代码片段。

  • examples

包含了很多例子,可以演示各种QP/C功能。每个示例项目都有具体操作描述,而且都是完整的工作项目,并且带有正确的预配置工具,例如编译器选项,链接器脚本,调试器设置等,同时也提供单元测试支持。

  • include

平台无关的QP/C API接口。

  • ports

继承好了很多平台的端口,可以适应各种操作系统,处理器体系结构和编译器,并且QP/C框架是从头开始设计的,以使移植变得容易。

  • qep/qf/qk/qs

包含了平台一些独立的代码。

  • qpc帮助文件 这个qpc.chm 真的很好,是一个不错的学习的教程。

QP/C框架的分层结构

如下图所示,QP/C框架从上到下包含了活动对象、板级支持软件包BSP、QS软件追踪系统、QEP分层事件处理器、QF活动对象框架、QV协作内核、QK抢占式非阻塞内核、QXK抢占式阻塞内核以及目标硬件。

我们来看看这些QPC框架的组成部分是什么,以及有什么作用,又是怎么协调合作的。

QEP Hierarchical Event Processor

QEP是一种通用的兼容UML的事件处理器,可以在可读性强的ANSI-C中对UML状态机进行编码 ,QEP状态机实施策略的特点是可追溯性,可以使每个状态机元素精确的追溯到代码上。

QEP完全支持分层状态嵌套,这是在许多状态之间重用行为的基本机制,而不是重复相同的动作并一遍又一遍地转换。

对事件驱动系统进行编程的主要挑战是,确定响应给定事件而执行的适当操作。通常,这些动作由两个因素决定:事件的性质和当前的上下文(即,涉及系统的过去事件的顺序)。

QEP的代码包含文件:

QF Active-Object Framework

QF是一个轻量级的,事件驱动的活动对象框架,专门为实时嵌入式(RTE)系统设计。

实时嵌入式框架(RTEF)提供了事件驱动的基础结构,用于基于实时内核(RTOS内核)执行活动对象,以确保确定性的实时性能。而且也比比传统的RTOS小,具体对比如下:

这个框架的主要任务是保证每个活动对象的线程安全,从运行到完成的事件处理。它包含了直接的事件传送,发布-订阅的事件转发,事件队列,时间事件等等。

QF的代码包含文件:

QV Cooperative Kernel

QV是一个简单的协作内核,该内核始终一次处理一个事件,直到完成为止,并在处理每个事件后对活动对象执行基于优先级的调度。

QV内核是隐式合作的,因为活动对象不需要显式产生CPU,而仅在事件处理完成后返回到QV调度程序。由于状态机中事件处理的持续时间很短,因此简单的QV内核通常足以满足许多实时系统的需求,这是执行活动对象的最快、最小和最容易理解的方式。

在任何活动对象的每个RTC步骤之后,将使用QV调度程序来选择要执行的下一个活动对象,QV调度程序始终选择事件队列中优先级最高的活动对象。

然后,QV调度程序从此队列中提取下一个事件,并将其分派到与活动对象关联的状态机上。状态机运行到结束,然后QV调度程序继续运行并且循环重复,如下图所示:

由于状态机总是在每个RTC步骤之后返回到QV调度程序,因此可以使用单个堆栈来处理所有状态机。QV调度程序还可以非常容易地检测到所有事件队列何时为空,此时它可以调用空闲回调,以使应用程序将CPU和外围设备置于低功耗睡眠模式。

鉴于其简单性,可移植性和低资源消耗等优点,我们可以有序执行这些活动对象。该调度程序的线程级响应是整个系统中最长的RTC步骤,但是由于事件驱动的活动对象不会阻塞,因此RTC步骤往往很短(通常只有几微秒)。

此外,通常可以通过将事件发布到自身并返回(“提醒”状态模式)来将较长的RTC步骤分解为更短的部分。然后,自发布事件触发了更长处理的继续。

QV的代码包含文件:

QK Preemptive Non-Blocking Kernel

QK是一种超快的、抢占式的、基于优先级的单栈实时内核,并且始终确保CPU执行最高优先级活动对象,在执行的时候,不像传统的RTOS内核那样无休止的循环,而是将事件作为一键式函数调用来处理。

如果新事件的优先级高于当前处理的事件,QK内核仍然允许这些单次事件处理功能相互抢占,类似于优先级中断控制器允许中断相互抢占。

只有两种情况可以导致准备更高优先级的线程:

  1. 当低优先级线程将事件发布到高优先级线程时,内核必须立即挂起低优先级线程的执行并启动高优先级线程。这种类型的抢占称为同步抢占,因为它与将事件发布到线程的事件队列中同步发生。
  1. 当中断向比被中断线程高优先级的线程发布事件时,内核必须开始执行高优先级的线程,而不是恢复低优先级的线程。这种类型的抢占称为异步抢占,因为它可以异步发生,只要不显式禁用中断即可。

QK的代码包含文件:

QXK Preemptive Blocking Kernel

QXK是一个小的、可抢占的、基于优先级的双模式阻塞内核,它执行诸如QK内核之类的活动对象,但也可以执行传统的阻塞线程,在这方面与常规RTOS(实时操作系统)完全相同。

QXK专为将事件驱动的活动对象与传统的代码混合而设计,可用于硬实时系统,支持基本线程,所有基本线程都嵌套在同一堆栈上,因此减少了堆栈使用量。

基本线程的另一个优点是,从基本线程切换到另一个基本线程只需要激活基本线程,这比QXK还支持的扩展线程所需的完整上下文切换要简单得多,而且速度也更快。

下图显示了QXK内核中引入的主要类以及它们与QP框架类的关系。

QXK的代码包含文件:

QS Software Tracing System

QS是软件追踪系统,使开发人员能够以最少的目标系统资源监视实时事件驱动的QP应用程序,而且无需停止或显着降低代码速度。QS是用于测试,故障排除和优化QP应用的理想工具。QS甚至可以用于支持产品制造验收测试。

QP/Spy软件跟踪系统的结构如下图:

QS的代码包含文件:

总而言之

QPC的目标硬件位于底部,它上方的板级支持软件包(BSP)提供对板级特定功能的访问,而实时内核(QV,QK,QXK或常规的第三方RTOS)为多任务处理提供了基础。

基于这些服务,活动对象框架(QF)提供了事件驱动的基础结构,用于执行活动对象,并且确保线程的事件驱动的安全。

最后,事件处理器(QEP)实现了基于UML状态图的分层状态机,顶层是由松散耦合的活动对象组成的应用程序级代码。

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

推荐阅读:


嵌入式编程专辑
Linux 学习专辑
C/C++编程专辑
Qt进阶学习专辑

关注我的微信公众号,回复“加群”按规则加入技术交流群。


点击“阅读原文”查看更多分享。

浏览 133
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报