QP/C  7.4.0-rc.2
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 6.1.1 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// This code is covered by the following QP license:
10// License # : LicenseRef-QL-dual
11// Issued to : Any user of the QP/C real-time embedded framework
12// Framework(s) : qpc
13// Support ends : 2024-12-31
14// License scope:
15//
16// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17//
18// Q u a n t u m L e a P s
19// ------------------------
20// Modern Embedded Software
21//
22// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
23//
24// This software is dual-licensed under the terms of the open source GNU
25// General Public License version 3 (or any later version), or alternatively,
26// under the terms of one of the closed source Quantum Leaps commercial
27// licenses.
28//
29// The terms of the open source GNU General Public License version 3
30// can be found at: <www.gnu.org/licenses/gpl-3.0>
31//
32// The terms of the closed source Quantum Leaps commercial licenses
33// can be found at: <www.state-machine.com/licensing>
34//
35// Redistributions in source code must retain this top-level comment block.
36// Plagiarizing this software to sidestep the license obligations is illegal.
37//
38// Contact information:
39// <www.state-machine.com/licensing>
40// <info@state-machine.com>
41//
42//$endhead${src::qv::qv.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qp_port.h" // QP port
45#include "qp_pkg.h" // QP package-scope internal interface
46#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
47#ifdef Q_SPY // QS software tracing enabled?
48 #include "qs_port.h" // QS port
49 #include "qs_pkg.h" // QS facilities for pre-defined trace records
50#else
51 #include "qs_dummy.h" // disable the QS software tracing
52#endif // Q_SPY
53
54// protection against including this source file in a wrong project
55#ifndef QV_H_
56 #error "Source file included in a project NOT based on the QV kernel"
57#endif // QV_H_
58
59Q_DEFINE_THIS_MODULE("qv")
60
61//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
62// Check for the minimum required QP version
63#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
64#error qpc version 7.3.0 or higher required
65#endif
66//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
67
68//$define${QV::QV-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
69
70//${QV::QV-base::priv_} ......................................................
71QV_Attr QV_priv_;
72
73//${QV::QV-base::schedDisable} ...............................................
74//! @static @public @memberof QV
75void QV_schedDisable(uint_fast8_t const ceiling) {
78 QF_MEM_SYS();
79
80 Q_INVARIANT_INCRIT(102, QV_priv_.schedCeil
81 == (uint_fast8_t)(~QV_priv_.schedCeil_dis));
82
83 if (ceiling > QV_priv_.schedCeil) { // raising the scheduler ceiling?
84
85 QS_BEGIN_PRE_(QS_SCHED_LOCK, 0U)
86 QS_TIME_PRE_(); // timestamp
87 // the previous sched ceiling & new sched ceiling
88 QS_2U8_PRE_((uint8_t)QV_priv_.schedCeil,
89 (uint8_t)ceiling);
90 QS_END_PRE_()
91
92 QV_priv_.schedCeil = ceiling;
93 #ifndef Q_UNSAFE
94 QV_priv_.schedCeil_dis = (uint_fast8_t)(~ceiling);
95 #endif
96 }
97 QF_MEM_APP();
99}
100
101//${QV::QV-base::schedEnable} ................................................
102//! @static @public @memberof QV
103void QV_schedEnable(void) {
106 QF_MEM_SYS();
107
108 Q_INVARIANT_INCRIT(202, QV_priv_.schedCeil
109 == (uint_fast8_t)(~QV_priv_.schedCeil_dis));
110
111 if (QV_priv_.schedCeil != 0U) { // actually enabling the scheduler?
112
113 QS_BEGIN_PRE_(QS_SCHED_UNLOCK, 0U)
114 QS_TIME_PRE_(); // timestamp
115 // current sched ceiling (old), previous sched ceiling (new)
116 QS_2U8_PRE_((uint8_t)QV_priv_.schedCeil, 0U);
117 QS_END_PRE_()
118
119 QV_priv_.schedCeil = 0U;
120 #ifndef Q_UNSAFE
121 QV_priv_.schedCeil_dis = (uint_fast8_t)(~0U);
122 #endif
123 }
124 QF_MEM_APP();
125 QF_CRIT_EXIT();
126}
127//$enddef${QV::QV-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
128
129//$define${QV::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
130
131//${QV::QF-cust::init} .......................................................
132//! @static @public @memberof QF
133void QF_init(void) {
134 QF_bzero_(&QF_priv_, sizeof(QF_priv_));
135 QF_bzero_(&QV_priv_, sizeof(QV_priv_));
136 QF_bzero_(&QActive_registry_[0], sizeof(QActive_registry_));
137
138 #ifndef Q_UNSAFE
139 QPSet_update_(&QV_priv_.readySet, &QV_priv_.readySet_dis);
140 QV_priv_.schedCeil_dis = (uint_fast8_t)(~0U);
141 #endif
142
143 for (uint_fast8_t tickRate = 0U;
144 tickRate < Q_DIM(QTimeEvt_timeEvtHead_);
145 ++tickRate)
146 {
147 QTimeEvt_ctorX(&QTimeEvt_timeEvtHead_[tickRate],
148 (QActive *)0, (enum_t)Q_USER_SIG, tickRate);
149 }
150
151 #ifdef QV_INIT
152 QV_INIT(); // port-specific initialization of the QV kernel
153 #endif
154}
155
156//${QV::QF-cust::stop} .......................................................
157//! @static @public @memberof QF
158void QF_stop(void) {
159 QF_onCleanup(); // application-specific cleanup callback
160 // nothing else to do for the QV kernel
161}
162
163//${QV::QF-cust::run} ........................................................
164//! @static @public @memberof QF
165int_t QF_run(void) {
166 #ifdef Q_SPY
167 // produce the QS_QF_RUN trace record
169 QF_MEM_SYS();
170 QS_beginRec_((uint_fast8_t)QS_QF_RUN);
171 QS_endRec_();
172 QF_MEM_APP();
174 #endif // Q_SPY
175
176 QF_onStartup(); // application-specific startup callback
177
179 QF_MEM_SYS();
180
181 #ifdef QV_START
182 QV_START(); // port-specific startup of the QV kernel
183 #endif
184
185 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
186 uint_fast8_t pprev = 0U; // previously used prio.
187 #endif
188
189 for (;;) { // QV event loop...
190
191 // check internal integrity (duplicate inverse storage)
192 Q_INVARIANT_INCRIT(302, QPSet_verify_(&QV_priv_.readySet,
193 &QV_priv_.readySet_dis));
194 // check internal integrity (duplicate inverse storage)
195 Q_INVARIANT_INCRIT(303, QV_priv_.schedCeil
196 == (uint_fast8_t)(~QV_priv_.schedCeil_dis));
197
198 // find the maximum prio. AO ready to run
199 uint_fast8_t const p = (QPSet_notEmpty(&QV_priv_.readySet)
200 ? QPSet_findMax(&QV_priv_.readySet)
201 : 0U);
202
203 if (p > QV_priv_.schedCeil) { // is it above the sched ceiling?
204 QActive * const a = QActive_registry_[p];
205
206 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
207 QS_BEGIN_PRE_(QS_SCHED_NEXT, p)
208 QS_TIME_PRE_(); // timestamp
209 QS_2U8_PRE_((uint8_t)p,
210 (uint8_t)pprev);
211 QS_END_PRE_()
212
213 #ifdef QF_ON_CONTEXT_SW
214 QF_onContextSw(((pprev != 0U)
215 ? QActive_registry_[pprev]
216 : (QActive *)0), a);
217 #endif // QF_ON_CONTEXT_SW
218
219 pprev = p; // update previous prio.
220 #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
221
222 QF_MEM_APP();
224
225 QEvt const * const e = QActive_get_(a);
226 // NOTE QActive_get_() performs QS_MEM_APP() before return
227
228 // dispatch event (virtual call)
229 (*a->super.vptr->dispatch)(&a->super, e, p);
230 #if (QF_MAX_EPOOL > 0U)
231 QF_gc(e);
232 #endif
234 QF_MEM_SYS();
235
236 if (a->eQueue.frontEvt == (QEvt *)0) { // empty queue?
237 QPSet_remove(&QV_priv_.readySet, p);
238 #ifndef Q_UNSAFE
239 QPSet_update_(&QV_priv_.readySet, &QV_priv_.readySet_dis);
240 #endif
241 }
242 }
243 else { // no AO ready to run --> idle
244 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
245 if (pprev != 0U) {
246 QS_BEGIN_PRE_(QS_SCHED_IDLE, pprev)
247 QS_TIME_PRE_(); // timestamp
248 QS_U8_PRE_((uint8_t)pprev); // previous prio
249 QS_END_PRE_()
250
251 #ifdef QF_ON_CONTEXT_SW
252 QF_onContextSw(QActive_registry_[pprev], (QActive *)0);
253 #endif // QF_ON_CONTEXT_SW
254
255 pprev = 0U; // update previous prio.
256 }
257 #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
258
259 QF_MEM_APP();
260
261 // QV_onIdle() must be called with interrupts DISABLED because
262 // the determination of the idle condition can change at any time
263 // by an interrupt posting events to a queue.
264 //
265 // NOTE: QV_onIdle() MUST enable interrupts internally, ideally
266 // atomically with putting the CPU into a power-saving mode.
267 QV_onIdle();
268
269 QF_INT_DISABLE(); // disable interrupts before looping back
270 QF_MEM_SYS();
271 }
272 }
273 #ifdef __GNUC__ // GNU compiler?
274 return 0;
275 #endif
276}
277//$enddef${QV::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
278
279//$define${QV::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
280
281//${QV::QActive} .............................................................
282
283//${QV::QActive::start_} .....................................................
284//! @public @memberof QActive
285void QActive_start_(QActive * const me,
286 QPrioSpec const prioSpec,
287 QEvt const * * const qSto,
288 uint_fast16_t const qLen,
289 void * const stkSto,
290 uint_fast16_t const stkSize,
291 void const * const par)
292{
293 Q_UNUSED_PAR(stkSto); // not needed in QV
294 Q_UNUSED_PAR(stkSize); // not needed in QV
295
298 Q_REQUIRE_INCRIT(300, stkSto == (void *)0);
299 QF_CRIT_EXIT();
300
301 me->prio = (uint8_t)(prioSpec & 0xFFU); // QF-prio. of the AO
302 me->pthre = 0U; // not used
303 QActive_register_(me); // make QF aware of this active object
304
305 QEQueue_init(&me->eQueue, qSto, qLen); // init the built-in queue
306
307 // top-most initial tran. (virtual call)
308 (*me->super.vptr->init)(&me->super, par, me->prio);
309 QS_FLUSH(); // flush the trace buffer to the host
310}
311//$enddef${QV::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
QF_Attr QF_priv_
Definition qf_act.c:71
#define QF_MEM_APP()
Definition qp.h:1288
#define Q_UNUSED_PAR(par_)
Definition qp.h:536
@ Q_USER_SIG
offset for the user signals (QP Application)
Definition qp.h:263
#define QF_MEM_SYS()
Definition qp.h:1283
int int_t
Definition qp.h:104
int enum_t
Definition qp.h:107
#define Q_DIM(array_)
Definition qp.h:539
uint16_t QPrioSpec
Definition qp.h:623
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_QF_RUN
QF_run() was entered.
Definition qs.h:179
#define QS_TIME_PRE_()
Definition qs.h:450
@ QS_SCHED_IDLE
scheduler restored the idle task
Definition qs.h:156
@ QS_SCHED_LOCK
scheduler was locked
Definition qs.h:153
@ QS_SCHED_UNLOCK
scheduler was unlocked
Definition qs.h:154
#define QS_FLUSH()
Definition qs.h:363
@ QS_SCHED_NEXT
scheduler started next task
Definition qs.h:155
QS/C package-scope interface.
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:58
#define Q_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:154
#define QF_CRIT_EXIT()
Definition qsafe.h:62
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:136
#define QF_CRIT_STAT
Definition qsafe.h:54
int_t QF_run(void)
Definition qutest.c:191
void QF_init(void)
Definition qutest.c:172
void QF_stop(void)
Definition qutest.c:186
Active object class (based on the QHsm implementation strategy)
Definition qp.h:804
QACTIVE_EQUEUE_TYPE eQueue
Definition qp.h:826
QAsm super
Definition qp.h:806
uint8_t prio
Definition qp.h:809
uint8_t pthre
Definition qp.h:812
struct QAsmVtable const * vptr
Definition qp.h:284
void(* init)(QAsm *const me, void const *const e, uint_fast8_t const qsId)
Definition qp.h:302
void(* dispatch)(QAsm *const me, QEvt const *const e, uint_fast8_t const qsId)
Definition qp.h:304
Event class.
Definition qp.h:145
Private attributes of the QV kernel.
Definition qv.h:61