QP/C++  7.0.1
Real-Time Embedded Framework
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 5.2.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 : 2023-12-31
14// License scope:
15//
16// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17//
18// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
19//
20// This software is dual-licensed under the terms of the open source GNU
21// General Public License version 3 (or any later version), or alternatively,
22// under the terms of one of the closed source Quantum Leaps commercial
23// licenses.
24//
25// The terms of the open source GNU General Public License version 3
26// can be found at: <www.gnu.org/licenses/gpl-3.0>
27//
28// The terms of the closed source Quantum Leaps commercial licenses
29// can be found at: <www.state-machine.com/licensing>
30//
31// Redistributions in source code must retain this top-level comment block.
32// Plagiarizing this software to sidestep the license obligations is illegal.
33//
34// Contact information:
35// <www.state-machine.com/licensing>
36// <info@state-machine.com>
37//
38//$endhead${src::qv::qv.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44
45#define QP_IMPL // this is QP implementation
46#include "qf_port.hpp" // QF port
47#include "qf_pkg.hpp" // QF package-scope internal interface
48#include "qassert.h" // QP embedded systems-friendly assertions
49#ifdef Q_SPY // QS software tracing enabled?
50 #include "qs_port.hpp" // QS port
51 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
52#else
53 #include "qs_dummy.hpp" // disable the QS software tracing
54#endif // Q_SPY
55
56// protection against including this source file in a wrong project
57#ifndef QV_HPP
58 #error "Source file included in a project NOT based on the QV kernel"
59#endif // QV_HPP
60
61//============================================================================
62namespace { // unnamed local namespace
64} // unnamed namespace
65
66//============================================================================
67//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
68// Check for the minimum required QP version
69#if (QP_VERSION < 690U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
70#error qpcpp version 6.9.0 or higher required
71#endif
72//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
73
74//$define${QV::QV-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
75namespace QP {
76namespace QV {
77
78} // namespace QV
79} // namespace QP
80//$enddef${QV::QV-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
81//$define${QV::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
82namespace QP {
83namespace QF {
84
85//${QV::QF-cust::init} .......................................................
86void init() {
87 QF::maxPool_ = 0U;
88 QActive::subscrList_ = nullptr;
90
94
95 #ifdef QV_INIT
96 QV_INIT(); // port-specific initialization of the QV kernel
97 #endif
98}
99
100//${QV::QF-cust::stop} .......................................................
101void stop() {
102 onCleanup(); // cleanup callback
103 // nothing else to do for the QV kernel
104}
105
106//${QV::QF-cust::run} ........................................................
107int_t run() {
108 #ifdef Q_SPY
109 std::uint_fast8_t pprev = 0U; // previous priority
110 #endif
111
112 onStartup(); // startup callback
113
114 // the combined event-loop and background-loop of the QV kernel...
116
117 // produce the QS_QF_RUN trace record
120
121 for (;;) {
122
123 // find the maximum priority AO ready to run
124 if (readySet_.notEmpty()) {
125 std::uint_fast8_t const p = readySet_.findMax();
126 QActive * const a = QActive::registry_[p];
127
128 #ifdef Q_SPY
130 QS_TIME_PRE_(); // timestamp
131 QS_2U8_PRE_(p, pprev);// scheduled prio & previous prio
133
134 pprev = p; // update previous priority
135 #endif // Q_SPY
136
138
139 // perform the run-to-completion (RTC) step...
140 // 1. retrieve the event from the AO's event queue, which by this
141 // time must be non-empty and The QV kernel asserts it.
142 // 2. dispatch the event to the AO's state machine.
143 // 3. determine if event is garbage and collect it if so
144 //
145 QEvt const * const e = a->get_();
146 a->dispatch(e, a->m_prio);
147 gc(e);
148
150 if (a->m_eQueue.isEmpty()) { // empty queue?
151 readySet_.rmove(p);
152 }
153 }
154 else { // no AO ready to run --> idle
155 #ifdef Q_SPY
156 if (pprev != 0U) {
158 QS_TIME_PRE_(); // timestamp
159 QS_U8_PRE_(pprev); // previous prio
161
162 pprev = 0U; // update previous prio
163 }
164 #endif // Q_SPY
165
166 // QV::onIdle() must be called with interrupts DISABLED because
167 // the determination of the idle condition (no events in the
168 // queues) can change at any time by an interrupt posting events
169 // to a queue. QV::onIdle() MUST enable interrupts internally,
170 // perhaps at the same time as putting the CPU into a power-saving
171 // mode.
172 QV::onIdle();
173
175 }
176 }
177 #ifdef __GNUC__ // GNU compiler?
178 return 0;
179 #endif
180}
181
182} // namespace QF
183} // namespace QP
184//$enddef${QV::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
185//$define${QV::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
186namespace QP {
187
188//${QV::QActive} .............................................................
189
190//${QV::QActive::start} ......................................................
191void QActive::start(
192 std::uint_fast8_t const prio,
193 QEvt const * * const qSto,
194 std::uint_fast16_t const qLen,
195 void * const stkSto,
196 std::uint_fast16_t const stkSize,
197 void const * const par)
198{
199 Q_UNUSED_PAR(stkSize); // not needed in QV
200
204 Q_REQUIRE_ID(500,
205 (0U < prio) && (prio <= QF_MAX_ACTIVE)
206 && (stkSto == nullptr));
207
208 m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO
209 m_prio = static_cast<std::uint8_t>(prio); // set the QF prio of this AO
210
211 register_(); // make QF aware of this AO
212
213 this->init(par, m_prio); // take the top-most initial tran. (virtual)
214 QS_FLUSH(); // flush the trace buffer to the host
215}
216
217} // namespace QP
218//$enddef${QV::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
std::uint8_t m_prio
QF priority (1..QF_MAX_ACTIVE) of this active object.
Definition: qf.hpp:367
static enum_t maxPubSignal_
The maximum published signal (the size of the subscrList_ array)
Definition: qf.hpp:399
static QActive * registry_[QF_MAX_ACTIVE+1U]
Internal array of registered active objects.
Definition: qf.hpp:393
void register_() noexcept
Register this active object to be managed by the framework.
Definition: qf_qact.cpp:142
virtual void start(std::uint_fast8_t const prio, QEvt const **const qSto, std::uint_fast16_t const qLen, void *const stkSto, std::uint_fast16_t const stkSize, void const *const par)
Starts execution of an active object and registers the object with the framework.
Definition: qk.cpp:215
static QSubscrList * subscrList_
pointer to the array of all subscriber AOs for a given event signal
Definition: qf.hpp:396
virtual void init(void const *const e, std::uint_fast8_t const qs_id)
Executes the top-most initial transition in QP::QHsm.
Definition: qep_hsm.cpp:134
std::uint_fast8_t findMax() const noexcept
Find the maximum element in the set, returns zero if the set is empty.
Definition: qf.hpp:258
void rmove(std::uint_fast8_t const n) noexcept
Remove element n from the set (n = 1U..64U)
Definition: qf.hpp:241
bool notEmpty() const noexcept
Return 'true' if the priority set is NOT empty.
Definition: qf.hpp:201
static QTimeEvt timeEvtHead_[QF_MAX_TICK_RATE]
heads of linked lists of time events, one for every clock tick rate
Definition: qf.hpp:963
#define QF_MAX_ACTIVE
The maximum number of active objects in the application.
Definition: config.hpp:32
#define QF_INT_DISABLE()
Define the interrupt disabling policy.
Definition: config.hpp:180
#define QF_INT_ENABLE()
Define the interrupt enabling policy.
Definition: config.hpp:191
void init()
QF initialization.
Definition: qk.cpp:155
std::uint_fast8_t maxPool_
number of initialized event pools
Definition: qf_qact.cpp:96
QPSet readySet_
"Ready-set" of all threads used in the built-in kernels
Definition: qf_qact.cpp:90
void onCleanup()
Cleanup QF callback (defined in applications/ports)
void gc(QEvt const *const e) noexcept
Recycle a dynamic event.
Definition: qf_dyn.cpp:161
void stop()
Function invoked by the application layer to stop the QF application and return control to the OS/Ker...
Definition: qk.cpp:174
int_t run()
Transfers control to QF to run the application.
Definition: qk.cpp:180
void bzero(void *const start, std::uint_fast16_t const len) noexcept
Clear a specified region of memory to zero.
Definition: qf_qact.cpp:99
void onStartup()
Startup QF callback (defined in applications/ports)
void onIdle()
QV idle callback (customized in BSPs for QV)
QP/C++ framework.
Definition: exa_native.dox:1
@ QS_QF_RUN
QF_run() was entered.
Definition: qs.hpp:231
@ QS_SCHED_IDLE
scheduler became idle
Definition: qs.hpp:210
@ QS_SCHED_NEXT
scheduler found next task to execute
Definition: qs.hpp:209
Customizable and memory-efficient Design by Contract (DbC) for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Definition: qassert.h:141
#define Q_REQUIRE_ID(id_, expr_)
Definition: qassert.h:243
int int_t
Definition: qassert.h:73
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition: qep.hpp:965
Internal (package scope) QF/C++ interface.
#define QS_TIME_PRE_()
Output time stamp to a QS record (used in predefined and application-specific trace records)
Definition: qs.hpp:1082
#define QS_FLUSH()
Flush the QS trace data to the host.
Definition: qs.hpp:961
Internal (package scope) QS/C++ interface.
#define QS_U8_PRE_(data_)
Internal QS macro to output an unformatted uint8_t data element.
Definition: qs_pkg.hpp:172
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Internal QS macro to begin a predefined QS record without critical section.
Definition: qs_pkg.hpp:144
#define QS_END_NOCRIT_PRE_()
Internal QS macro to end a predefiend QS record without critical section.
Definition: qs_pkg.hpp:153
#define QS_2U8_PRE_(data1_, data2_)
Internal QS macro to output 2 unformatted uint8_t data elements.
Definition: qs_pkg.hpp:176