QP/C++  7.3.3
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qs_rx.cpp
Go to the documentation of this file.
1//$file${src::qs::qs_rx.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpcpp.qm
4// File: ${src::qs::qs_rx.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::qs::qs_rx.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qs_port.hpp" // QS port
45#include "qs_pkg.hpp" // QS package-scope internal interface
46#include "qp_pkg.hpp" // QP package-scope interface
47#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
48
49//============================================================================
50//! @cond INTERNAL
51
52namespace { // unnamed local namespace
53
54Q_DEFINE_THIS_MODULE("qs_rx")
55
56enum RxStateEnum : std::uint8_t {
57 ERROR_STATE,
58 WAIT4_SEQ,
59 WAIT4_REC,
60 WAIT4_INFO_FRAME,
61 WAIT4_CMD_ID,
62 WAIT4_CMD_PARAM1,
63 WAIT4_CMD_PARAM2,
64 WAIT4_CMD_PARAM3,
65 WAIT4_CMD_FRAME,
66 WAIT4_RESET_FRAME,
67 WAIT4_TICK_RATE,
68 WAIT4_TICK_FRAME,
69 WAIT4_PEEK_OFFS,
70 WAIT4_PEEK_SIZE,
71 WAIT4_PEEK_NUM,
72 WAIT4_PEEK_FRAME,
73 WAIT4_POKE_OFFS,
74 WAIT4_POKE_SIZE,
75 WAIT4_POKE_NUM,
76 WAIT4_POKE_DATA,
77 WAIT4_POKE_FRAME,
78 WAIT4_FILL_DATA,
79 WAIT4_FILL_FRAME,
80 WAIT4_FILTER_LEN,
81 WAIT4_FILTER_DATA,
82 WAIT4_FILTER_FRAME,
83 WAIT4_OBJ_KIND,
84 WAIT4_OBJ_ADDR,
85 WAIT4_OBJ_FRAME,
86 WAIT4_QUERY_KIND,
87 WAIT4_QUERY_FRAME,
88 WAIT4_EVT_PRIO,
89 WAIT4_EVT_SIG,
90 WAIT4_EVT_LEN,
91 WAIT4_EVT_PAR,
92 WAIT4_EVT_FRAME
93
94#ifdef Q_UTEST
95 ,
96 WAIT4_TEST_SETUP_FRAME,
97 WAIT4_TEST_TEARDOWN_FRAME,
98 WAIT4_TEST_PROBE_DATA,
99 WAIT4_TEST_PROBE_ADDR,
100 WAIT4_TEST_PROBE_FRAME,
101 WAIT4_TEST_CONTINUE_FRAME
102#endif // Q_UTEST
103};
104
105// internal helper functions...
106static void rxParseData_(std::uint8_t const b) noexcept;
107static void rxHandleGoodFrame_(std::uint8_t const state);
108static void rxHandleBadFrame_(std::uint8_t const state) noexcept;
109static void rxReportAck_(enum QP::QSpyRxRecords const recId) noexcept;
110static void rxReportError_(std::uint8_t const code) noexcept;
111static void rxReportDone_(enum QP::QSpyRxRecords const recId) noexcept;
112static void queryCurrObj_(std::uint8_t obj_kind) noexcept;
113static void rxPoke_() noexcept;
114
115// Internal QS-RX function to take a tran. in the QS-RX FSM
116static inline void tran_(RxStateEnum const target) noexcept {
117 QP::QS::rxPriv_.state = static_cast<std::uint8_t>(target);
118}
119
120} // unnamed namespace
121
122#ifndef QF_MEM_ISOLATE
123namespace QP {
124namespace QS {
125RxAttr rxPriv_;
126} // namespace QS
127} // namespace QP
128#endif // QF_MEM_ISOLATE
129
130//! @endcond
131//============================================================================
132
133//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
134// Check for the minimum required QP version
135#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
136#error qpcpp version 7.3.0 or higher required
137#endif
138//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
139
140//$define${QS::QS-RX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
141namespace QP {
142namespace QS {
143
144//${QS::QS-RX::rxInitBuf} ....................................................
146 std::uint8_t * const sto,
147 std::uint16_t const stoSize) noexcept
148{
149 rxPriv_.buf = &sto[0];
150 rxPriv_.end = static_cast<QSCtr>(stoSize);
151 rxPriv_.head = 0U;
152 rxPriv_.tail = 0U;
153
154 rxPriv_.currObj[QS::SM_OBJ] = nullptr;
155 rxPriv_.currObj[QS::AO_OBJ] = nullptr;
156 rxPriv_.currObj[QS::MP_OBJ] = nullptr;
157 rxPriv_.currObj[QS::EQ_OBJ] = nullptr;
158 rxPriv_.currObj[QS::TE_OBJ] = nullptr;
159 rxPriv_.currObj[QS::AP_OBJ] = nullptr;
160
161 tran_(WAIT4_SEQ);
162 QP::QS::rxPriv_.esc = 0U;
163 QP::QS::rxPriv_.seq = 0U;
164 QP::QS::rxPriv_.chksum = 0U;
165
166 beginRec_(static_cast<std::uint_fast8_t>(QS_OBJ_DICT));
167 QS_OBJ_PRE_(&rxPriv_);
168 QS_STR_PRE_("QS_RX");
169 endRec_();
170 // no QS_REC_DONE(), because QS is not running yet
171
172 #ifdef Q_UTEST
173 tstPriv_.tpNum = 0U;
174 tstPriv_.testTime = 0U;
175 #endif // Q_UTEST
176}
177
178//${QS::QS-RX::rxParse} ......................................................
179void rxParse() {
180 QSCtr tail = rxPriv_.tail;
181 while (rxPriv_.head != tail) { // QS-RX buffer NOT empty?
182 std::uint8_t b = rxPriv_.buf[tail];
183
184 ++tail;
185 if (tail == rxPriv_.end) {
186 tail = 0U;
187 }
188 rxPriv_.tail = tail; // update the tail to a *valid* index
189
190 if (QP::QS::rxPriv_.esc != 0U) { // escaped byte arrived?
191 QP::QS::rxPriv_.esc = 0U;
192 b ^= QS_ESC_XOR;
193
194 QP::QS::rxPriv_.chksum += b;
195 rxParseData_(b);
196 }
197 else if (b == QS_ESC) {
198 QP::QS::rxPriv_.esc = 1U;
199 }
200 else if (b == QS_FRAME) {
201 // get ready for the next frame
202 b = QP::QS::rxPriv_.state; // save the current state in b
203 QP::QS::rxPriv_.esc = 0U;
204 tran_(WAIT4_SEQ);
205
206 if (QP::QS::rxPriv_.chksum == QS_GOOD_CHKSUM) {
207 QP::QS::rxPriv_.chksum = 0U;
208 rxHandleGoodFrame_(b);
209 }
210 else { // bad checksum
211 QP::QS::rxPriv_.chksum = 0U;
212 rxReportError_(0x41U);
213 rxHandleBadFrame_(b);
214 }
215 }
216 else {
217 QP::QS::rxPriv_.chksum += b;
218 rxParseData_(b);
219 }
220 }
221}
222
223//${QS::QS-RX::setCurrObj} ...................................................
225 std::uint8_t const obj_kind,
226 void * const obj_ptr)
227{
230 Q_REQUIRE_INCRIT(300, obj_kind < Q_DIM(rxPriv_.currObj));
231
232 QS_MEM_SYS();
233
234 rxPriv_.currObj[obj_kind] = obj_ptr;
235
236 QS_MEM_APP();
237 QS_CRIT_EXIT();
238}
239
240//${QS::QS-RX::rxGetNfree} ...................................................
241std::uint16_t rxGetNfree() noexcept {
242 // NOTE: Must be called IN critical section.
243 // Also requires system-level memory access (QF_MEM_SYS()).
244
245 QSCtr const head = rxPriv_.head;
246 std::uint16_t nFree;
247 if (head == rxPriv_.tail) { // buffer empty?
248 nFree = static_cast<std::uint16_t>(rxPriv_.end - 1U);
249 }
250 else if (head < rxPriv_.tail) {
251 nFree = static_cast<std::uint16_t>(rxPriv_.tail - head - 1U);
252 }
253 else {
254 nFree = static_cast<std::uint16_t>(rxPriv_.end + rxPriv_.tail
255 - head - 1U);
256 }
257 return nFree;
258}
259
260} // namespace QS
261} // namespace QP
262//$enddef${QS::QS-RX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
263
264//============================================================================
265//! @cond INTERNAL
266namespace { // unnamed local namespace
267
268//............................................................................
269static void rxParseData_(std::uint8_t const b) noexcept {
270 switch (QP::QS::rxPriv_.state) {
271 case WAIT4_SEQ: {
272 ++QP::QS::rxPriv_.seq;
273 if (QP::QS::rxPriv_.seq != b) { // not the expected sequence?
274 rxReportError_(0x42U);
275 QP::QS::rxPriv_.seq = b; // update the sequence
276 }
277 tran_(WAIT4_REC);
278 break;
279 }
280 case WAIT4_REC: {
281 switch (b) {
282 case QP::QS_RX_INFO:
283 tran_(WAIT4_INFO_FRAME);
284 break;
285 case QP::QS_RX_COMMAND:
286 tran_(WAIT4_CMD_ID);
287 break;
288 case QP::QS_RX_RESET:
289 tran_(WAIT4_RESET_FRAME);
290 break;
291 case QP::QS_RX_TICK:
292 tran_(WAIT4_TICK_RATE);
293 break;
294 case QP::QS_RX_PEEK:
295 if (QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ] != nullptr) {
296 QP::QS::rxPriv_.var.peek.offs = 0U;
297 QP::QS::rxPriv_.var.peek.idx = 0U;
298 tran_(WAIT4_PEEK_OFFS);
299 }
300 else {
301 rxReportError_(
302 static_cast<std::uint8_t>(QP::QS_RX_PEEK));
303 tran_(ERROR_STATE);
304 }
305 break;
306 case QP::QS_RX_POKE:
307 case QP::QS_RX_FILL:
308 QP::QS::rxPriv_.var.poke.fill =
309 (b == static_cast<std::uint8_t>(QP::QS_RX_FILL))
310 ? 1U : 0U;
311 if (QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ] != nullptr) {
312 QP::QS::rxPriv_.var.poke.offs = 0U;
313 QP::QS::rxPriv_.var.poke.idx = 0U;
314 tran_(WAIT4_POKE_OFFS);
315 }
316 else {
317 rxReportError_(
318 (QP::QS::rxPriv_.var.poke.fill != 0U)
319 ? static_cast<std::uint8_t>(QP::QS_RX_FILL)
320 : static_cast<std::uint8_t>(QP::QS_RX_POKE));
321 tran_(ERROR_STATE);
322 }
323 break;
324 case QP::QS_RX_GLB_FILTER: // intentionally fall-through
325 case QP::QS_RX_LOC_FILTER:
326 QP::QS::rxPriv_.var.flt.recId = b;
327 tran_(WAIT4_FILTER_LEN);
328 break;
329 case QP::QS_RX_AO_FILTER: // intentionally fall-through
330 case QP::QS_RX_CURR_OBJ:
331 QP::QS::rxPriv_.var.obj.recId = b;
332 tran_(WAIT4_OBJ_KIND);
333 break;
334 case QP::QS_RX_QUERY_CURR:
335 QP::QS::rxPriv_.var.obj.recId =
336 static_cast<std::uint8_t>(QP::QS_RX_QUERY_CURR);
337 tran_(WAIT4_QUERY_KIND);
338 break;
339 case QP::QS_RX_EVENT:
340 tran_(WAIT4_EVT_PRIO);
341 break;
342
343#ifdef Q_UTEST
344 case QP::QS_RX_TEST_SETUP:
345 tran_(WAIT4_TEST_SETUP_FRAME);
346 break;
347 case QP::QS_RX_TEST_TEARDOWN:
348 tran_(WAIT4_TEST_TEARDOWN_FRAME);
349 break;
350 case QP::QS_RX_TEST_CONTINUE:
351 tran_(WAIT4_TEST_CONTINUE_FRAME);
352 break;
353 case QP::QS_RX_TEST_PROBE:
354 if (QP::QS::tstPriv_.tpNum
355 < static_cast<std::uint8_t>(
356 (sizeof(QP::QS::tstPriv_.tpBuf)
357 / sizeof(QP::QS::tstPriv_.tpBuf[0]))))
358 {
359 QP::QS::rxPriv_.var.tp.data = 0U;
360 QP::QS::rxPriv_.var.tp.idx = 0U;
361 tran_(WAIT4_TEST_PROBE_DATA);
362 }
363 else { // the # Test-Probes exceeded
364 rxReportError_(
365 static_cast<std::uint8_t>(QP::QS_RX_TEST_PROBE));
366 tran_(ERROR_STATE);
367 }
368 break;
369#endif // Q_UTEST
370
371 default:
372 rxReportError_(0x43U);
373 tran_(ERROR_STATE);
374 break;
375 }
376 break;
377 }
378 case WAIT4_INFO_FRAME: {
379 // keep ignoring the data until a frame is collected
380 break;
381 }
382 case WAIT4_CMD_ID: {
383 QP::QS::rxPriv_.var.cmd.cmdId = b;
384 QP::QS::rxPriv_.var.cmd.idx = 0U;
385 QP::QS::rxPriv_.var.cmd.param1 = 0U;
386 QP::QS::rxPriv_.var.cmd.param2 = 0U;
387 QP::QS::rxPriv_.var.cmd.param3 = 0U;
388 tran_(WAIT4_CMD_PARAM1);
389 break;
390 }
391 case WAIT4_CMD_PARAM1: {
392 QP::QS::rxPriv_.var.cmd.param1 |=
393 (static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.cmd.idx);
394 QP::QS::rxPriv_.var.cmd.idx += 8U;
395 if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) {
396 QP::QS::rxPriv_.var.cmd.idx = 0U;
397 tran_(WAIT4_CMD_PARAM2);
398 }
399 break;
400 }
401 case WAIT4_CMD_PARAM2: {
402 QP::QS::rxPriv_.var.cmd.param2 |=
403 static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.cmd.idx;
404 QP::QS::rxPriv_.var.cmd.idx += 8U;
405 if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) {
406 QP::QS::rxPriv_.var.cmd.idx = 0U;
407 tran_(WAIT4_CMD_PARAM3);
408 }
409 break;
410 }
411 case WAIT4_CMD_PARAM3: {
412 QP::QS::rxPriv_.var.cmd.param3 |=
413 static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.cmd.idx;
414 QP::QS::rxPriv_.var.cmd.idx += 8U;
415 if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) {
416 QP::QS::rxPriv_.var.cmd.idx = 0U;
417 tran_(WAIT4_CMD_FRAME);
418 }
419 break;
420 }
421 case WAIT4_CMD_FRAME: {
422 // keep ignoring the data until a frame is collected
423 break;
424 }
425 case WAIT4_RESET_FRAME: {
426 // keep ignoring the data until a frame is collected
427 break;
428 }
429 case WAIT4_TICK_RATE: {
430 QP::QS::rxPriv_.var.tick.rate = static_cast<std::uint_fast8_t>(b);
431 tran_(WAIT4_TICK_FRAME);
432 break;
433 }
434 case WAIT4_TICK_FRAME: {
435 // keep ignoring the data until a frame is collected
436 break;
437 }
438 case WAIT4_PEEK_OFFS: {
439 if (QP::QS::rxPriv_.var.peek.idx == 0U) {
440 QP::QS::rxPriv_.var.peek.offs = static_cast<std::uint16_t>(b);
441 QP::QS::rxPriv_.var.peek.idx += 8U;
442 }
443 else {
444 QP::QS::rxPriv_.var.peek.offs |= static_cast<std::uint16_t>(
445 static_cast<std::uint16_t>(b) << 8U);
446 tran_(WAIT4_PEEK_SIZE);
447 }
448 break;
449 }
450 case WAIT4_PEEK_SIZE: {
451 if ((b == 1U) || (b == 2U) || (b == 4U)) {
452 QP::QS::rxPriv_.var.peek.size = b;
453 tran_(WAIT4_PEEK_NUM);
454 }
455 else {
456 rxReportError_(static_cast<std::uint8_t>(QP::QS_RX_PEEK));
457 tran_(ERROR_STATE);
458 }
459 break;
460 }
461 case WAIT4_PEEK_NUM: {
462 QP::QS::rxPriv_.var.peek.num = b;
463 tran_(WAIT4_PEEK_FRAME);
464 break;
465 }
466 case WAIT4_PEEK_FRAME: {
467 // keep ignoring the data until a frame is collected
468 break;
469 }
470 case WAIT4_POKE_OFFS: {
471 if (QP::QS::rxPriv_.var.poke.idx == 0U) {
472 QP::QS::rxPriv_.var.poke.offs = static_cast<std::uint16_t>(b);
473 QP::QS::rxPriv_.var.poke.idx = 1U;
474 }
475 else {
476 QP::QS::rxPriv_.var.poke.offs |= static_cast<std::uint16_t>(
477 static_cast<std::uint16_t>(b) << 8U);
478 tran_(WAIT4_POKE_SIZE);
479 }
480 break;
481 }
482 case WAIT4_POKE_SIZE: {
483 if ((b == 1U) || (b == 2U) || (b == 4U)) {
484 QP::QS::rxPriv_.var.poke.size = b;
485 tran_(WAIT4_POKE_NUM);
486 }
487 else {
488 rxReportError_((QP::QS::rxPriv_.var.poke.fill != 0U)
489 ? static_cast<std::uint8_t>(QP::QS_RX_FILL)
490 : static_cast<std::uint8_t>(QP::QS_RX_POKE));
491 tran_(ERROR_STATE);
492 }
493 break;
494 }
495 case WAIT4_POKE_NUM: {
496 if (b > 0U) {
497 QP::QS::rxPriv_.var.poke.num = b;
498 QP::QS::rxPriv_.var.poke.data = 0U;
499 QP::QS::rxPriv_.var.poke.idx = 0U;
500 tran_((QP::QS::rxPriv_.var.poke.fill != 0U)
501 ? WAIT4_FILL_DATA
502 : WAIT4_POKE_DATA);
503 }
504 else {
505 rxReportError_((QP::QS::rxPriv_.var.poke.fill != 0U)
506 ? static_cast<std::uint8_t>(QP::QS_RX_FILL)
507 : static_cast<std::uint8_t>(QP::QS_RX_POKE));
508 tran_(ERROR_STATE);
509 }
510 break;
511 }
512 case WAIT4_FILL_DATA: {
513 QP::QS::rxPriv_.var.poke.data |=
514 static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.poke.idx;
515 QP::QS::rxPriv_.var.poke.idx += 8U;
516 if ((QP::QS::rxPriv_.var.poke.idx >> 3U) == QP::QS::rxPriv_.var.poke.size) {
517 tran_(WAIT4_FILL_FRAME);
518 }
519 break;
520 }
521 case WAIT4_POKE_DATA: {
522 QP::QS::rxPriv_.var.poke.data |=
523 static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.poke.idx;
524 QP::QS::rxPriv_.var.poke.idx += 8U;
525 if ((QP::QS::rxPriv_.var.poke.idx >> 3U) == QP::QS::rxPriv_.var.poke.size) {
526 rxPoke_();
527 --QP::QS::rxPriv_.var.poke.num;
528 if (QP::QS::rxPriv_.var.poke.num == 0U) {
529 tran_(WAIT4_POKE_FRAME);
530 }
531 }
532 break;
533 }
534 case WAIT4_FILL_FRAME: {
535 // keep ignoring the data until a frame is collected
536 break;
537 }
538 case WAIT4_POKE_FRAME: {
539 // keep ignoring the data until a frame is collected
540 break;
541 }
542 case WAIT4_FILTER_LEN: {
543 if (b == static_cast<std::uint8_t>(sizeof(QP::QS::rxPriv_.var.flt.data))) {
544 QP::QS::rxPriv_.var.flt.idx = 0U;
545 tran_(WAIT4_FILTER_DATA);
546 }
547 else {
548 rxReportError_(QP::QS::rxPriv_.var.flt.recId);
549 tran_(ERROR_STATE);
550 }
551 break;
552 }
553 case WAIT4_FILTER_DATA: {
554 QP::QS::rxPriv_.var.flt.data[QP::QS::rxPriv_.var.flt.idx] = b;
555 ++QP::QS::rxPriv_.var.flt.idx;
556 if (QP::QS::rxPriv_.var.flt.idx == sizeof(QP::QS::rxPriv_.var.flt.data)) {
557 tran_(WAIT4_FILTER_FRAME);
558 }
559 break;
560 }
561 case WAIT4_FILTER_FRAME: {
562 // keep ignoring the data until a frame is collected
563 break;
564 }
565 case WAIT4_OBJ_KIND: {
566 if (b <= static_cast<std::uint8_t>(QP::QS::SM_AO_OBJ)) {
567 QP::QS::rxPriv_.var.obj.kind = b;
568 QP::QS::rxPriv_.var.obj.addr = 0U;
569 QP::QS::rxPriv_.var.obj.idx = 0U;
570 tran_(WAIT4_OBJ_ADDR);
571 }
572 else {
573 rxReportError_(QP::QS::rxPriv_.var.obj.recId);
574 tran_(ERROR_STATE);
575 }
576 break;
577 }
578 case WAIT4_OBJ_ADDR: {
579 QP::QS::rxPriv_.var.obj.addr |=
580 static_cast<QP::QSObj>(b) << QP::QS::rxPriv_.var.obj.idx;
581 QP::QS::rxPriv_.var.obj.idx += 8U;
582 if (QP::QS::rxPriv_.var.obj.idx
583 == (8U * static_cast<unsigned>(QS_OBJ_PTR_SIZE)))
584 {
585 tran_(WAIT4_OBJ_FRAME);
586 }
587 break;
588 }
589 case WAIT4_OBJ_FRAME: {
590 // keep ignoring the data until a frame is collected
591 break;
592 }
593 case WAIT4_QUERY_KIND: {
594 if (b < static_cast<std::uint8_t>(QP::QS::MAX_OBJ)) {
595 QP::QS::rxPriv_.var.obj.kind = b;
596 tran_(WAIT4_QUERY_FRAME);
597 }
598 else {
599 rxReportError_(QP::QS::rxPriv_.var.obj.recId);
600 tran_(ERROR_STATE);
601 }
602 break;
603 }
604 case WAIT4_QUERY_FRAME: {
605 // keep ignoring the data until a frame is collected
606 break;
607 }
608 case WAIT4_EVT_PRIO: {
609 QP::QS::rxPriv_.var.evt.prio = b;
610 QP::QS::rxPriv_.var.evt.sig = 0U;
611 QP::QS::rxPriv_.var.evt.idx = 0U;
612 tran_(WAIT4_EVT_SIG);
613 break;
614 }
615 case WAIT4_EVT_SIG: {
616 QP::QS::rxPriv_.var.evt.sig |= static_cast<QP::QSignal>(
617 static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.evt.idx);
618 QP::QS::rxPriv_.var.evt.idx += 8U;
619 if (QP::QS::rxPriv_.var.evt.idx
620 == (8U *static_cast<unsigned>(Q_SIGNAL_SIZE)))
621 {
622 QP::QS::rxPriv_.var.evt.len = 0U;
623 QP::QS::rxPriv_.var.evt.idx = 0U;
624 tran_(WAIT4_EVT_LEN);
625 }
626 break;
627 }
628 case WAIT4_EVT_LEN: {
629 QP::QS::rxPriv_.var.evt.len |= static_cast<std::uint16_t>(
630 static_cast<unsigned>(b) << QP::QS::rxPriv_.var.evt.idx);
631 QP::QS::rxPriv_.var.evt.idx += 8U;
632 if (QP::QS::rxPriv_.var.evt.idx == (8U * 2U)) {
633 if ((QP::QS::rxPriv_.var.evt.len + sizeof(QP::QEvt))
635 {
636 // report Ack before generating any other QS records
637 rxReportAck_(QP::QS_RX_EVENT);
638
639 QP::QS::rxPriv_.var.evt.e = QP::QF::newX_(
640 (static_cast<std::uint_fast16_t>(QP::QS::rxPriv_.var.evt.len)
641 + sizeof(QP::QEvt)),
642 0U, // margin
643 static_cast<enum_t>(QP::QS::rxPriv_.var.evt.sig));
644 // event allocated?
645 if (QP::QS::rxPriv_.var.evt.e != nullptr) {
646 QP::QS::rxPriv_.var.evt.p =
647 reinterpret_cast<std::uint8_t *>(QP::QS::rxPriv_.var.evt.e);
648 QP::QS::rxPriv_.var.evt.p = &QP::QS::rxPriv_.var.evt.p[sizeof(QP::QEvt)];
649 if (QP::QS::rxPriv_.var.evt.len > 0U) {
650 tran_(WAIT4_EVT_PAR);
651 }
652 else {
653 tran_(WAIT4_EVT_FRAME);
654 }
655 }
656 else {
657 rxReportError_(
658 static_cast<std::uint8_t>(QP::QS_RX_EVENT));
659 tran_(ERROR_STATE);
660 }
661 }
662 else {
663 rxReportError_(
664 static_cast<std::uint8_t>(QP::QS_RX_EVENT));
665 tran_(ERROR_STATE);
666 }
667 }
668 break;
669 }
670 case WAIT4_EVT_PAR: { // event parameters
671 *QP::QS::rxPriv_.var.evt.p = b;
672 ++QP::QS::rxPriv_.var.evt.p;
673 --QP::QS::rxPriv_.var.evt.len;
674 if (QP::QS::rxPriv_.var.evt.len == 0U) {
675 tran_(WAIT4_EVT_FRAME);
676 }
677 break;
678 }
679 case WAIT4_EVT_FRAME: {
680 // keep ignoring the data until a frame is collected
681 break;
682 }
683
684#ifdef Q_UTEST
685 case WAIT4_TEST_SETUP_FRAME: {
686 // keep ignoring the data until a frame is collected
687 break;
688 }
689 case WAIT4_TEST_TEARDOWN_FRAME: {
690 // keep ignoring the data until a frame is collected
691 break;
692 }
693 case WAIT4_TEST_CONTINUE_FRAME: {
694 // keep ignoring the data until a frame is collected
695 break;
696 }
697 case WAIT4_TEST_PROBE_DATA: {
698 QP::QS::rxPriv_.var.tp.data |=
699 (static_cast<QP::QSFun>(b) << QP::QS::rxPriv_.var.tp.idx);
700 QP::QS::rxPriv_.var.tp.idx += 8U;
701 if (QP::QS::rxPriv_.var.tp.idx == (8U * sizeof(std::uint32_t))) {
702 QP::QS::rxPriv_.var.tp.addr = 0U;
703 QP::QS::rxPriv_.var.tp.idx = 0U;
704 tran_(WAIT4_TEST_PROBE_ADDR);
705 }
706 break;
707 }
708 case WAIT4_TEST_PROBE_ADDR: {
709 QP::QS::rxPriv_.var.tp.addr |=
710 (static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.tp.idx);
711 QP::QS::rxPriv_.var.tp.idx += 8U;
712 if (QP::QS::rxPriv_.var.tp.idx
713 == (8U * static_cast<unsigned>(QS_FUN_PTR_SIZE)))
714 {
715 tran_(WAIT4_TEST_PROBE_FRAME);
716 }
717 break;
718 }
719 case WAIT4_TEST_PROBE_FRAME: {
720 // keep ignoring the data until a frame is collected
721 break;
722 }
723#endif // Q_UTEST
724
725 case ERROR_STATE: {
726 // keep ignoring the data until a good frame is collected
727 break;
728 }
729 default: { // unexpected or unimplemented state
730 rxReportError_(0x45U);
731 tran_(ERROR_STATE);
732 break;
733 }
734 }
735}
736
737//............................................................................
738void rxHandleGoodFrame_(std::uint8_t const state) {
739 std::uint8_t i;
740 std::uint8_t *ptr;
742
743 switch (state) {
744 case WAIT4_INFO_FRAME: {
745 // no need to report Ack or Done
747 QS_MEM_SYS();
748 QP::QS::target_info_pre_(0U); // send only Target info
749 QS_MEM_APP();
750 QS_CRIT_EXIT();
751 break;
752 }
753 case WAIT4_RESET_FRAME: {
754 // no need to report Ack or Done, because Target resets
755 QP::QS::onReset(); // reset the Target
756 break;
757 }
758 case WAIT4_CMD_PARAM1: // intentionally fall-through
759 case WAIT4_CMD_PARAM2: // intentionally fall-through
760 case WAIT4_CMD_PARAM3: // intentionally fall-through
761 case WAIT4_CMD_FRAME: {
762 rxReportAck_(QP::QS_RX_COMMAND);
763 QP::QS::onCommand(QP::QS::rxPriv_.var.cmd.cmdId, QP::QS::rxPriv_.var.cmd.param1,
764 QP::QS::rxPriv_.var.cmd.param2, QP::QS::rxPriv_.var.cmd.param3);
765#ifdef Q_UTEST
766 #if Q_UTEST != 0
767 QP::QS::processTestEvts_(); // process all events produced
768 #endif // Q_UTEST != 0
769#endif // Q_UTEST
770 rxReportDone_(QP::QS_RX_COMMAND);
771 break;
772 }
773 case WAIT4_TICK_FRAME: {
774 rxReportAck_(QP::QS_RX_TICK);
775#ifdef Q_UTEST
777 static_cast<std::uint_fast8_t>(QP::QS::rxPriv_.var.tick.rate),
778 &QP::QS::rxPriv_);
779 #if Q_UTEST != 0
780 QP::QS::processTestEvts_(); // process all events produced
781 #endif // Q_UTEST != 0
782#else
784 static_cast<std::uint_fast8_t>(QP::QS::rxPriv_.var.tick.rate),
785 &QP::QS::rxPriv_);
786#endif // Q_UTEST
787 rxReportDone_(QP::QS_RX_TICK);
788 break;
789 }
790 case WAIT4_PEEK_FRAME: {
791 // no need to report Ack or Done
793 QS_MEM_SYS();
794 QP::QS::beginRec_(static_cast<std::uint_fast8_t>(
796 ptr = static_cast<std::uint8_t*>(
797 QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]);
798 ptr = &ptr[QP::QS::rxPriv_.var.peek.offs];
799 QS_TIME_PRE_(); // timestamp
800 QS_U16_PRE_(QP::QS::rxPriv_.var.peek.offs); // data offset
801 QS_U8_PRE_(QP::QS::rxPriv_.var.peek.size); // data size
802 QS_U8_PRE_(QP::QS::rxPriv_.var.peek.num); // number of data items
803 for (i = 0U; i < QP::QS::rxPriv_.var.peek.num; ++i) {
804 switch (QP::QS::rxPriv_.var.peek.size) {
805 case 1:
806 QS_U8_PRE_(ptr[i]);
807 break;
808 case 2:
809 QS_U16_PRE_(
810 reinterpret_cast<std::uint16_t*>(ptr)[i]);
811 break;
812 case 4:
813 QS_U32_PRE_(
814 reinterpret_cast<std::uint32_t*>(ptr)[i]);
815 break;
816 default:
817 // intentionally empty
818 break;
819 }
820 }
821 QP::QS::endRec_();
822 QS_MEM_APP();
823 QS_CRIT_EXIT();
824
825 QS_REC_DONE(); // user callback (if defined)
826 break;
827 }
828 case WAIT4_POKE_DATA: {
829 // received less than expected poke data items
830 rxReportError_(static_cast<std::uint8_t>(QP::QS_RX_POKE));
831 break;
832 }
833 case WAIT4_POKE_FRAME: {
834 rxReportAck_(QP::QS_RX_POKE);
835 // no need to report done
836 break;
837 }
838 case WAIT4_FILL_FRAME: {
839 rxReportAck_(QP::QS_RX_FILL);
840 ptr = static_cast<std::uint8_t *>(
841 QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]);
842 ptr = &ptr[QP::QS::rxPriv_.var.poke.offs];
843 for (i = 0U; i < QP::QS::rxPriv_.var.poke.num; ++i) {
844 switch (QP::QS::rxPriv_.var.poke.size) {
845 case 1:
846 ptr[i] =
847 static_cast<std::uint8_t>(QP::QS::rxPriv_.var.poke.data);
848 break;
849 case 2:
850 reinterpret_cast<std::uint16_t *>(ptr)[i] =
851 static_cast<std::uint16_t>(QP::QS::rxPriv_.var.poke.data);
852 break;
853 case 4:
854 reinterpret_cast<std::uint32_t *>(ptr)[i] =
855 QP::QS::rxPriv_.var.poke.data;
856 break;
857 default:
858 // intentionally empty
859 break;
860 }
861 }
862 break;
863 }
864 case WAIT4_FILTER_FRAME: {
865 rxReportAck_(static_cast<enum QP::QSpyRxRecords>(
866 QP::QS::rxPriv_.var.flt.recId));
867
868 // apply the received filters
869 if (QP::QS::rxPriv_.var.flt.recId
870 == static_cast<std::uint8_t>(QP::QS_RX_GLB_FILTER))
871 {
872 for (i = 0U;
873 i < static_cast<std::uint8_t>(sizeof(QP::QS::filt_.glb));
874 ++i)
875 {
876 QP::QS::filt_.glb[i] = QP::QS::rxPriv_.var.flt.data[i];
877 }
878 // leave the "not maskable" filters enabled,
879 // see qs.hpp, Miscellaneous QS records (not maskable)
880 QP::QS::filt_.glb[0] |= 0x01U;
881 QP::QS::filt_.glb[7] |= 0xFCU;
882 QP::QS::filt_.glb[8] |= 0x7FU;
883
884 // never enable the last 3 records (0x7D, 0x7E, 0x7F)
885 QP::QS::filt_.glb[15] &= 0x1FU;
886 }
887 else if (QP::QS::rxPriv_.var.flt.recId
888 == static_cast<std::uint8_t>(QP::QS_RX_LOC_FILTER))
889 {
890 for (i = 0U; i < Q_DIM(QP::QS::filt_.loc); ++i) {
891 QP::QS::filt_.loc[i] = QP::QS::rxPriv_.var.flt.data[i];
892 }
893 // leave QS_ID == 0 always on
894 QP::QS::filt_.loc[0] |= 0x01U;
895 }
896 else {
897 rxReportError_(QP::QS::rxPriv_.var.flt.recId);
898 }
899 // no need to report Done
900 break;
901 }
902 case WAIT4_OBJ_FRAME: {
903 i = QP::QS::rxPriv_.var.obj.kind;
904 if (i < static_cast<std::uint8_t>(QP::QS::MAX_OBJ)) {
905 if (QP::QS::rxPriv_.var.obj.recId
906 == static_cast<std::uint8_t>(QP::QS_RX_CURR_OBJ))
907 {
908 QP::QS::rxPriv_.currObj[i] =
909 reinterpret_cast<void *>(QP::QS::rxPriv_.var.obj.addr);
910 rxReportAck_(QP::QS_RX_CURR_OBJ);
911 }
912 else if (QP::QS::rxPriv_.var.obj.recId
913 == static_cast<std::uint8_t>(QP::QS_RX_AO_FILTER))
914 {
915 if (QP::QS::rxPriv_.var.obj.addr != 0U) {
916 std::int_fast16_t const filter =
917 static_cast<std::int_fast16_t>(
918 reinterpret_cast<QP::QActive *>(
919 QP::QS::rxPriv_.var.obj.addr)->getPrio());
920 QP::QS::locFilter_((i == 0)
921 ? filter
922 :-filter);
923 rxReportAck_(QP::QS_RX_AO_FILTER);
924 }
925 else {
926 rxReportError_(static_cast<enum_t>(
927 QP::QS_RX_AO_FILTER));
928 }
929 }
930 else {
931 rxReportError_(QP::QS::rxPriv_.var.obj.recId);
932 }
933 }
934 // both SM and AO
935 else if (i == static_cast<std::uint8_t>(QP::QS::SM_AO_OBJ)) {
936 if (QP::QS::rxPriv_.var.obj.recId
937 == static_cast<std::uint8_t>(QP::QS_RX_CURR_OBJ))
938 {
939 QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ]
940 = reinterpret_cast<void *>(QP::QS::rxPriv_.var.obj.addr);
941 QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ]
942 = reinterpret_cast<void *>(QP::QS::rxPriv_.var.obj.addr);
943 }
944 rxReportAck_(
945 static_cast<enum QP::QSpyRxRecords>(QP::QS::rxPriv_.var.obj.recId));
946 }
947 else {
948 rxReportError_(QP::QS::rxPriv_.var.obj.recId);
949 }
950 break;
951 }
952 case WAIT4_QUERY_FRAME: {
953 queryCurrObj_(QP::QS::rxPriv_.var.obj.kind);
954 break;
955 }
956 case WAIT4_EVT_FRAME: {
957 // NOTE: Ack was already reported in the WAIT4_EVT_LEN state
958#ifdef Q_UTEST
959 QP::QS::onTestEvt(QP::QS::rxPriv_.var.evt.e); // "massage" the event
960#endif // Q_UTEST
961 // use 'i' as status, 0 == success,no-recycle
962 i = 0U;
963
964 if (QP::QS::rxPriv_.var.evt.prio == 0U) { // publish
965 QP::QActive::publish_(QP::QS::rxPriv_.var.evt.e, &QP::QS::rxPriv_, 0U);
966 }
967 else if (QP::QS::rxPriv_.var.evt.prio < QF_MAX_ACTIVE) {
968 if (!QP::QActive::registry_[QP::QS::rxPriv_.var.evt.prio]->POST_X(
969 QP::QS::rxPriv_.var.evt.e,
970 0U, // margin
971 &QP::QS::rxPriv_))
972 {
973 // failed QACTIVE_POST() recycles the event
974 i = 0x80U; // failure status, no recycle
975 }
976 }
977 else if (QP::QS::rxPriv_.var.evt.prio == 255U) {
978 // dispatch to the current SM object
979 if (QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] != nullptr) {
980 // increment the ref-ctr to simulate the situation
981 // when the event is just retrieved from a queue.
982 // This is expected for the following QF::gc() call.
983 QP::QEvt_refCtr_inc_(QP::QS::rxPriv_.var.evt.e);
984
985 static_cast<QP::QAsm *>(
986 QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ])
987 ->dispatch(QP::QS::rxPriv_.var.evt.e, 0U);
988 i = 0x01U; // success, recycle
989 }
990 else {
991 i = 0x81U; // failure, recycle
992 }
993 }
994 else if (QP::QS::rxPriv_.var.evt.prio == 254U) {
995 // init the current SM object"
996 if (QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] != nullptr) {
997 // increment the ref-ctr to simulate the situation
998 // when the event is just retrieved from a queue.
999 // This is expected for the following QF::gc() call.
1000 QP::QEvt_refCtr_inc_(QP::QS::rxPriv_.var.evt.e);
1001
1002 static_cast<QP::QAsm *>(
1003 QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ])
1004 ->init(QP::QS::rxPriv_.var.evt.e, 0U);
1005 i = 0x01U; // success, recycle
1006 }
1007 else {
1008 i = 0x81U; // failure, recycle
1009 }
1010 }
1011 else if (QP::QS::rxPriv_.var.evt.prio == 253U) {
1012 // post to the current AO
1013 if (QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ] != nullptr) {
1014 if (!static_cast<QP::QActive *>(
1015 QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ])->POST_X(
1016 QP::QS::rxPriv_.var.evt.e,
1017 0U, // margin
1018 &QP::QS::rxPriv_))
1019 {
1020 // failed QACTIVE_POST() recycles the event
1021 i = 0x80U; // failure, no recycle
1022 }
1023 }
1024 else {
1025 i = 0x81U; // failure, recycle
1026 }
1027 }
1028 else {
1029 i = 0x81U; // failure, recycle
1030 }
1031
1032#if (QF_MAX_EPOOL > 0U)
1033 // recycle needed?
1034 if ((i & 1U) != 0U) {
1035 QP::QF::gc(QP::QS::rxPriv_.var.evt.e);
1036 }
1037#endif
1038 // failure?
1039 if ((i & 0x80U) != 0U) {
1040 rxReportError_(static_cast<std::uint8_t>(QP::QS_RX_EVENT));
1041 }
1042 else {
1043#ifdef Q_UTEST
1044 #if Q_UTEST != 0
1045 QP::QS::processTestEvts_(); // process all events produced
1046 #endif // Q_UTEST != 0
1047#endif // Q_UTEST
1048 rxReportDone_(QP::QS_RX_EVENT);
1049 }
1050 break;
1051 }
1052
1053#ifdef Q_UTEST
1054 case WAIT4_TEST_SETUP_FRAME: {
1055 rxReportAck_(QP::QS_RX_TEST_SETUP);
1056 QP::QS::tstPriv_.tpNum = 0U; // clear Test-Probes
1057 QP::QS::tstPriv_.testTime = 0U; //clear time tick
1058 // don't clear current objects
1059 QP::QS::onTestSetup(); // application-specific test setup
1060 // no need to report Done
1061 break;
1062 }
1063 case WAIT4_TEST_TEARDOWN_FRAME: {
1064 rxReportAck_(QP::QS_RX_TEST_TEARDOWN);
1065 QP::QS::onTestTeardown(); // application-specific test teardown
1066 // no need to report Done
1067 break;
1068 }
1069 case WAIT4_TEST_CONTINUE_FRAME: {
1070 rxReportAck_(QP::QS_RX_TEST_CONTINUE);
1071 QP::QS::rxPriv_.inTestLoop = false; // exit the QUTest loop
1072 // no need to report Done
1073 break;
1074 }
1075 case WAIT4_TEST_PROBE_FRAME: {
1076 rxReportAck_(QP::QS_RX_TEST_PROBE);
1077 Q_ASSERT_INCRIT(815,
1078 QP::QS::tstPriv_.tpNum
1079 < (sizeof(QP::QS::tstPriv_.tpBuf)
1080 / sizeof(QP::QS::tstPriv_.tpBuf[0])));
1081 QP::QS::tstPriv_.tpBuf[QP::QS::tstPriv_.tpNum] = QP::QS::rxPriv_.var.tp;
1082 ++QP::QS::tstPriv_.tpNum;
1083 // no need to report Done
1084 break;
1085 }
1086#endif // Q_UTEST
1087
1088 case ERROR_STATE: {
1089 // keep ignoring all bytes until new frame
1090 break;
1091 }
1092 default: {
1093 rxReportError_(0x47U);
1094 break;
1095 }
1096 }
1097}
1098
1099//............................................................................
1100static void rxHandleBadFrame_(std::uint8_t const state) noexcept {
1101 rxReportError_(0x50U); // error for all bad frames
1102 switch (state) {
1103 case WAIT4_EVT_FRAME: {
1105 QS_CRIT_ENTRY();
1106 Q_ASSERT_INCRIT(910, QP::QS::rxPriv_.var.evt.e != nullptr);
1107 QS_CRIT_EXIT();
1108#if (QF_MAX_EPOOL > 0U)
1109 QP::QF::gc(QP::QS::rxPriv_.var.evt.e); // don't leak allocated evt
1110#endif
1111 break;
1112 }
1113 default: {
1114 // intentionally empty
1115 break;
1116 }
1117 }
1118}
1119
1120//............................................................................
1121static void rxReportAck_(enum QP::QSpyRxRecords const recId) noexcept {
1123 QS_CRIT_ENTRY();
1124 QS_MEM_SYS();
1125 QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_RX_STATUS));
1126 QS_U8_PRE_(recId); // record ID
1127 QP::QS::endRec_();
1128 QS_MEM_APP();
1129 QS_CRIT_EXIT();
1130 QS_REC_DONE(); // user callback (if defined)
1131}
1132
1133//............................................................................
1134static void rxReportError_(std::uint8_t const code) noexcept {
1136 QS_CRIT_ENTRY();
1137 QS_MEM_SYS();
1138 QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_RX_STATUS));
1139 QS_U8_PRE_(0x80U | code); // error code
1140 QP::QS::endRec_();
1141 QS_MEM_APP();
1142 QS_CRIT_EXIT();
1143 QS_REC_DONE(); // user callback (if defined)
1144}
1145
1146//............................................................................
1147static void rxReportDone_(enum QP::QSpyRxRecords const recId) noexcept {
1149 QS_CRIT_ENTRY();
1150 QS_MEM_SYS();
1151 QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_TARGET_DONE));
1152 QS_TIME_PRE_(); // timestamp
1153 QS_U8_PRE_(recId); // record ID
1154 QP::QS::endRec_();
1155 QS_MEM_APP();
1156 QS_CRIT_EXIT();
1157 QS_REC_DONE(); // user callback (if defined)
1158}
1159
1160//............................................................................
1161static void queryCurrObj_(std::uint8_t obj_kind) noexcept {
1163 QS_CRIT_ENTRY();
1164 Q_REQUIRE_INCRIT(800, obj_kind < Q_DIM(QP::QS::rxPriv_.currObj));
1165 QS_CRIT_EXIT();
1166
1167 if (QP::QS::rxPriv_.currObj[obj_kind] != nullptr) {
1168 QS_CRIT_ENTRY();
1169 QS_MEM_SYS();
1170 QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_QUERY_DATA));
1171 QS_TIME_PRE_(); // timestamp
1172 QS_U8_PRE_(obj_kind); // object kind
1173 QS_OBJ_PRE_(QP::QS::rxPriv_.currObj[obj_kind]); // object pointer
1174 switch (obj_kind) {
1175 case QP::QS::SM_OBJ: // intentionally fall through
1176 case QP::QS::AO_OBJ:
1177 QS_FUN_PRE_(reinterpret_cast<QP::QHsm *>(
1178 QP::QS::rxPriv_.currObj[obj_kind])->getStateHandler());
1179 break;
1180 case QP::QS::MP_OBJ:
1181 QS_MPC_PRE_(reinterpret_cast<QP::QMPool *>(
1182 QP::QS::rxPriv_.currObj[obj_kind])->getNFree());
1183 QS_MPC_PRE_(reinterpret_cast<QP::QMPool *>(
1184 QP::QS::rxPriv_.currObj[obj_kind])->getNMin());
1185 break;
1186 case QP::QS::EQ_OBJ:
1187 QS_EQC_PRE_(reinterpret_cast<QP::QEQueue *>(
1188 QP::QS::rxPriv_.currObj[obj_kind])->getNFree());
1189 QS_EQC_PRE_(reinterpret_cast<QP::QEQueue *>(
1190 QP::QS::rxPriv_.currObj[obj_kind])->getNMin());
1191 break;
1192 case QP::QS::TE_OBJ:
1193 QS_OBJ_PRE_(reinterpret_cast<QP::QTimeEvt *>(
1194 QP::QS::rxPriv_.currObj[obj_kind])->getAct());
1195 QS_TEC_PRE_(reinterpret_cast<QP::QTimeEvt *>(
1196 QP::QS::rxPriv_.currObj[obj_kind])->getCtr());
1197 QS_TEC_PRE_(reinterpret_cast<QP::QTimeEvt *>(
1198 QP::QS::rxPriv_.currObj[obj_kind])->getInterval());
1199 QS_SIG_PRE_(reinterpret_cast<QP::QTimeEvt *>(
1200 QP::QS::rxPriv_.currObj[obj_kind])->sig);
1201 QS_U8_PRE_ (reinterpret_cast<QP::QTimeEvt *>(
1202 QP::QS::rxPriv_.currObj[obj_kind])->refCtr_);
1203 break;
1204 default:
1205 // intentionally empty
1206 break;
1207 }
1208 QP::QS::endRec_();
1209 QS_MEM_APP();
1210 QS_CRIT_EXIT();
1211 QS_REC_DONE(); // user callback (if defined)
1212 }
1213 else {
1214 rxReportError_(static_cast<std::uint8_t>(QP::QS_RX_AO_FILTER));
1215 }
1216}
1217
1218//............................................................................
1219static void rxPoke_() noexcept {
1220 std::uint8_t * ptr =
1221 static_cast<std::uint8_t *>(QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]);
1222 ptr = &ptr[QP::QS::rxPriv_.var.poke.offs];
1223 switch (QP::QS::rxPriv_.var.poke.size) {
1224 case 1:
1225 *ptr = static_cast<std::uint8_t>(QP::QS::rxPriv_.var.poke.data);
1226 break;
1227 case 2:
1228 *reinterpret_cast<std::uint16_t *>(ptr)
1229 = static_cast<std::uint16_t>(QP::QS::rxPriv_.var.poke.data);
1230 break;
1231 case 4:
1232 *reinterpret_cast<std::uint32_t *>(ptr) = QP::QS::rxPriv_.var.poke.data;
1233 break;
1234 default:
1235 Q_ERROR_ID(900);
1236 break;
1237 }
1238
1239 QP::QS::rxPriv_.var.poke.data = 0U;
1240 QP::QS::rxPriv_.var.poke.idx = 0U;
1241 QP::QS::rxPriv_.var.poke.offs += static_cast<std::uint16_t>(QP::QS::rxPriv_.var.poke.size);
1242}
1243
1244} // unnamed namespace
1245
1246//! @endcond
Active object class (based on the QHsm implementation strategy)
Definition qp.hpp:724
static void publish_(QEvt const *const e, void const *const sender, std::uint_fast8_t const qsId) noexcept
Definition qf_ps.cpp:107
static QActive * registry_[QF_MAX_ACTIVE+1U]
Definition qp.hpp:750
Abstract State Machine class (state machine interface)
Definition qp.hpp:220
Native QP event queue.
Definition qequeue.hpp:70
Event class.
Definition qp.hpp:139
Hierarchical State Machine class (QHsm-style state machine implementation strategy)
Definition qp.hpp:392
Native QF Memory Pool.
Definition qmpool.hpp:101
std::uint8_t glb[16]
Definition qs.hpp:314
std::uint8_t loc[16]
Definition qs.hpp:315
Time Event class.
Definition qp.hpp:955
static void tick1_(std::uint_fast8_t const tickRate, void const *const sender)
Definition qutest.cpp:274
static void tick(std::uint_fast8_t const tickRate, void const *const sender) noexcept
Definition qf_time.cpp:280
std::uint_fast16_t poolGetMaxBlockSize() noexcept
Definition qf_dyn.cpp:126
QEvt * newX_(std::uint_fast16_t const evtSize, std::uint_fast16_t const margin, enum_t const sig) noexcept
Definition qf_dyn.cpp:157
void init()
Definition qk.cpp:368
void gc(QEvt const *const e) noexcept
Definition qf_dyn.cpp:236
Filter filt_
Definition qs.cpp:163
void rxInitBuf(std::uint8_t *const sto, std::uint16_t const stoSize) noexcept
Definition qs_rx.cpp:145
void onTestSetup()
std::uint16_t rxGetNfree() noexcept
Definition qs_rx.cpp:241
void onReset()
@ SM_AO_OBJ
combination of SM and AO
Definition qs.hpp:1003
void rxParse()
Definition qs_rx.cpp:179
void setCurrObj(std::uint8_t const obj_kind, void *const obj_ptr)
Definition qs_rx.cpp:224
void onCommand(std::uint8_t cmdId, std::uint32_t param1, std::uint32_t param2, std::uint32_t param3)
void onTestTeardown()
void processTestEvts_()
Definition qutest.cpp:163
void onTestEvt(QEvt *e)
@ SM_OBJ
state machine object
Definition qs.hpp:991
@ TE_OBJ
time event object
Definition qs.hpp:995
@ MAX_OBJ
Definition qs.hpp:997
@ EQ_OBJ
raw queue object
Definition qs.hpp:994
@ AP_OBJ
generic Application-specific object
Definition qs.hpp:996
@ AO_OBJ
active object
Definition qs.hpp:992
@ MP_OBJ
event pool object
Definition qs.hpp:993
QP/C++ framework.
Definition qequeue.hpp:50
std::uint16_t QSignal
Definition qp.hpp:130
void QEvt_refCtr_inc_(QEvt const *const e) noexcept
Definition qp_pkg.hpp:92
@ QS_TARGET_DONE
reports completion of a user callback
Definition qs.hpp:166
@ QS_QUERY_DATA
reports the data from "current object" query
Definition qs.hpp:168
@ QS_RX_STATUS
reports QS data receive status
Definition qs.hpp:167
@ QS_PEEK_DATA
reports the data from the PEEK query
Definition qs.hpp:169
@ QS_OBJ_DICT
object dictionary entry
Definition qs.hpp:162
int enum_t
Definition qp.hpp:108
#define Q_DIM(array_)
Definition qp.hpp:544
#define QS_FUN_PTR_SIZE
#define QF_MAX_ACTIVE
#define QS_OBJ_PTR_SIZE
#define Q_SIGNAL_SIZE
Internal (package scope) QP/C++ interface.
#define QS_CRIT_STAT
Definition qs.hpp:590
#define QS_TIME_PRE_()
Definition qs.hpp:473
#define QS_REC_DONE()
Definition qs.hpp:392
#define QS_MEM_APP()
Definition qs.hpp:610
#define QS_CRIT_EXIT()
Definition qs.hpp:600
#define QS_MEM_SYS()
Definition qs.hpp:605
#define QS_CRIT_ENTRY()
Definition qs.hpp:595
QS/C++ package-scope interface.
QS/C++ port to a 32-bit CPU, generic C++ compiler.
QP Functional Safety (FuSa) Subsystem.
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:72
#define Q_ERROR_ID(id_)
Definition qsafe.h:88
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:136