QP-nano  6.9.0
Real-Time Embedded Framework
qfn.c
Go to the documentation of this file.
1
40#include "qpn_conf.h" /* QP-nano configuration file (from the application) */
41#include "qfn_port.h" /* QF-nano port from the port directory */
42#include "qassert.h" /* embedded systems-friendly assertions */
43
45
46/* Global-scope objects *****************************************************/
47
48
53uint_fast8_t QF_maxActive_;
54
65uint_fast8_t volatile QF_readySet_;
66
67#ifdef QF_TIMEEVT_USAGE
85uint_fast8_t volatile QF_timerSetX_[QF_MAX_TICK_RATE];
86#endif
87
88#ifndef QF_LOG2
89uint8_t const Q_ROM QF_log2Lkup[16] = {
90 0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U,
91 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U
92};
93#endif /* QF_LOG2 */
94
95/****************************************************************************/
99void QActive_ctor(QActive * const me, QStateHandler initial) {
100 static QActiveVtable const vtable = { /* QActive virtual table */
101 { &QHsm_init_,
105 };
106
116 QHsm_ctor(&me->super, initial);
117 me->super.vptr = &vtable.super; /* hook the vptr to QActive vtable */
118}
119
120/****************************************************************************/
142#if (Q_PARAM_SIZE != 0U)
143bool QActive_postX_(QActive * const me, uint_fast8_t margin,
144 enum_t const sig, QParam const par)
145#else
146bool QActive_postX_(QActive * const me, uint_fast8_t margin,
147 enum_t const sig)
148#endif
149{
150 QActiveCB const Q_ROM *acb = &QF_active[me->prio];
151 uint_fast8_t qlen = Q_ROM_BYTE(acb->qlen);
152 bool can_post;
153
154 QF_INT_DISABLE();
155
156 if (margin == QF_NO_MARGIN) {
157 if (qlen > (uint_fast8_t)me->nUsed) {
158 can_post = true; /* can post */
159 }
160 else {
161 can_post = false; /* cannot post */
162#ifndef Q_NASSERT
163 QF_INT_ENABLE();
164 /* must be able to post event : Q_ERROR_ID(310) */
165 Q_onAssert(Q_this_module_, 310);
166#endif
167 }
168 }
169 else if ((qlen - (uint_fast8_t)me->nUsed) > margin) {
170 can_post = true; /* can post */
171 }
172 else {
173 can_post = false; /* cannot post */
174 }
175
176 if (can_post) { /* can post the event? */
177 /* insert event into the ring buffer (FIFO) */
178 QF_ROM_QUEUE_AT_(acb, me->head).sig = (QSignal)sig;
179#if (Q_PARAM_SIZE != 0U)
180 QF_ROM_QUEUE_AT_(acb, me->head).par = par;
181#endif
182 if (me->head == 0U) {
183 me->head = (uint8_t)qlen; /* wrap the head */
184 }
185 --me->head;
186 ++me->nUsed;
187
188 /* is this the first event? */
189 if (me->nUsed == 1U) {
190
191 /* set the corresponding bit in the ready set */
192 QF_readySet_ |= (uint_fast8_t)1 << (me->prio - 1U);
193
194#ifdef qkn_h
195 if (QK_sched_() != 0U) {
196 QK_activate_(); /* activate the next active object */
197 }
198#endif
199 }
200 }
201 QF_INT_ENABLE();
202
203 return can_post;
204}
205
206/****************************************************************************/
228#if (Q_PARAM_SIZE != 0U)
229bool QActive_postXISR_(QActive * const me, uint_fast8_t margin,
230 enum_t const sig, QParam const par)
231#else
232bool QActive_postXISR_(QActive * const me, uint_fast8_t margin,
233 enum_t const sig)
234#endif
235{
236#ifdef QF_ISR_NEST
237#ifdef QF_ISR_STAT_TYPE
238 QF_ISR_STAT_TYPE stat;
239#endif
240#endif
241 QActiveCB const Q_ROM *acb = &QF_active[me->prio];
242 uint_fast8_t qlen = Q_ROM_BYTE(acb->qlen);
243 bool can_post;
244
245#ifdef QF_ISR_NEST
246#ifdef QF_ISR_STAT_TYPE
247 QF_ISR_DISABLE(stat);
248#else
249 QF_INT_DISABLE();
250#endif
251#endif
252
253 if (margin == QF_NO_MARGIN) {
254 if (qlen > (uint_fast8_t)me->nUsed) {
255 can_post = true; /* can post */
256 }
257 else {
258 can_post = false; /* cannot post */
259#ifndef Q_NASSERT
260 QF_INT_ENABLE();
261 /* must be able to post event : Q_ERROR_ID(410) */
262 Q_onAssert(Q_this_module_, 410);
263#endif
264 }
265 }
266 else if ((qlen - (uint_fast8_t)me->nUsed) > margin) {
267 can_post = true; /* can post */
268 }
269 else {
270 can_post = false; /* cannot post */
271 }
272
273 if (can_post) { /* can post the event? */
274 /* insert event into the ring buffer (FIFO) */
275 QF_ROM_QUEUE_AT_(acb, me->head).sig = (QSignal)sig;
276#if (Q_PARAM_SIZE != 0U)
277 QF_ROM_QUEUE_AT_(acb, me->head).par = par;
278#endif
279 if (me->head == 0U) {
280 me->head = (uint8_t)qlen; /* wrap the head */
281 }
282 --me->head;
283 ++me->nUsed;
284 /* is this the first event? */
285 if (me->nUsed == 1U) {
286 /* set the bit */
287 QF_readySet_ |= (uint_fast8_t)1 << (me->prio - 1U);
288 }
289 }
290
291#ifdef QF_ISR_NEST
292#ifdef QF_ISR_STAT_TYPE
293 QF_ISR_RESTORE(stat);
294#else
295 QF_INT_ENABLE();
296#endif
297#endif
298
299 return can_post;
300}
301
302/****************************************************************************/
315void QF_init(uint_fast8_t maxActive) {
316 QActive *a;
317 uint_fast8_t p;
318 uint_fast8_t n;
319
321 Q_REQUIRE_ID(100, (1U < maxActive)
322 && (maxActive <= 9U));
323 QF_maxActive_ = (uint_fast8_t)maxActive - 1U;
324
325#ifdef QF_TIMEEVT_USAGE
326 for (n = 0U; n < (uint_fast8_t)QF_MAX_TICK_RATE; ++n) {
327 QF_timerSetX_[n] = 0U;
328 }
329#endif /* QF_TIMEEVT_USAGE */
330
331 QF_readySet_ = 0U;
332
333#ifdef qkn_h
334 QK_attr_.actPrio = 8U; /* QK-nano scheduler locked */
335
336#ifdef QF_ISR_NEST
337 QK_attr_.intNest = 0U;
338#endif
339
340#ifdef QK_SCHED_LOCK
341 QK_attr_.lockPrio = 0U;
342 QK_attr_.lockHolder = 0U;
343#endif
344
345#endif /* #ifdef qkn_h */
346
347 /* clear all registered active objects... */
348 for (p = 1U; p <= QF_maxActive_; ++p) {
349 a = QF_ROM_ACTIVE_GET_(p);
350
351 /* QF_active[p] must be initialized */
352 Q_ASSERT_ID(110, a != (QActive *)0);
353
354 a->head = 0U;
355 a->tail = 0U;
356 a->nUsed = 0U;
357#if (QF_TIMEEVT_CTR_SIZE != 0U)
358 for (n = 0U; n < (uint_fast8_t)QF_MAX_TICK_RATE; ++n) {
359 a->tickCtr[n].nTicks = 0U;
360#ifdef QF_TIMEEVT_PERIODIC
361 a->tickCtr[n].interval = 0U;
362#endif /* def QF_TIMEEVT_PERIODIC */
363 }
364#endif /* (QF_TIMEEVT_CTR_SIZE != 0U) */
365 }
366
367#ifdef QV_INIT /* initialization of the QV-nano kernel defined? */
368 QV_INIT(); /* port-specific initialization of the QV-nano kernel */
369#elif defined QK_INIT /* initialization of the QK-nano kernel defined? */
370 QK_INIT(); /* port-specific initialization of the QK-nano kernel */
371#endif
372}
373
374/****************************************************************************/
375/****************************************************************************/
376#if (QF_TIMEEVT_CTR_SIZE != 0U)
377
378/****************************************************************************/
398void QF_tickXISR(uint_fast8_t const tickRate) {
399 uint_fast8_t p = QF_maxActive_;
400 do {
402 QTimer *t = &a->tickCtr[tickRate];
403
404 if (t->nTicks != 0U) {
405 --t->nTicks;
406 if (t->nTicks == 0U) {
407
408#ifdef QF_TIMEEVT_PERIODIC
409 if (t->interval != 0U) {
410 t->nTicks = t->interval; /* re-arm the periodic timer */
411 }
412#endif /* QF_TIMEEVT_PERIODIC */
413
414#ifdef QF_TIMEEVT_USAGE
415 QF_timerSetX_[tickRate] &= (uint_fast8_t)(~(1U << (p - 1U)));
416#endif /* QF_TIMEEVT_USAGE */
417
418#if (Q_PARAM_SIZE != 0)
420 0U);
421#else
423#endif /* (Q_PARAM_SIZE != 0U) */
424 }
425 }
426 --p;
427 } while (p != 0U);
428}
429
430/****************************************************************************/
461#ifdef QF_TIMEEVT_PERIODIC
462void QActive_armX(QActive * const me, uint_fast8_t const tickRate,
463 QTimeEvtCtr const nTicks, QTimeEvtCtr const interval)
464#else
465void QActive_armX(QActive * const me, uint_fast8_t const tickRate,
466 QTimeEvtCtr const nTicks)
467#endif
468{
469 QF_INT_DISABLE();
470 me->tickCtr[tickRate].nTicks = nTicks;
471#ifdef QF_TIMEEVT_PERIODIC
472 me->tickCtr[tickRate].interval = interval;
473#endif /* QF_TIMEEVT_PERIODIC */
474
475#ifdef QF_TIMEEVT_USAGE
476 /* set a bit in QF_timerSetX_[] to rememer that the timer is running */
477 QF_timerSetX_[tickRate] |= (uint_fast8_t)1 << (me->prio - 1U);
478#endif
479 QF_INT_ENABLE();
480}
481
482/****************************************************************************/
495void QActive_disarmX(QActive * const me, uint_fast8_t const tickRate) {
496 QF_INT_DISABLE();
497 me->tickCtr[tickRate].nTicks = 0U;
498#ifdef QF_TIMEEVT_PERIODIC
499 me->tickCtr[tickRate].interval = 0U;
500#endif /* QF_TIMEEVT_PERIODIC */
501
502#ifdef QF_TIMEEVT_USAGE
503 /* clear a bit in QF_timerSetX_[] to rememer that timer is not running */
504 QF_timerSetX_[tickRate] &= (uint_fast8_t)(~(1U << (me->prio - 1U)));
505#endif
506 QF_INT_ENABLE();
507}
508#endif /* #if (QF_TIMEEVT_CTR_SIZE != 0U) */
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Definition: qassert.h:125
#define Q_ROM
Definition: qassert.h:90
#define Q_ASSERT_ID(id_, test_)
Definition: qassert.h:160
#define Q_REQUIRE_ID(id_, test_)
Definition: qassert.h:284
Q_NORETURN Q_onAssert(char_t const Q_ROM *const module, int_t const location)
uint8_t QSignal
Definition: qepn.h:93
uint16_t QParam
Definition: qepn.h:103
#define Q_ROM_BYTE(rom_var_)
Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do not generate correct code for a...
Definition: qepn.h:454
QState(* QStateHandler)(void *const me)
Definition: qepn.h:158
int enum_t
Definition: qepn.h:76
#define Q_TIMEOUT_SIG
Definition: qepn.h:391
void QF_init(uint_fast8_t maxActive)
Definition: qfn.c:315
uint_fast8_t volatile QF_readySet_
Definition: qfn.c:65
uint_fast8_t QF_maxActive_
Definition: qfn.c:53
void QF_tickXISR(uint_fast8_t const tickRate)
Definition: qfn.c:398
uint8_t const Q_ROM QF_log2Lkup[16]
Definition: qfn.c:89
uint_fast8_t volatile QF_timerSetX_[QF_MAX_TICK_RATE]
Definition: qfn.c:85
QActiveCB const Q_ROM QF_active[]
active object control blocks
#define QF_ROM_QUEUE_AT_(ao_, i_)
Definition: qfn.h:442
#define QF_MAX_TICK_RATE
Definition: qfn.h:94
#define QF_NO_MARGIN
Definition: qfn.h:181
uint16_t QTimeEvtCtr
Definition: qfn.h:75
QTimeEvtCtr interval
Definition: qfn.h:87
#define QF_ROM_ACTIVE_GET_(p_)
Definition: qfn.h:448
QTimeEvtCtr nTicks
Definition: qfn.h:85
#define QACTIVE_POST_ISR(me_, sig_, par_)
Definition: qfn.h:250
Definition: qfn.h:397
Definition: qfn.h:84
uint8_t volatile lockPrio
Definition: qkn.h:48
uint_fast8_t QK_sched_(void)
Definition: qkn.c:247
void QK_activate_(void)
Definition: qkn.c:291
QK_PrivAttr QK_attr_
Definition: qkn.c:52
uint8_t volatile actPrio
Definition: qkn.h:46
uint8_t volatile intNest
Definition: qkn.h:50
uint8_t volatile lockHolder
Definition: qkn.h:49
Definition: qfn.h:122
void QActive_ctor(QActive *const me, QStateHandler initial)
Definition: qfn.c:99
uint8_t volatile nUsed
Definition: qfn.h:142
QHsm super
derives from the QHsm base class
Definition: qfn.h:123
bool QActive_postX_(QActive *const me, uint_fast8_t margin, enum_t const sig, QParam const par)
Definition: qfn.c:143
uint8_t volatile head
Definition: qfn.h:134
uint8_t prio
Definition: qfn.h:131
void QActive_disarmX(QActive *const me, uint_fast8_t const tickRate)
Definition: qfn.c:495
uint8_t volatile tail
Definition: qfn.h:137
void QActive_armX(QActive *const me, uint_fast8_t const tickRate, QTimeEvtCtr const nTicks, QTimeEvtCtr const interval)
Definition: qfn.c:462
QTimer tickCtr[QF_MAX_TICK_RATE]
Definition: qfn.h:127
bool QActive_postXISR_(QActive *const me, uint_fast8_t margin, enum_t const sig, QParam const par)
Definition: qfn.c:229
QHsmVtable super
Definition: qfn.h:150
void QHsm_ctor(QHsm *const me, QStateHandler initial)
Definition: qepn.c:84
QHsmVtable const * vptr
Definition: qepn.h:184
void QHsm_init_(QHsm *const me)
Definition: qepn.c:105
void QHsm_dispatch_(QHsm *const me)
Definition: qepn.c:190