The Active Object model of computation can work with a wide range of real-time kernels. Specifically for the kernel discussed in this section, an Active Object requires an execution context only during the RTC (Run-to-Completion) processing and an Active Object that is merely waiting for events does not need an execution context at all. This opens up possibility of executing multiple Active Objects in a single thread (e.g., the main()
function in C or C++).
QV is a simple non-preemptive, cooperative, fixed-priority, event-driven kernel integrated with the QP Framework. As shown in Figure SRS-QV-LOOP, QV executes all Active Objects in the system in a single loop (similar to the traditional "superloop", a.k.a. "main+ISRs" architecture), so Active Objects cannot preempt each other (non-preemptive kernel). The QV priority-based scheduler engages only at the top of the loop and selects the highest-priority Active Object ready to run (with some event(s) in its queue). When such Active Object is found, QV executes the RTC step in this Active Object and then loops back. That way, Active Objects cooperate to share a single "superloop" and implicitly yield to each other after every RTC step. When the QV scheduler finds no Active Objects ready to run, it invokes the idle processing.
As described in the Shared-Nothing Principle for Active Objects, QP Applications should generally strive to avoid any sharing of resources among Active Objects. However, the simplistic and non-preemptive nature of the QV kernel allows applications to relax the "shared-nothing" principle and safely share some resources among Active Objects.
The situation when QV scheduler finds no events for processing in a given pass through the "superloop" is called the idle condition. In that case, the QV kernel executes idle processing to let the application, among others, put the CPU and peripherals in a low-power sleep mode (see Figure SRS-QV-IDL). Existence of such a single point to apply low-power modes is a hallmark of a power-friendly architecture.
However, as in the traditional "superloop" (a.k.a., "foreground/background" architecture) QV kernel must detect the idle condition inside a critical section (with interrupts disabled) and must be careful to enter the low-power mode safely without re-enabling interrupts too soon (see [Samek:07]). Otherwise any interrupt allowed after determining the idle condition but before calling the idle processing could post events to Active Objects, thus invalidating the idle condition. However, due to the simplistic, non-preemptive nature of the QV kernel, the idle processing would still be called and would enter the sleep mode while some events might be available and waiting (indefinitely) for processing.
The maximum time an event for the highest-priority Active Object can be delayed is called the task-level response. The task-level response in the QV kernel is equal to the longest RTC step of all Active Objects in the system. Note that this task-level response is still a lot better than the traditional "superloop" (a.k.a. main+ISRs) architecture, where the task-level response is typically the sum of the worst-case execution times of all tasks in the "superloop".
Due to the non-blocking nature of event processing inside Active Objects, the RTC steps tend to be short (typically microseconds), which can deliver adequate real-time performance to surprisingly wide range of applications. Also, the task-level response can be often improved by breaking up the longest RTC steps into shorter pieces (multi-stage processing). For example, an Active Object can perform only a fraction of the overall event processing and post event to self to trigger continuation next time ("Reminder" state pattern).
SRS_QP_QV_00 : QP Framework shall provide non-preemptive QV kernel as one of the built-in kernels. |
---|
Description QP Framework shall provide QV kernel implementation and ports to the supported CPU/compiler combinations as one of the optional software components. QP Application can then choose the QV kernel to execute Active Objects. Such a selection is exclusive, meaning that when QP Application selects the QV kernel, other kernels are excluded and cannot be used. |
Description QP Framework can implement the QV kernel component by re-using already existing mechanisms, such as event queues for Active Objects, event delivery mechanisms, event memory management, etc. That way, the QV kernel implementation can be quite small and consist only of the missing pieces, such as the "superloop" with the QV scheduler. |
Forward Traceability |
SRS_QP_QV_10 : QV kernel shall provide an idle-callback defined in QP Application. |
---|
Description When no events are available in a given pass through the "superloop" (see Figure SRS-QV-SCH), the QV kernel executes idle processing. This idle processing shall invoke an idle-callback (a function) defined in QP Application. The idle-callback can perform any processing, including putting the CPU and peripherals in a low-power sleep mode.
|
Use Case The idle-callback can perform Software Tracing data transfer to the host, or other processing. |
Forward Traceability |
SRS_QP_QV_11 : The idle-callback shall be invoked with interrupts disabled to allow a safe transition to a low-power sleep mode. |
---|
Description As described in Section Idle Processing in QV, a safe transition to low-power sleep mode requires the QV idle-callback to be invoked with interrupts disabled (inside the same critical section as the detection of the idle condition). |
Forward Traceability |
SRS_QP_QV_12 : The idle-callback shall always return with interrupts enabled. |
---|
Description Regardless whether the idle-callback switches to a low-power mode, QP Application must define the idle-callback such that it re-enables interrupts in every path through the code. The QV kernel assumes that this will be the case, and will not work correctly if the idle-callback fails to enable interrupts. |
Forward Traceability |
SRS_QP_QV_20 : QV kernel may provide API to selectively disable scheduling Active Objects below the specified scheduler-disable ceiling priority. |
---|
Description The selective scheduler disabling API shall prevent scheduling any Active Object whose unique priority is below the specified scheduler-disable ceiling priority. |
Use Case The main use case for selective scheduler disabling is in time-triggered designs and Active Objects with multi-stage processing. An Active Object that breaks up its long RTC steps into shorter pieces (multi-stage processing) would self-post a special "Reminder" event to trigger subsequent stages of processing. However, to prevent such processing from overrunning the next clock period, the Active Object can explicitly disable the QV scheduler up to its own priority level. |
Forward Traceability |
SRS_QP_QV_21 : If QV kernel provides API to disable the scheduler it shall provide the API to enable the scheduler. |
---|
Description The scheduler enabling API shall complement the scheduler disabling API (see SRS_QP_QV_20). The scheduler enabling API shall restore the scheduler-disable ceiling established in the most recent call to the scheduler disabling API. |
Use Case The main use case for scheduler enabling (matching the use case in SRS_QP_QV_20) is enabling the QV scheduler in the system clock tick. |
Forward Traceability |