QP/C  8.0.3
Real-Time Event Framework
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//............................................................................
48QV_Attr QV_priv_;
49
50//............................................................................
51//! @static @public @memberof QV
52void QV_schedDisable(uint_fast8_t const ceiling) {
55
56 if (ceiling > QV_priv_.schedCeil) { // raising the scheduler ceiling?
57
58 QS_BEGIN_PRE(QS_SCHED_LOCK, 0U)
59 QS_TIME_PRE(); // timestamp
60 // the previous sched ceiling & new sched ceiling
61 QS_2U8_PRE((uint8_t)QV_priv_.schedCeil,
62 (uint8_t)ceiling);
64
65 QV_priv_.schedCeil = ceiling;
66 }
68}
69
70//............................................................................
71//! @static @public @memberof QV
72void QV_schedEnable(void) {
75
76 if (QV_priv_.schedCeil != 0U) { // actually enabling the scheduler?
77
78 QS_BEGIN_PRE(QS_SCHED_UNLOCK, 0U)
79 QS_TIME_PRE(); // timestamp
80 // current sched ceiling (old), previous sched ceiling (new)
81 QS_2U8_PRE((uint8_t)QV_priv_.schedCeil, 0U);
83
84 QV_priv_.schedCeil = 0U;
85 }
87}
88
89//............................................................................
90//! @static @public @memberof QF
91void QF_init(void) {
92 QF_bzero_(&QF_priv_, sizeof(QF_priv_));
93 QF_bzero_(&QV_priv_, sizeof(QV_priv_));
94 QF_bzero_(&QActive_registry_[0], sizeof(QActive_registry_));
95
96 QTimeEvt_init(); // initialize QTimeEvts
97
98#ifdef QV_INIT
99 QV_INIT(); // port-specific initialization of the QV kernel
100#endif
101}
102
103//............................................................................
104//! @static @public @memberof QF
105void QF_stop(void) {
106 QF_onCleanup(); // application-specific cleanup callback
107 // nothing else to do for the QV kernel
108}
109
110//............................................................................
111//! @static @public @memberof QF
114#ifdef Q_SPY
115 // produce the QS_QF_RUN trace record
116 QS_beginRec_((uint_fast8_t)QS_QF_RUN);
117 QS_endRec_();
118#endif // Q_SPY
119
120#ifdef QV_START
121 QV_START(); // port-specific startup of the QV kernel
122#endif
123
124#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
125 uint_fast8_t pprev = 0U; // previously used prio.
126
127#ifdef QF_ON_CONTEXT_SW
128 // officially switch to the idle cotext
129 QF_onContextSw((QActive *)0, (QActive *)0);
130#endif // def QF_ON_CONTEXT_SW
131
132#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
133
135
136 QF_onStartup(); // app. callback: configure and enable interrupts
137
139 for (;;) { // QV event loop...
140 // find the maximum prio. AO ready to run
141 uint_fast8_t const p = (QPSet_notEmpty(&QV_priv_.readySet)
142 ? QPSet_findMax(&QV_priv_.readySet)
143 : 0U);
144
145 if (p > QV_priv_.schedCeil) { // is it above the sched ceiling?
146 QActive * const a = QActive_registry_[p];
147
148#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
149 QS_BEGIN_PRE(QS_SCHED_NEXT, p)
150 QS_TIME_PRE(); // timestamp
151 QS_2U8_PRE((uint8_t)p,
152 (uint8_t)pprev);
153 QS_END_PRE()
154
155#ifdef QF_ON_CONTEXT_SW
156 QF_onContextSw(((pprev != 0U)
157 ? QActive_registry_[pprev]
158 : (QActive *)0), a);
159#endif // QF_ON_CONTEXT_SW
160
161 pprev = p; // update previous prio.
162#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
163
165
166 QEvt const * const e = QActive_get_(a);
167
168 // dispatch event (virtual call)
169 (*a->super.vptr->dispatch)(&a->super, e, p);
170#if (QF_MAX_EPOOL > 0U)
171 QF_gc(e);
172#endif
174
175 if (a->eQueue.frontEvt == (QEvt *)0) { // empty queue?
176 QPSet_remove(&QV_priv_.readySet, p);
177 }
178 }
179 else { // no AO ready to run --> idle
180#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
181 if (pprev != 0U) {
182 QS_BEGIN_PRE(QS_SCHED_IDLE, pprev)
183 QS_TIME_PRE(); // timestamp
184 QS_U8_PRE((uint8_t)pprev); // previous prio
185 QS_END_PRE()
186
187#ifdef QF_ON_CONTEXT_SW
188 QF_onContextSw(QActive_registry_[pprev], (QActive *)0);
189#endif // QF_ON_CONTEXT_SW
190
191 pprev = 0U; // update previous prio.
192 }
193#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
194
195 // QV_onIdle() must be called with interrupts DISABLED because
196 // the determination of the idle condition can change at any time
197 // by an interrupt posting events to a queue.
198 //
199 // NOTE: QV_onIdle() MUST enable interrupts internally, ideally
200 // atomically with putting the CPU into a power-saving mode.
201 QV_onIdle();
202
203 QF_INT_DISABLE(); // disable interrupts before looping back
204 }
205 }
206#ifdef __GNUC__ // GNU compiler?
207 return 0;
208#endif
209}
210
211//============================================================================
212//! @public @memberof QActive
213void QActive_start(QActive * const me,
214 QPrioSpec const prioSpec,
215 QEvtPtr * const qSto,
216 uint_fast16_t const qLen,
217 void * const stkSto,
218 uint_fast16_t const stkSize,
219 void const * const par)
220{
221 Q_UNUSED_PAR(stkSto); // not needed in QV
222 Q_UNUSED_PAR(stkSize); // not needed in QV
223
226 Q_REQUIRE_INCRIT(300, (me->super.vptr != (struct QAsmVtable *)0)
227 && (stkSto == (void *)0));
228 QF_CRIT_EXIT();
229
230 me->prio = (uint8_t)(prioSpec & 0xFFU); // QF-prio. of the AO
231 me->pthre = 0U; // not used
232 QActive_register_(me); // make QF aware of this active object
233
234 QEQueue_init(&me->eQueue, qSto, qLen); // init the built-in queue
235
236 // top-most initial tran. (virtual call)
237 (*me->super.vptr->init)(&me->super, par, me->prio);
238 QS_FLUSH(); // flush the trace buffer to the host
239}
void QF_onStartup(void)
Startup QF callback.
void QF_bzero_(void *const start, uint_fast16_t const len)
Definition qf_act.c:52
void QF_onCleanup(void)
Cleanup QF callback.
int_t QF_run(void)
Transfers control to QF to run the application.
Definition qv.c:112
QF_Attr QF_priv_
Definition qp_pkg.h:46
void QF_gc(QEvt const *const e)
Recycle a mutable (mutable) event.
Definition qf_dyn.c:182
void QF_onContextSw(QActive *prev, QActive *next)
QF context switch callback used in built-in kernels (QV/QK/QXK)
void QF_init(void)
QF initialization.
Definition qv.c:91
void QF_stop(void)
Invoked by the application layer to stop the QF framework and return control to the OS/Kernel (used i...
Definition qv.c:105
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.h:94
QEvt const * QEvtPtr
Pointer to const event instances passed around in QP Framework.
Definition qp.h:136
int int_t
Alias for assertion-ID numbers in QP assertions and return from QF_run()
Definition qp.h:91
uint16_t QPrioSpec
Priority specification for Active Objects in QP.
Definition qp.h:382
Internal (package scope) QP/C interface.
Sample QP/C port.
#define QF_INT_DISABLE()
Disable interrupts.
Definition qp_port.h:37
#define QF_INT_ENABLE()
Enable interrupts.
Definition qp_port.h:40
QS/C dummy public interface.
#define QS_TIME_PRE()
Definition qs_dummy.h:146
#define QS_2U8_PRE(data1_, data2_)
Definition qs_dummy.h:143
#define QS_FLUSH()
Definition qs_dummy.h:75
#define QS_U8_PRE(data_)
Definition qs_dummy.h:142
#define QS_END_PRE()
Definition qs_dummy.h:141
#define QS_BEGIN_PRE(rec_, qsId_)
Definition qs_dummy.h:140
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:39
#define QF_CRIT_EXIT()
Definition qsafe.h:43
#define Q_REQUIRE_INCRIT(id_, expr_)
Assertion for checking a precondition (in critical section)
Definition qsafe.h:86
#define QF_CRIT_STAT
Definition qsafe.h:35
Active object class (based on the QHsm implementation strategy)
Definition qp.h:504
QAsm super
Definition qp.h:505
QACTIVE_EQUEUE_TYPE eQueue
Port-dependent event-queue type (often QEQueue)
Definition qp.h:518
void QActive_register_(QActive *const me)
Register this active object to be managed by the framework.
Definition qf_qact.c:73
uint8_t prio
QF-priority [1..QF_MAX_ACTIVE] of this AO.
Definition qp.h:506
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:213
uint8_t pthre
Preemption-threshold [1..QF_MAX_ACTIVE] of this AO.
Definition qp.h:507
struct QAsmVtable const * vptr
Virtual pointer inherited by all QAsm subclasses (see also SAS_QP_OO)
Definition qp.h:179
Virtual table for the QAsm class.
Definition qp.h:221
void(* init)(QAsm *const me, void const *const e, uint_fast8_t const qsId)
Virtual function to take the top-most initial transition in the state machine.
Definition qp.h:222
void(* dispatch)(QAsm *const me, QEvt const *const e, uint_fast8_t const qsId)
Virtual function to dispatch an event to the state machine.
Definition qp.h:224
Event class.
Definition qp.h:112
Private attributes of the QV kernel.
Definition qv.h:42
QPSet readySet
Definition qv.h:43
uint_fast8_t schedCeil
Definition qv.h:44
void QV_schedEnable(void)
Definition qv.c:72
QV_Attr QV_priv_
Definition qv.h:48