QP/C  8.0.0
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qv.c
Go to the documentation of this file.
1//$file${src::qv::qv.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpc.qm
4// File: ${src::qv::qv.c}
5//
6// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
10//
11// Q u a n t u m L e a P s
12// ------------------------
13// Modern Embedded Software
14//
15// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
16//
17// The QP/C software is dual-licensed under the terms of the open-source GNU
18// General Public License (GPL) or under the terms of one of the closed-
19// source Quantum Leaps commercial licenses.
20//
21// Redistributions in source code must retain this top-level comment block.
22// Plagiarizing this software to sidestep the license obligations is illegal.
23//
24// NOTE:
25// The GPL does NOT permit the incorporation of this code into proprietary
26// programs. Please contact Quantum Leaps for commercial licensing options,
27// which expressly supersede the GPL and are designed explicitly for
28// closed-source distribution.
29//
30// Quantum Leaps contact information:
31// <www.state-machine.com/licensing>
32// <info@state-machine.com>
33//
34//$endhead${src::qv::qv.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35#define QP_IMPL // this is QP implementation
36#include "qp_port.h" // QP port
37#include "qp_pkg.h" // QP package-scope internal interface
38#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
39#ifdef Q_SPY // QS software tracing enabled?
40 #include "qs_port.h" // QS port
41 #include "qs_pkg.h" // QS facilities for pre-defined trace records
42#else
43 #include "qs_dummy.h" // disable the QS software tracing
44#endif // Q_SPY
45
46// protection against including this source file in a wrong project
47#ifndef QV_H_
48 #error "Source file included in a project NOT based on the QV kernel"
49#endif // QV_H_
50
51Q_DEFINE_THIS_MODULE("qv")
52
53//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
54// Check for the minimum required QP version
55#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U))
56#error qpc version 7.3.0 or higher required
57#endif
58//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
59//$define${QV::QV-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
60
61//${QV::QV-base::priv_} ......................................................
62QV_Attr QV_priv_;
63
64//${QV::QV-base::schedDisable} ...............................................
65//! @static @public @memberof QV
66void QV_schedDisable(uint_fast8_t const ceiling) {
69 QF_MEM_SYS();
70
71 Q_INVARIANT_INCRIT(102, QV_priv_.schedCeil
72 == (uint_fast8_t)(~QV_priv_.schedCeil_dis));
73
74 if (ceiling > QV_priv_.schedCeil) { // raising the scheduler ceiling?
75
76 QS_BEGIN_PRE(QS_SCHED_LOCK, 0U)
77 QS_TIME_PRE(); // timestamp
78 // the previous sched ceiling & new sched ceiling
79 QS_2U8_PRE((uint8_t)QV_priv_.schedCeil,
80 (uint8_t)ceiling);
82
83 QV_priv_.schedCeil = ceiling;
84 #ifndef Q_UNSAFE
85 QV_priv_.schedCeil_dis = (uint_fast8_t)(~ceiling);
86 #endif
87 }
88 QF_MEM_APP();
90}
91
92//${QV::QV-base::schedEnable} ................................................
93//! @static @public @memberof QV
94void QV_schedEnable(void) {
97 QF_MEM_SYS();
98
99 Q_INVARIANT_INCRIT(202, QV_priv_.schedCeil
100 == (uint_fast8_t)(~QV_priv_.schedCeil_dis));
101
102 if (QV_priv_.schedCeil != 0U) { // actually enabling the scheduler?
103
104 QS_BEGIN_PRE(QS_SCHED_UNLOCK, 0U)
105 QS_TIME_PRE(); // timestamp
106 // current sched ceiling (old), previous sched ceiling (new)
107 QS_2U8_PRE((uint8_t)QV_priv_.schedCeil, 0U);
108 QS_END_PRE()
109
110 QV_priv_.schedCeil = 0U;
111 #ifndef Q_UNSAFE
112 QV_priv_.schedCeil_dis = (uint_fast8_t)(~0U);
113 #endif
114 }
115 QF_MEM_APP();
116 QF_CRIT_EXIT();
117}
118//$enddef${QV::QV-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
119
120//$define${QV::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
121
122//${QV::QF-cust::init} .......................................................
123//! @static @public @memberof QF
124void QF_init(void) {
125 QF_bzero_(&QF_priv_, sizeof(QF_priv_));
126 QF_bzero_(&QV_priv_, sizeof(QV_priv_));
127 QF_bzero_(&QActive_registry_[0], sizeof(QActive_registry_));
128
129 #ifndef Q_UNSAFE
130 QPSet_update_(&QV_priv_.readySet, &QV_priv_.readySet_dis);
131 QV_priv_.schedCeil_dis = (uint_fast8_t)(~0U);
132 #endif
133
134 QTimeEvt_init(); // initialize QTimeEvts
135
136 #ifdef QV_INIT
137 QV_INIT(); // port-specific initialization of the QV kernel
138 #endif
139}
140
141//${QV::QF-cust::stop} .......................................................
142//! @static @public @memberof QF
143void QF_stop(void) {
144 QF_onCleanup(); // application-specific cleanup callback
145 // nothing else to do for the QV kernel
146}
147
148//${QV::QF-cust::run} ........................................................
149//! @static @public @memberof QF
150int_t QF_run(void) {
151 #ifdef Q_SPY
152 // produce the QS_QF_RUN trace record
154 QF_MEM_SYS();
155 QS_beginRec_((uint_fast8_t)QS_QF_RUN);
156 QS_endRec_();
157 QF_MEM_APP();
159 #endif // Q_SPY
160
161 QF_onStartup(); // application-specific startup callback
162
164 QF_MEM_SYS();
165
166 #ifdef QV_START
167 QV_START(); // port-specific startup of the QV kernel
168 #endif
169
170 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
171 uint_fast8_t pprev = 0U; // previously used prio.
172
173 #ifdef QF_ON_CONTEXT_SW
174 // officially switch to the idle cotext
175 QF_onContextSw((QActive *)0, (QActive *)0);
176 #endif // def QF_ON_CONTEXT_SW
177
178 #endif // def (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
179
180 for (;;) { // QV event loop...
181
182 // check internal integrity (duplicate inverse storage)
183 Q_INVARIANT_INCRIT(302, QPSet_verify_(&QV_priv_.readySet,
184 &QV_priv_.readySet_dis));
185 // check internal integrity (duplicate inverse storage)
186 Q_INVARIANT_INCRIT(303, QV_priv_.schedCeil
187 == (uint_fast8_t)(~QV_priv_.schedCeil_dis));
188
189 // find the maximum prio. AO ready to run
190 uint_fast8_t const p = (QPSet_notEmpty(&QV_priv_.readySet)
191 ? QPSet_findMax(&QV_priv_.readySet)
192 : 0U);
193
194 if (p > QV_priv_.schedCeil) { // is it above the sched ceiling?
195 QActive * const a = QActive_registry_[p];
196
197 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
198 QS_BEGIN_PRE(QS_SCHED_NEXT, p)
199 QS_TIME_PRE(); // timestamp
200 QS_2U8_PRE((uint8_t)p,
201 (uint8_t)pprev);
202 QS_END_PRE()
203
204 #ifdef QF_ON_CONTEXT_SW
205 QF_onContextSw(((pprev != 0U)
206 ? QActive_registry_[pprev]
207 : (QActive *)0), a);
208 #endif // QF_ON_CONTEXT_SW
209
210 pprev = p; // update previous prio.
211 #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
212
213 QF_MEM_APP();
215
216 QEvt const * const e = QActive_get_(a);
217 // NOTE QActive_get_() performs QS_MEM_APP() before return
218
219 // dispatch event (virtual call)
220 (*a->super.vptr->dispatch)(&a->super, e, p);
221 #if (QF_MAX_EPOOL > 0U)
222 QF_gc(e);
223 #endif
225 QF_MEM_SYS();
226
227 if (a->eQueue.frontEvt == (QEvt *)0) { // empty queue?
228 QPSet_remove(&QV_priv_.readySet, p);
229 #ifndef Q_UNSAFE
230 QPSet_update_(&QV_priv_.readySet, &QV_priv_.readySet_dis);
231 #endif
232 }
233 }
234 else { // no AO ready to run --> idle
235 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
236 if (pprev != 0U) {
237 QS_BEGIN_PRE(QS_SCHED_IDLE, pprev)
238 QS_TIME_PRE(); // timestamp
239 QS_U8_PRE((uint8_t)pprev); // previous prio
240 QS_END_PRE()
241
242 #ifdef QF_ON_CONTEXT_SW
243 QF_onContextSw(QActive_registry_[pprev], (QActive *)0);
244 #endif // QF_ON_CONTEXT_SW
245
246 pprev = 0U; // update previous prio.
247 }
248 #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
249
250 QF_MEM_APP();
251
252 // QV_onIdle() must be called with interrupts DISABLED because
253 // the determination of the idle condition can change at any time
254 // by an interrupt posting events to a queue.
255 //
256 // NOTE: QV_onIdle() MUST enable interrupts internally, ideally
257 // atomically with putting the CPU into a power-saving mode.
258 QV_onIdle();
259
260 QF_INT_DISABLE(); // disable interrupts before looping back
261 QF_MEM_SYS();
262 }
263 }
264 #ifdef __GNUC__ // GNU compiler?
265 return 0;
266 #endif
267}
268//$enddef${QV::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
269
270//$define${QV::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
271
272//${QV::QActive} .............................................................
273
274//${QV::QActive::start} ......................................................
275//! @public @memberof QActive
276void QActive_start(QActive * const me,
277 QPrioSpec const prioSpec,
278 QEvtPtr * const qSto,
279 uint_fast16_t const qLen,
280 void * const stkSto,
281 uint_fast16_t const stkSize,
282 void const * const par)
283{
284 Q_UNUSED_PAR(stkSto); // not needed in QV
285 Q_UNUSED_PAR(stkSize); // not needed in QV
286
289 Q_REQUIRE_INCRIT(300, stkSto == (void *)0);
290 QF_CRIT_EXIT();
291
292 me->prio = (uint8_t)(prioSpec & 0xFFU); // QF-prio. of the AO
293 me->pthre = 0U; // not used
294 QActive_register_(me); // make QF aware of this active object
295
296 QEQueue_init(&me->eQueue, qSto, qLen); // init the built-in queue
297
298 // top-most initial tran. (virtual call)
299 (*me->super.vptr->init)(&me->super, par, me->prio);
300 QS_FLUSH(); // flush the trace buffer to the host
301}
302//$enddef${QV::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
QF_Attr QF_priv_
Definition qf_act.c:62
#define QF_MEM_APP()
Definition qp.h:1276
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.h:521
QEvt const * QEvtPtr
Pointer to const event instances passed around in QP Framework.
Definition qp.h:764
#define QF_MEM_SYS()
Definition qp.h:1271
int int_t
Alias for assertion-ID numbers in QP assertions and return from QF_run()
Definition qp.h:96
uint16_t QPrioSpec
Priority specification for Active Objects in QP.
Definition qp.h:591
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
#define QS_TIME_PRE()
Definition qs_dummy.h:147
#define QS_2U8_PRE(data1_, data2_)
Definition qs_dummy.h:144
#define QS_FLUSH()
Definition qs_dummy.h:76
#define QS_U8_PRE(data_)
Definition qs_dummy.h:143
#define QS_END_PRE()
Definition qs_dummy.h:142
#define QS_BEGIN_PRE(rec_, qsId_)
Definition qs_dummy.h:141
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:50
#define Q_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:146
#define QF_CRIT_EXIT()
Definition qsafe.h:54
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:128
#define QF_CRIT_STAT
Definition qsafe.h:46
Active object class (based on the QHsm implementation strategy)
Definition qp.h:775
QACTIVE_EQUEUE_TYPE eQueue
Port-dependent event-queue type (often QEQueue)
Definition qp.h:797
QAsm super
Definition qp.h:777
uint8_t prio
QF-priority [1..QF_MAX_ACTIVE] of this AO.
Definition qp.h:780
uint8_t pthre
Preemption-threshold [1..QF_MAX_ACTIVE] of this AO.
Definition qp.h:783
struct QAsmVtable const * vptr
Virtual pointer inherited by all QAsm subclasses (see also Object Orientation)
Definition qp.h:260
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:278
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:280
Event class.
Definition qp.h:131
Private attributes of the QV kernel.
Definition qv.h:53