QP/C++  6.9.3
Real-Time Embedded Framework
qv.cpp
Go to the documentation of this file.
1 
40 #define QP_IMPL // this is QP implementation
41 #include "qf_port.hpp" // QF port
42 #include "qf_pkg.hpp" // QF package-scope internal interface
43 #include "qassert.h" // QP embedded systems-friendly assertions
44 #ifdef Q_SPY // QS software tracing enabled?
45  #include "qs_port.hpp" // QS port
46  #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
47 #else
48  #include "qs_dummy.hpp" // disable the QS software tracing
49 #endif // Q_SPY
50 
51 // protection against including this source file in a wrong project
52 #ifndef QV_HPP
53  #error "Source file included in a project NOT based on the QV kernel"
54 #endif // QV_HPP
55 
56 namespace QP {
57 
59 
60 
64 // Package-scope objects *****************************************************
65 extern "C" {
66  QPSet QV_readySet_; // ready set of AOs
67 } // extern "C"
68 
69 //****************************************************************************
79 void QF::init(void) {
80  QF_maxPool_ = 0U;
81  QF_subscrList_ = nullptr;
82  QF_maxPubSignal_ = 0;
83 
85  bzero(&active_[0], sizeof(active_));
86  bzero(&QV_readySet_, sizeof(QV_readySet_));
87 
88 #ifdef QV_INIT
89  QV_INIT(); // port-specific initialization of the QV kernel
90 #endif
91 }
92 
93 //****************************************************************************
109 void QF::stop(void) {
110  onCleanup(); // cleanup callback
111  // nothing else to do for the "vanilla" kernel
112 }
113 
114 //****************************************************************************
130 int_t QF::run(void) {
131 #ifdef Q_SPY
132  std::uint_fast8_t pprev = 0U; // previous priority
133 #endif
134 
135  onStartup(); // startup callback
136 
137  // the combined event-loop and background-loop of the QV kernel...
138  QF_INT_DISABLE();
139 
140  // produce the QS_QF_RUN trace record
143 
144  for (;;) {
145 
146  // find the maximum priority AO ready to run
147  if (QV_readySet_.notEmpty()) {
149  QActive * const a = active_[p];
150 
151 #ifdef Q_SPY
153  QS_TIME_PRE_(); // timestamp
154  QS_2U8_PRE_(p, pprev);// scheduled prio & previous prio
156 
157  pprev = p; // update previous priority
158 #endif // Q_SPY
159 
160  QF_INT_ENABLE();
161 
162  // perform the run-to-completion (RTC) step...
163  // 1. retrieve the event from the AO's event queue, which by this
164  // time must be non-empty and The "Vanialla" kernel asserts it.
165  // 2. dispatch the event to the AO's state machine.
166  // 3. determine if event is garbage and collect it if so
167  //
168  QEvt const * const e = a->get_();
169  a->dispatch(e, a->m_prio);
170  gc(e);
171 
172  QF_INT_DISABLE();
173 
174  if (a->m_eQueue.isEmpty()) { // empty queue?
175  QV_readySet_.rmove(p);
176  }
177  }
178  else { // no AO ready to run --> idle
179 #ifdef Q_SPY
180  if (pprev != 0U) {
182  QS_TIME_PRE_(); // timestamp
183  QS_U8_PRE_(pprev); // previous prio
185 
186  pprev = 0U; // update previous prio
187  }
188 #endif // Q_SPY
189 
190  // QV::onIdle() must be called with interrupts DISABLED because
191  // the determination of the idle condition (no events in the
192  // queues) can change at any time by an interrupt posting events
193  // to a queue. QV::onIdle() MUST enable interrupts internally,
194  // perhaps at the same time as putting the CPU into a power-saving
195  // mode.
196  QP::QV::onIdle();
197 
198  QF_INT_DISABLE();
199  }
200  }
201 #ifdef __GNUC__ // GNU compiler?
202  return 0;
203 #endif
204 }
205 
206 //****************************************************************************
222 void QActive::start(std::uint_fast8_t const prio,
223  QEvt const * * const qSto, std::uint_fast16_t const qLen,
224  void * const stkSto, std::uint_fast16_t const stkSize,
225  void const * const par)
226 {
227  static_cast<void>(stkSize); // unused paramteter in the QV port
228 
232  Q_REQUIRE_ID(500,
233  (0U < prio) && (prio <= QF_MAX_ACTIVE)
234  && (stkSto == nullptr));
235 
236  m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO
237  m_prio = static_cast<std::uint8_t>(prio); // set the QF prio of this AO
238 
239  QF::add_(this); // make QF aware of this AO
240 
241  this->init(par, m_prio); // take the top-most initial tran. (virtual)
242  QS_FLUSH(); // flush the trace buffer to the host
243 }
244 
245 } // namespace QP
246 
unsigned int uint_fast16_t
Definition: 16bit/stdint.h:38
unsigned char uint8_t
Definition: 16bit/stdint.h:29
unsigned int uint_fast8_t
Definition: 16bit/stdint.h:36
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)
Definition: qk.cpp:173
static void onStartup(void)
Startup QF callback.
friend class QActive
Definition: qf.hpp:617
static void init(void)
QF initialization.
Definition: qk.cpp:78
static void onCleanup(void)
Cleanup QF callback.
static int_t run(void)
Transfers control to QF to run the application.
Definition: qk.cpp:137
static QTimeEvt timeEvtHead_[QF_MAX_TICK_RATE]
heads of linked lists of time events, one for every clock tick rate
Definition: qf.hpp:615
static void gc(QEvt const *const e) noexcept
Recycle a dynamic event.
Definition: qf_dyn.cpp:219
static void bzero(void *const start, std::uint_fast16_t const len) noexcept
Clear a specified region of memory to zero.
Definition: qf_act.cpp:129
static void add_(QActive *const a) noexcept
Register an active object to be managed by the framework.
Definition: qf_act.cpp:79
static void stop(void)
Definition: qk.cpp:111
static QActive * active_[QF_MAX_ACTIVE+1U]
array of registered active objects
Definition: qf.hpp:580
static void onIdle(void)
Definition: struct.dox:1
@ QS_QF_RUN
QF_run() was entered.
Definition: qs.hpp:162
@ QS_SCHED_IDLE
scheduler became idle
Definition: qs.hpp:141
@ QS_SCHED_NEXT
scheduler found next task to execute
Definition: qs.hpp:140
QPSet QV_readySet_
Definition: qv.cpp:66
enum_t QF_maxPubSignal_
the maximum published signal
Definition: qf_ps.cpp:58
std::uint_fast8_t QF_maxPool_
Definition: qf_dyn.cpp:55
QSubscrList * QF_subscrList_
the subscriber list array
Definition: qf_ps.cpp:57
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Definition: qassert.h:120
int int_t
Definition: qassert.h:86
#define Q_REQUIRE_ID(id_, test_)
Definition: qassert.h:279
Internal (package scope) QF/C++ interface.
#define QF_INT_DISABLE()
Definition: qk/qf_port.hpp:43
#define QF_INT_ENABLE()
Definition: qk/qf_port.hpp:44
#define QS_TIME_PRE_()
Definition: qs.hpp:266
#define QS_FLUSH()
Definition: qs.hpp:1049
Dummy definitions of the QS macros that avoid code generation from the QS instrumentation.
#define QS_U8_PRE_(data_)
Definition: qs_dummy.hpp:100
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Definition: qs_dummy.hpp:98
#define QS_END_NOCRIT_PRE_()
Definition: qs_dummy.hpp:99
#define QS_2U8_PRE_(data1_, data2_)
Definition: qs_dummy.hpp:101
Internal (package scope) QS/C++ interface.
QS/C++ port to a 32-bit CPU, generic compiler.
#define QF_MAX_ACTIVE
Definition: qxk/qf_port.hpp:57
void rmove(std::uint_fast8_t const n) noexcept
Definition: qpset.hpp:109
bool notEmpty(void) const noexcept
Evaluates to true if the priority set is not empty.
Definition: qpset.hpp:91
std::uint_fast8_t findMax(void) const noexcept
Definition: qpset.hpp:114