QP/C Real-Time Event Framework 8.1.5
Loading...
Searching...
No Matches
qv.c
Go to the documentation of this file.
1//============================================================================
2// QP/C Real-Time Event Framework (RTEF)
3//
4// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
5//
6// Q u a n t u m L e a P s
7// ------------------------
8// Modern Embedded Software
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
11//
12// This software is dual-licensed under the terms of the open-source GNU
13// General Public License (GPL) or under the terms of one of the closed-
14// source Quantum Leaps commercial licenses.
15//
16// Redistributions in source code must retain this top-level comment block.
17// Plagiarizing this software to sidestep the license obligations is illegal.
18//
19// NOTE:
20// The GPL does NOT permit the incorporation of this code into proprietary
21// programs. Please contact Quantum Leaps for commercial licensing options,
22// which expressly supersede the GPL and are designed explicitly for
23// closed-source distribution.
24//
25// Quantum Leaps contact information:
26// <www.state-machine.com/licensing>
27// <info@state-machine.com>
28//============================================================================
29#define QP_IMPL // this is QP implementation
30#include "qp_port.h" // QP port
31#include "qp_pkg.h" // QP package-scope internal interface
32#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
33#ifdef Q_SPY // QS software tracing enabled?
34 #include "qs_port.h" // QS port
35 #include "qs_pkg.h" // QS facilities for pre-defined trace records
36#else
37 #include "qs_dummy.h" // disable the QS software tracing
38#endif // Q_SPY
39
40// protection against including this source file in a wrong project
41#ifndef QV_H_
42 #error Source file included in a project NOT based on the QV kernel
43#endif // QV_H_
44
45Q_DEFINE_THIS_MODULE("qv")
46
47//............................................................................
49
50//............................................................................
51//! @static @public @memberof QF
52void QF_init(void) {
53#if (QF_MAX_TICK_RATE > 0U)
54 QTimeEvt_init(); // initialize QTimeEvts
55#endif
56
57#ifdef QV_INIT
58 QV_INIT(); // port-specific initialization of the QV kernel
59#endif
60}
61
62//............................................................................
63//! @static @public @memberof QF
64void QF_stop(void) {
65 QF_onCleanup(); // application-specific cleanup callback
66 // nothing else to do for the QV kernel
67}
68
69//............................................................................
70//! @static @public @memberof QF
71int_t QF_run(void) {
73#ifdef Q_SPY
74 // produce the QS_QF_RUN trace record
75 QS_beginRec_((uint_fast8_t)QS_QF_RUN);
76 QS_endRec_();
77#endif // Q_SPY
78
79#ifdef QV_START
80 QV_START(); // port-specific startup of the QV kernel
81#endif
82
83#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
84 uint_fast8_t pprev = 0U; // previous prio.
85
86#ifdef QF_ON_CONTEXT_SW
87 // officially switch to the idle cotext
88 QF_onContextSw((QActive *)0, (QActive *)0);
89#endif // def QF_ON_CONTEXT_SW
90
91#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
92
93 // Application callback: configure and enable individual interrupts.
94 // NOTE: called with interrupts disabled and returns also
95 // with interrupts disabled
96 QF_onStartup();
97
98 for (;;) { // QV event-loop...
99 if (QPSet_notEmpty(&QV_priv_.readySet)) { // any AOs ready to run?
100 // find the maximum prio. AO ready to run
101 uint_fast8_t const p = QPSet_findMax(&QV_priv_.readySet);
102 QActive * const a = QActive_registry_[p];
103
104#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
105 if (p != pprev) { // changing threads?
106
108 QS_TIME_PRE(); // timestamp
109 QS_2U8_PRE((uint8_t)p,
110 (uint8_t)pprev);
111 QS_END_PRE()
112
113#ifdef QF_ON_CONTEXT_SW
114 QF_onContextSw(((pprev != 0U)
115 ? QActive_registry_[pprev]
116 : (QActive *)0), a);
117#endif // QF_ON_CONTEXT_SW
118
119 pprev = p; // update previous prio.
120 }
121#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
122
124
125 QEvt const * const e = QActive_get_(a); // queue not empty
126 QASM_DISPATCH(a, e, p); // virtual call
127#if (QF_MAX_EPOOL > 0U)
128 QF_gc(e); // check if the event is garbage, and collect it if so
129#endif
131
132 if (a->eQueue.frontEvt.e == (QEvt *)0) { // empty queue?
133 QPSet_remove(&QV_priv_.readySet, p);
134 }
135 }
136 else { // no AO ready to run --> idle
137#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
138 if (pprev != 0U) {
140 QS_TIME_PRE(); // timestamp
141 QS_U8_PRE((uint8_t)pprev);
142 QS_END_PRE()
143
144#ifdef QF_ON_CONTEXT_SW
145 QF_onContextSw(QActive_registry_[pprev], (QActive *)0);
146#endif // QF_ON_CONTEXT_SW
147
148 pprev = 0U; // update previous prio.
149 }
150#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
151
152 // QV_onIdle() must be called with interrupts DISABLED because
153 // the determination of the idle condition can change at any time
154 // by an interrupt posting events to a queue.
155 //
156 // NOTE: QV_onIdle() MUST enable interrupts internally, ideally
157 // atomically with putting the CPU into a power-saving mode.
158 QV_onIdle();
159
160 QF_INT_DISABLE(); // disable interrupts before looping back
161 }
162 }
163}
164
165//----------------------------------------------------------------------------
166//! @public @memberof QActive
167void QActive_start(QActive * const me,
168 QPrioSpec const prioSpec,
169 QEvtPtr * const qSto,
170 uint_fast16_t const qLen,
171 void * const stkSto,
172 uint_fast16_t const stkSize,
173 void const * const par)
174{
175 Q_UNUSED_PAR(stkSto); // not needed in QV
176 Q_UNUSED_PAR(stkSize); // not needed in QV
177
180
181 // the VPTR for this AO must be valid
182 Q_REQUIRE_INCRIT(300, me->super.vptr != (struct QAsmVtable *)0);
183
184 // stack storage must NOT be provided for the AO (QV does not need it)
185 Q_REQUIRE_INCRIT(310, stkSto == (void *)0);
186
187 QF_CRIT_EXIT();
188
189 me->prio = (uint8_t)(prioSpec & 0xFFU); // QF-prio.
190 me->pthre = 0U; // not used
191 QActive_register_(me); // make QF aware of this AO
192
193 QEQueue_init(&me->eQueue, qSto, qLen);
194
195 QASM_INIT(me, par, me->prio); // top-most initial tran. (virtual call)
196 QS_FLUSH(); // flush the trace buffer to the host
197}
#define QASM_INIT(me_, par_, qsId_)
Virtual call to the top-most initial transition in a state machine.
Definition qp.h:223
#define Q_UNUSED_PAR(par_)
Helper macro to mark unused parameters of functions.
Definition qp.h:90
int int_t
Alias for assertion-ID numbers in QP assertions and return from QF_run().
Definition qp.h:87
#define QASM_DISPATCH(me_, e_, qsId_)
Virtual call to dispatch an event to a state machine.
Definition qp.h:225
uint16_t QPrioSpec
Priority specification for Active Objects in QP.
Definition qp.h:388
QP/C Framework in C internal (package-scope) interface.
Sample QP/C port.
#define QF_INT_DISABLE()
Port-specific interrupt disable.
Definition qp_port.h:55
#define QF_INT_ENABLE()
Port-specific interrupt enable.
Definition qp_port.h:63
#define QS_TIME_PRE()
Definition qs.h:340
@ QS_QF_RUN
QF_run() was entered.
Definition qs.h:152
@ QS_SCHED_IDLE
scheduler restored the idle task
Definition qs.h:129
@ QS_SCHED_NEXT
scheduler started next task
Definition qs.h:128
#define QS_FLUSH()
Definition qs.h:262
QS (QP/Spy software tracing) internal (package-scope) interface.
#define QS_2U8_PRE(data1_, data2_)
Output two pre-formatted unsigned 8-bit integer data elements.
Definition qs_pkg.h:41
#define QS_U8_PRE(data_)
Output pre-formatted unsigned 8-bit integer data element.
Definition qs_pkg.h:40
#define QS_END_PRE()
Pre-formatted QS trace record end.
Definition qs_pkg.h:38
#define QS_BEGIN_PRE(rec_, qsId_)
Pre-formatted QS trace record begin.
Definition qs_pkg.h:32
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem (fault detection).
#define QF_CRIT_ENTRY()
Definition qsafe.h:40
#define QF_CRIT_EXIT()
Definition qsafe.h:44
#define Q_REQUIRE_INCRIT(id_, expr_)
Assertion for checking a precondition (in critical section).
Definition qsafe.h:98
#define QF_CRIT_STAT
Definition qsafe.h:36
int_t QF_run(void)
Definition qutest.c:217
void QF_init(void)
Definition qutest.c:138
void QF_stop(void)
Definition qutest.c:145
QV QV_priv_
Definition qv.c:48
Active object class (based on the QHsm implementation strategy).
Definition qp.h:452
QAsm super
Definition qp.h:453
QACTIVE_EQUEUE_TYPE eQueue
Port-dependent event-queue type (often QEQueue).
Definition qp.h:466
void QActive_register_(QActive *const me)
Register this active object to be managed by the framework.
Definition qf_qact.c:72
uint8_t prio
QF-priority [1..QF_MAX_ACTIVE] of this AO.
Definition qp.h:454
void QActive_start(QActive *const me, QPrioSpec const prioSpec, QEvtPtr *const qSto, uint_fast16_t const qLen, void *const stkSto, uint_fast16_t const stkSize, void const *const par)
Starts execution of an active object and registers the object with the framework.
Definition qv.c:167
uint8_t pthre
Preemption-threshold [1..QF_MAX_ACTIVE] of this AO.
Definition qp.h:455
struct QAsmVtable const * vptr
Virtual pointer inherited by all QAsm subclasses (see also ARCH_QP_OOA).
Definition qp.h:184
Virtual table for the QAsm class.
Definition qp.h:213
Event class.
Definition qp.h:100
The data type to store in the event queue ring-buffer.
Definition qequeue.h:46
QV non-preemptive kernel.
Definition qv.h:34