QP/C++  7.4.0-rc.1
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qv.cpp
Go to the documentation of this file.
1//$file${src::qv::qv.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpcpp.qm
4// File: ${src::qv::qv.cpp}
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) : qpcpp
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.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qp_port.hpp" // QP port
45#include "qp_pkg.hpp" // QP package-scope interface
46#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
47#ifdef Q_SPY // QS software tracing enabled?
48 #include "qs_port.hpp" // QS port
49 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
50#else
51 #include "qs_dummy.hpp" // disable the QS software tracing
52#endif // Q_SPY
53
54// protection against including this source file in a wrong project
55#ifndef QV_HPP_
56 #error "Source file included in a project NOT based on the QV kernel"
57#endif // QV_HPP_
58
59// unnamed namespace for local definitions with internal linkage
60namespace {
61Q_DEFINE_THIS_MODULE("qv")
62} // unnamed namespace
63
64//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
65// Check for the minimum required QP version
66#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
67#error qpcpp version 7.3.0 or higher required
68#endif
69//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
70
71//$define${QV::QV-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
72namespace QP {
73namespace QV {
74
75//${QV::QV-base::priv_} ......................................................
77
78//${QV::QV-base::schedDisable} ...............................................
79void schedDisable(std::uint_fast8_t const ceiling) {
82 QF_MEM_SYS();
83
85 == static_cast<std::uint_fast8_t>(~priv_.schedCeil_dis));
86
87 if (ceiling > priv_.schedCeil) { // raising the scheduler ceiling?
88
89 QS_BEGIN_PRE_(QS_SCHED_LOCK, 0U)
90 QS_TIME_PRE_(); // timestamp
91 // the previous sched ceiling & new sched ceiling
92 QS_2U8_PRE_(static_cast<std::uint8_t>(priv_.schedCeil),
93 static_cast<std::uint8_t>(ceiling));
94 QS_END_PRE_()
95
96 priv_.schedCeil = ceiling;
97 #ifndef Q_UNSAFE
98 priv_.schedCeil_dis = static_cast<std::uint_fast8_t>(~ceiling);
99 #endif
100 }
101 QF_MEM_APP();
102 QF_CRIT_EXIT();
103}
104
105//${QV::QV-base::schedEnable} ................................................
109 QF_MEM_SYS();
110
112 == static_cast<std::uint_fast8_t>(~priv_.schedCeil_dis));
113
114 if (priv_.schedCeil != 0U) { // actually enabling the scheduler?
115
116 QS_BEGIN_PRE_(QS_SCHED_UNLOCK, 0U)
117 QS_TIME_PRE_(); // timestamp
118 // current sched ceiling (old), previous sched ceiling (new)
119 QS_2U8_PRE_(static_cast<std::uint8_t>(priv_.schedCeil), 0U);
120 QS_END_PRE_()
121
122 priv_.schedCeil = 0U;
123 #ifndef Q_UNSAFE
124 priv_.schedCeil_dis = ~static_cast<std::uint_fast8_t>(0U);
125 #endif
126 }
127 QF_MEM_APP();
128 QF_CRIT_EXIT();
129}
130
131} // namespace QV
132} // namespace QP
133//$enddef${QV::QV-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
134
135//$define${QV::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
136namespace QP {
137namespace QF {
138
139//${QV::QF-cust::init} .......................................................
140void init() {
141 bzero_(&QF::priv_, sizeof(QF::priv_));
142 bzero_(&QV::priv_, sizeof(QV::priv_));
144
145 #ifndef Q_UNSAFE
146 QV::priv_.readySet.update_(&QV::priv_.readySet_dis);
147 QV::priv_.schedCeil_dis = ~static_cast<std::uint_fast8_t>(0U);
148 #endif
149
150 #ifdef QV_INIT
151 QV_INIT(); // port-specific initialization of the QV kernel
152 #endif
153}
154
155//${QV::QF-cust::stop} .......................................................
156void stop() {
157 onCleanup(); // cleanup callback
158 // nothing else to do for the QV kernel
159}
160
161//${QV::QF-cust::run} ........................................................
162int_t run() {
163 #ifdef Q_SPY
164 // produce the QS_QF_RUN trace record
166 QF_MEM_SYS();
167 QS::beginRec_(QS_REC_NUM_(QS_QF_RUN));
168 QS::endRec_();
169 QF_MEM_APP();
171 #endif // Q_SPY
172
173 onStartup(); // application-specific startup callback
174
176 QF_MEM_SYS();
177
178 #ifdef QV_START
179 QV_START(); // port-specific startup of the QV kernel
180 #endif
181
182 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
183 std::uint_fast8_t pprev = 0U; // previous prio.
184 #endif
185
186 for (;;) { // QV event loop...
187
188 // check internal integrity (duplicate inverse storage)
190 QV::priv_.readySet.verify_(&QV::priv_.readySet_dis));
191 // check internal integrity (duplicate inverse storage)
192 Q_INVARIANT_INCRIT(303, QV::priv_.schedCeil
193 == static_cast<std::uint_fast8_t>(~QV::priv_.schedCeil_dis));
194
195 // find the maximum prio. AO ready to run
196 std::uint_fast8_t const p = (QV::priv_.readySet.notEmpty()
198 : 0U);
199
200 if (p > QV::priv_.schedCeil) { // is it above the sched ceiling?
201 QActive * const a = QActive::registry_[p];
202
203 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
204 QS_BEGIN_PRE_(QS_SCHED_NEXT, p)
205 QS_TIME_PRE_(); // timestamp
206 QS_2U8_PRE_(static_cast<std::uint8_t>(p),
207 static_cast<std::uint8_t>(pprev));
208 QS_END_PRE_()
209
210 #ifdef QF_ON_CONTEXT_SW
211 QF_onContextSw(((pprev != 0U)
212 ? QActive::registry_[pprev]
213 : nullptr), a);
214 #endif // QF_ON_CONTEXT_SW
215
216 pprev = p; // update previous prio.
217 #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
218
219 QF_MEM_APP();
221
222 QEvt const * const e = a->get_();
223 // NOTE QActive::get_() performs QF_MEM_APP() before return
224
225 // dispatch event (virtual call)
226 a->dispatch(e, a->getPrio());
227 #if (QF_MAX_EPOOL > 0U)
228 gc(e);
229 #endif
231 QF_MEM_SYS();
232
233 if (a->getEQueue().isEmpty()) { // empty queue?
235 #ifndef Q_UNSAFE
236 QV::priv_.readySet.update_(&QV::priv_.readySet_dis);
237 #endif
238 }
239 }
240 else { // no AO ready to run --> idle
241 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
242 if (pprev != 0U) {
243 QS_BEGIN_PRE_(QS_SCHED_IDLE, pprev)
244 QS_TIME_PRE_(); // timestamp
245 QS_U8_PRE_(static_cast<std::uint8_t>(pprev));
246 QS_END_PRE_()
247
248 #ifdef QF_ON_CONTEXT_SW
249 QF_onContextSw(QActive::registry_[pprev], nullptr);
250 #endif // QF_ON_CONTEXT_SW
251
252 pprev = 0U; // update previous prio
253 }
254 #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
255
256 QF_MEM_APP();
257
258 // QV::onIdle() must be called with interrupts DISABLED
259 // because the determination of the idle condition (all event
260 // queues empty) can change at any time by an interrupt posting
261 // events to a queue.
262 //
263 // NOTE: QV::onIdle() MUST enable interrupts internally,
264 // ideally at the same time as putting the CPU into a power-
265 // saving mode.
266 QV::onIdle();
267
269 QF_MEM_SYS();
270 }
271 }
272 #ifdef __GNUC__ // GNU compiler?
273 return 0;
274 #endif
275}
276
277} // namespace QF
278} // namespace QP
279//$enddef${QV::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
280
281//$define${QV::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
282namespace QP {
283
284//${QV::QActive} .............................................................
285
286//${QV::QActive::start} ......................................................
287void QActive::start(
288 QPrioSpec const prioSpec,
289 QEvt const * * const qSto,
290 std::uint_fast16_t const qLen,
291 void * const stkSto,
292 std::uint_fast16_t const stkSize,
293 void const * const par)
294{
295 Q_UNUSED_PAR(stkSto); // not needed in QV
296 Q_UNUSED_PAR(stkSize); // not needed in QV
297
300 Q_REQUIRE_INCRIT(300, stkSto == nullptr);
301 QF_CRIT_EXIT();
302
303 m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio.
304 m_pthre = 0U; // not used
305 register_(); // make QF aware of this AO
306
307 m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO
308
309 this->init(par, m_prio); // take the top-most initial tran. (virtual)
310 QS_FLUSH(); // flush the trace buffer to the host
311}
312
313} // namespace QP
314//$enddef${QV::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
void init(void const *const e, std::uint_fast8_t const qsId) override
Definition qp.hpp:779
static QActive * registry_[QF_MAX_ACTIVE+1U]
Definition qp.hpp:748
void register_() noexcept
Definition qf_qact.cpp:76
QACTIVE_EQUEUE_TYPE m_eQueue
Definition qp.hpp:736
std::uint8_t m_pthre
Definition qp.hpp:725
void start(QPrioSpec const prioSpec, QEvt const **const qSto, std::uint_fast16_t const qLen, void *const stkSto, std::uint_fast16_t const stkSize, void const *const par)
Definition qk.cpp:449
std::uint8_t m_prio
Definition qp.hpp:724
std::uint_fast8_t findMax() const noexcept
Definition qp.hpp:668
void remove(std::uint_fast8_t const n) noexcept
Definition qp.hpp:656
bool notEmpty() const noexcept
Definition qp.hpp:628
void update_(QPSet *const dis) const noexcept
Definition qp.hpp:679
Private attributes of the QV kernel.
Definition qv.hpp:51
QPSet readySet
Definition qv.hpp:53
QPSet readySet_dis
Definition qv.hpp:57
std::uint_fast8_t schedCeil
Definition qv.hpp:54
std::uint_fast8_t schedCeil_dis
Definition qv.hpp:61
void onCleanup()
void gc(QEvt const *const e) noexcept
Definition qf_dyn.cpp:222
void bzero_(void *const start, std::uint_fast16_t const len) noexcept
Definition qf_act.cpp:81
QF::Attr priv_
Definition qf_act.cpp:78
void init()
Definition qk.cpp:369
int_t run()
Definition qk.cpp:397
void stop()
Definition qk.cpp:391
void onStartup()
QV::Attr priv_
Definition qv.cpp:76
void schedEnable()
Definition qv.cpp:106
void onIdle()
void schedDisable(std::uint_fast8_t const ceiling)
Definition qv.cpp:79
QP/C++ framework.
Definition qequeue.hpp:50
std::uint16_t QPrioSpec
Definition qp.hpp:572
@ QS_SCHED_LOCK
scheduler was locked
Definition qs.hpp:145
@ QS_QF_RUN
QF_run() was entered.
Definition qs.hpp:171
@ QS_SCHED_NEXT
scheduler started next task
Definition qs.hpp:147
@ QS_SCHED_UNLOCK
scheduler was unlocked
Definition qs.hpp:146
@ QS_SCHED_IDLE
scheduler restored the idle task
Definition qs.hpp:148
int int_t
Definition qp.hpp:103
#define QF_MEM_APP()
Definition qp.hpp:1331
#define Q_UNUSED_PAR(par_)
Definition qp.hpp:539
void QF_onContextSw(QP::QActive *prev, QP::QActive *next)
#define QF_MEM_SYS()
Definition qp.hpp:1326
Internal (package scope) QP/C++ interface.
Sample QP/C++ port.
#define QF_INT_DISABLE()
Disable interrupts.
Definition qp_port.hpp:36
#define QF_INT_ENABLE()
Enable interrupts.
Definition qp_port.hpp:39
#define QS_TIME_PRE_()
Definition qs.hpp:473
#define QS_FLUSH()
Definition qs.hpp:363
QS/C++ package-scope interface.
QS/C++ port to a 32-bit CPU, generic C++ compiler.
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