QP/C++ 6.9.3
qs_rx.cpp
Go to the documentation of this file.
1 
39 #define QP_IMPL // this is QP implementation
40 #include "qs_port.hpp" // QS port
41 #include "qs_pkg.hpp" // QS package-scope internal interface
42 #include "qf_pkg.hpp" // QF package-scope internal interface
43 #include "qassert.h" // QP assertions
44 
45 namespace QP {
46 
47 Q_DEFINE_THIS_MODULE("qs_rx")
48 
49 //****************************************************************************
50 struct QS::QSrxPriv QS::rxPriv_; // QS-RX private data
51 
52 //****************************************************************************
53 #if (QS_OBJ_PTR_SIZE == 1U)
54  using QSObj = std::uint8_t;
55 #elif (QS_OBJ_PTR_SIZE == 2U)
56  using QSObj = std::uint16_t;
57 #elif (QS_OBJ_PTR_SIZE == 4U)
58  using QSObj = std::uint32_t;
59 #elif (QS_OBJ_PTR_SIZE == 8U)
60  using QSObj = std::uint64_t;
61 #endif
62 
63 #if (QS_FUN_PTR_SIZE == 1U)
64  using QSFun = std::uint8_t;
65 #elif (QS_FUN_PTR_SIZE == 2U)
66  using QSFun = std::uint16_t;
67 #elif (QS_FUN_PTR_SIZE == 4U)
68  using QSFun = std::uint32_t;
69 #elif (QS_FUN_PTR_SIZE == 8U)
70  using QSFun = std::uint64_t;
71 #endif
72 
76 struct CmdVar {
77  std::uint32_t param1;
78  std::uint32_t param2;
79  std::uint32_t param3;
80  std::uint8_t idx;
81  std::uint8_t cmdId;
82 };
83 
84 struct TickVar {
85  std::uint_fast8_t rate;
86 };
87 
88 struct PeekVar {
89  std::uint16_t offs;
90  std::uint8_t size;
91  std::uint8_t num;
92  std::uint8_t idx;
93 };
94 
95 struct PokeVar {
96  std::uint32_t data;
97  std::uint16_t offs;
98  std::uint8_t size;
99  std::uint8_t num;
100  std::uint8_t idx;
101  std::uint8_t fill;
102 };
103 
104 struct FltVar {
105  std::uint8_t data[16];
106  std::uint8_t idx;
107  std::uint8_t recId; // global/local
108 };
109 
110 struct ObjVar {
111  QSObj addr;
112  std::uint8_t idx;
113  std::uint8_t kind; // see qs.hpp, enum QSpyObjKind
114  std::uint8_t recId;
115 };
116 
117 struct TPVar { // Test-Probe
118  QSFun addr;
119  std::uint32_t data;
120  std::uint8_t idx;
121 };
122 
123 struct AFltVar {
124  std::uint8_t prio;
125 };
126 
127 struct EvtVar {
128  QEvt *e;
129  std::uint8_t *p;
130  QSignal sig;
131  std::uint16_t len;
132  std::uint8_t prio;
133  std::uint8_t idx;
134 };
135 
136 // extended-state variables for the current QS-RX state
137 static struct ExtState {
138  union Variant {
139  CmdVar cmd;
140  TickVar tick;
141  PeekVar peek;
142  PokeVar poke;
143  FltVar flt;
144  AFltVar aFlt;
145  ObjVar obj;
146  EvtVar evt;
147  TPVar tp;
148  } var;
149  std::uint8_t state;
150  std::uint8_t esc;
151  std::uint8_t seq;
152  std::uint8_t chksum;
153 } l_rx;
154 
155 enum RxStateEnum : std::uint8_t {
156  WAIT4_SEQ,
157  WAIT4_REC,
158  WAIT4_INFO_FRAME,
159  WAIT4_CMD_ID,
160  WAIT4_CMD_PARAM1,
161  WAIT4_CMD_PARAM2,
162  WAIT4_CMD_PARAM3,
163  WAIT4_CMD_FRAME,
164  WAIT4_RESET_FRAME,
165  WAIT4_TICK_RATE,
166  WAIT4_TICK_FRAME,
167  WAIT4_PEEK_OFFS,
168  WAIT4_PEEK_SIZE,
169  WAIT4_PEEK_NUM,
170  WAIT4_PEEK_FRAME,
171  WAIT4_POKE_OFFS,
172  WAIT4_POKE_SIZE,
173  WAIT4_POKE_NUM,
174  WAIT4_POKE_DATA,
175  WAIT4_POKE_FRAME,
176  WAIT4_FILL_DATA,
177  WAIT4_FILL_FRAME,
178  WAIT4_FILTER_LEN,
179  WAIT4_FILTER_DATA,
180  WAIT4_FILTER_FRAME,
181  WAIT4_OBJ_KIND,
182  WAIT4_OBJ_ADDR,
183  WAIT4_OBJ_FRAME,
184  WAIT4_QUERY_KIND,
185  WAIT4_QUERY_FRAME,
186  WAIT4_EVT_PRIO,
187  WAIT4_EVT_SIG,
188  WAIT4_EVT_LEN,
189  WAIT4_EVT_PAR,
190  WAIT4_EVT_FRAME,
191  WAIT4_TEST_SETUP_FRAME,
192  WAIT4_TEST_TEARDOWN_FRAME,
193  WAIT4_TEST_PROBE_DATA,
194  WAIT4_TEST_PROBE_ADDR,
195  WAIT4_TEST_PROBE_FRAME,
196  WAIT4_TEST_CONTINUE_FRAME,
197  ERROR_STATE
198 };
199 
200 #ifdef Q_UTEST
201  static struct TestData {
202  TPVar tpBuf[16]; // buffer of Test-Probes received so far
203  std::uint8_t tpNum; // current number of Test-Probes
204  QSTimeCtr testTime; // test time (tick counter)
205  } l_testData;
206 #endif // Q_UTEST
207 
208 // internal helper functions...
209 static void rxParseData_(std::uint8_t const b) noexcept;
210 static void rxHandleBadFrame_(std::uint8_t const state) noexcept;
211 static void rxReportAck_(enum QSpyRxRecords const recId) noexcept;
212 static void rxReportError_(std::uint8_t const code) noexcept;
213 static void rxReportDone_(enum QSpyRxRecords const recId) noexcept;
214 static void rxPoke_(void) noexcept;
215 
217 static inline void tran_(RxStateEnum const target) noexcept {
218  l_rx.state = static_cast<std::uint8_t>(target);
219 }
221 
222 
223 //****************************************************************************
243 void QS::rxInitBuf(std::uint8_t * const sto,
244  std::uint16_t const stoSize) noexcept
245 {
246  rxPriv_.buf = &sto[0];
247  rxPriv_.end = static_cast<QSCtr>(stoSize);
248  rxPriv_.head = 0U;
249  rxPriv_.tail = 0U;
250 
251  rxPriv_.currObj[QS::SM_OBJ] = nullptr;
252  rxPriv_.currObj[QS::AO_OBJ] = nullptr;
253  rxPriv_.currObj[QS::MP_OBJ] = nullptr;
254  rxPriv_.currObj[QS::EQ_OBJ] = nullptr;
255  rxPriv_.currObj[QS::TE_OBJ] = nullptr;
256  rxPriv_.currObj[QS::AP_OBJ] = nullptr;
257 
258  tran_(WAIT4_SEQ);
259  l_rx.esc = 0U;
260  l_rx.seq = 0U;
261  l_rx.chksum = 0U;
262 
263  beginRec_(static_cast<std::uint_fast8_t>(QS_OBJ_DICT));
264  QS_OBJ_PRE_(&rxPriv_);
265  QS_STR_PRE_("QS_RX");
266  endRec_();
267  // no QS_REC_DONE(), because QS is not running yet
268 
269 #ifdef Q_UTEST
270  l_testData.tpNum = 0U;
271  l_testData.testTime = 0U;
272 #endif // Q_UTEST
273 }
274 
275 //****************************************************************************
284  QSCtr head = rxPriv_.head;
285  if (head == rxPriv_.tail) { // buffer empty?
286  return static_cast<std::uint16_t>(rxPriv_.end - 1U);
287  }
288  else if (head < rxPriv_.tail) {
289  return static_cast<std::uint16_t>(rxPriv_.tail - head - 1U);
290  }
291  else {
292  return static_cast<std::uint16_t>(rxPriv_.end + rxPriv_.tail
293  - head - 1U);
294  }
295 }
296 
297 //****************************************************************************
302 void QS::setCurrObj(std::uint8_t obj_kind, void *obj_ptr) noexcept {
303 
304  Q_REQUIRE_ID(100, obj_kind < Q_DIM(rxPriv_.currObj));
305  rxPriv_.currObj[obj_kind] = obj_ptr;
306 }
307 
308 //****************************************************************************
314 void QS::queryCurrObj(std::uint8_t obj_kind) noexcept {
315  Q_REQUIRE_ID(200, obj_kind < Q_DIM(rxPriv_.currObj));
316 
317  if (QS::rxPriv_.currObj[obj_kind] != nullptr) {
319  QS_CRIT_E_();
321  QS_TIME_PRE_(); // timestamp
322  QS_U8_PRE_(obj_kind); // object kind
323  QS_OBJ_PRE_(QS::rxPriv_.currObj[obj_kind]); // object pointer
324  switch (obj_kind) {
325  case SM_OBJ: // intentionally fall through
326  case AO_OBJ:
327  QS_FUN_PRE_(
328  reinterpret_cast<QHsm *>(
329  QS::rxPriv_.currObj[obj_kind])->getStateHandler());
330  break;
331  case QS::MP_OBJ:
332  QS_MPC_PRE_(reinterpret_cast<QMPool *>(
333  QS::rxPriv_.currObj[obj_kind])->m_nFree);
334  QS_MPC_PRE_(reinterpret_cast<QMPool *>(
335  QS::rxPriv_.currObj[obj_kind])->m_nMin);
336  break;
337  case QS::EQ_OBJ:
338  QS_EQC_PRE_(reinterpret_cast<QEQueue *>(
339  QS::rxPriv_.currObj[obj_kind])->m_nFree);
340  QS_EQC_PRE_(reinterpret_cast<QEQueue *>(
341  QS::rxPriv_.currObj[obj_kind])->m_nMin);
342  break;
343  case QS::TE_OBJ:
344  QS_OBJ_PRE_(reinterpret_cast<QTimeEvt *>(
345  QS::rxPriv_.currObj[obj_kind])->m_act);
346  QS_TEC_PRE_(reinterpret_cast<QTimeEvt *>(
347  QS::rxPriv_.currObj[obj_kind])->m_ctr);
348  QS_TEC_PRE_(reinterpret_cast<QTimeEvt *>(
349  QS::rxPriv_.currObj[obj_kind])->m_interval);
350  QS_SIG_PRE_(reinterpret_cast<QTimeEvt *>(
351  QS::rxPriv_.currObj[obj_kind])->sig);
352  QS_U8_PRE_ (reinterpret_cast<QTimeEvt *>(
353  QS::rxPriv_.currObj[obj_kind])->refCtr_);
354  break;
355  default:
356  break;
357  }
358  QS::endRec_();
359  QS_CRIT_X_();
360 
361  QS_REC_DONE(); // user callback (if defined)
362  }
363  else {
365  }
366  // no need to report Done
367 }
368 
369 //****************************************************************************
370 void QS::rxParse(void) {
372  while (rxPriv_.head != tail) { // QS-RX buffer NOT empty?
374 
375  ++tail;
376  if (tail == rxPriv_.end) {
377  tail = 0U;
378  }
379  rxPriv_.tail = tail; // update the tail to a *valid* index
380 
381  if (l_rx.esc != 0U) { // escaped byte arrived?
382  l_rx.esc = 0U;
383  b ^= QS_ESC_XOR;
384 
385  l_rx.chksum += b;
386  rxParseData_(b);
387  }
388  else if (b == QS_ESC) {
389  l_rx.esc = 1U;
390  }
391  else if (b == QS_FRAME) {
392  // get ready for the next frame
393  b = l_rx.state; // save the current state in b
394  l_rx.esc = 0U;
395  tran_(WAIT4_SEQ);
396 
397  if (l_rx.chksum == QS_GOOD_CHKSUM) {
398  l_rx.chksum = 0U;
400  }
401  else { // bad checksum
402  l_rx.chksum = 0U;
403  rxReportError_(0x00U);
405  }
406  }
407  else {
408  l_rx.chksum += b;
409  rxParseData_(b);
410  }
411  }
412 }
413 
414 //****************************************************************************
415 static void rxParseData_(std::uint8_t const b) noexcept {
416  switch (l_rx.state) {
417  case WAIT4_SEQ: {
418  ++l_rx.seq;
419  if (l_rx.seq != b) { // not the expected sequence?
420  rxReportError_(0x42U);
421  l_rx.seq = b; // update the sequence
422  }
423  tran_(WAIT4_REC);
424  break;
425  }
426  case WAIT4_REC: {
427  switch (b) {
428  case QS_RX_INFO:
429  tran_(WAIT4_INFO_FRAME);
430  break;
431  case QS_RX_COMMAND:
432  tran_(WAIT4_CMD_ID);
433  break;
434  case QS_RX_RESET:
435  tran_(WAIT4_RESET_FRAME);
436  break;
437  case QS_RX_TICK:
438  tran_(WAIT4_TICK_RATE);
439  break;
440  case QS_RX_PEEK:
441  if (QS::rxPriv_.currObj[QS::AP_OBJ] != nullptr) {
442  l_rx.var.peek.offs = 0U;
443  l_rx.var.peek.idx = 0U;
444  tran_(WAIT4_PEEK_OFFS);
445  }
446  else {
447  rxReportError_(static_cast<std::uint8_t>(QS_RX_PEEK));
448  tran_(ERROR_STATE);
449  }
450  break;
451  case QS_RX_POKE:
452  case QS_RX_FILL:
453  l_rx.var.poke.fill =
454  (b == static_cast<std::uint8_t>(QS_RX_FILL))
455  ? 1U
456  : 0U;
457  if (QS::rxPriv_.currObj[QS::AP_OBJ] != nullptr) {
458  l_rx.var.poke.offs = 0U;
459  l_rx.var.poke.idx = 0U;
460  tran_(WAIT4_POKE_OFFS);
461  }
462  else {
464  (l_rx.var.poke.fill != 0U)
465  ? static_cast<std::uint8_t>(QS_RX_FILL)
466  : static_cast<std::uint8_t>(QS_RX_POKE));
467  tran_(ERROR_STATE);
468  }
469  break;
470  case QS_RX_GLB_FILTER: // intentionally fall-through
471  case QS_RX_LOC_FILTER:
472  l_rx.var.flt.recId = b;
473  tran_(WAIT4_FILTER_LEN);
474  break;
475  case QS_RX_AO_FILTER: // intentionally fall-through
476  case QS_RX_CURR_OBJ:
477  l_rx.var.obj.recId = b;
478  tran_(WAIT4_OBJ_KIND);
479  break;
480  case QS_RX_QUERY_CURR:
481  l_rx.var.obj.recId =
482  static_cast<std::uint8_t>(QS_RX_QUERY_CURR);
483  tran_(WAIT4_QUERY_KIND);
484  break;
485  case QS_RX_EVENT:
486  tran_(WAIT4_EVT_PRIO);
487  break;
488 
489 #ifdef Q_UTEST
490  case QS_RX_TEST_SETUP:
491  tran_(WAIT4_TEST_SETUP_FRAME);
492  break;
493  case QS_RX_TEST_TEARDOWN:
494  tran_(WAIT4_TEST_TEARDOWN_FRAME);
495  break;
496  case QS_RX_TEST_CONTINUE:
497  tran_(WAIT4_TEST_CONTINUE_FRAME);
498  break;
499  case QS_RX_TEST_PROBE:
500  if (l_testData.tpNum
501  < static_cast<std::uint8_t>(
502  (sizeof(l_testData.tpBuf)
503  / sizeof(l_testData.tpBuf[0]))))
504  {
505  l_rx.var.tp.data = 0U;
506  l_rx.var.tp.idx = 0U;
507  tran_(WAIT4_TEST_PROBE_DATA);
508  }
509  else { // the number of Test-Probes exceeded
511  static_cast<std::uint8_t>(QS_RX_TEST_PROBE));
512  tran_(ERROR_STATE);
513  }
514  break;
515 #endif // Q_UTEST
516 
517  default:
518  rxReportError_(0x43U);
519  tran_(ERROR_STATE);
520  break;
521  }
522  break;
523  }
524  case WAIT4_INFO_FRAME: {
525  // keep ignoring the data until a frame is collected
526  break;
527  }
528  case WAIT4_CMD_ID: {
529  l_rx.var.cmd.cmdId = b;
530  l_rx.var.cmd.idx = 0U;
531  l_rx.var.cmd.param1 = 0U;
532  l_rx.var.cmd.param2 = 0U;
533  l_rx.var.cmd.param3 = 0U;
534  tran_(WAIT4_CMD_PARAM1);
535  break;
536  }
537  case WAIT4_CMD_PARAM1: {
538  l_rx.var.cmd.param1 |=
539  (static_cast<std::uint32_t>(b) << l_rx.var.cmd.idx);
540  l_rx.var.cmd.idx += 8U;
541  if (l_rx.var.cmd.idx == (8U*4U)) {
542  l_rx.var.cmd.idx = 0U;
543  tran_(WAIT4_CMD_PARAM2);
544  }
545  break;
546  }
547  case WAIT4_CMD_PARAM2: {
548  l_rx.var.cmd.param2 |=
549  static_cast<std::uint32_t>(b) << l_rx.var.cmd.idx;
550  l_rx.var.cmd.idx += 8U;
551  if (l_rx.var.cmd.idx == (8U*4U)) {
552  l_rx.var.cmd.idx = 0U;
553  tran_(WAIT4_CMD_PARAM3);
554  }
555  break;
556  }
557  case WAIT4_CMD_PARAM3: {
558  l_rx.var.cmd.param3 |=
559  static_cast<std::uint32_t>(b) << l_rx.var.cmd.idx;
560  l_rx.var.cmd.idx += 8U;
561  if (l_rx.var.cmd.idx == (8U*4U)) {
562  l_rx.var.cmd.idx = 0U;
563  tran_(WAIT4_CMD_FRAME);
564  }
565  break;
566  }
567  case WAIT4_CMD_FRAME: {
568  // keep ignoring the data until a frame is collected
569  break;
570  }
571  case WAIT4_RESET_FRAME: {
572  // keep ignoring the data until a frame is collected
573  break;
574  }
575  case WAIT4_TICK_RATE: {
576  l_rx.var.tick.rate = static_cast<std::uint_fast8_t>(b);
577  tran_(WAIT4_TICK_FRAME);
578  break;
579  }
580  case WAIT4_TICK_FRAME: {
581  // keep ignoring the data until a frame is collected
582  break;
583  }
584  case WAIT4_PEEK_OFFS: {
585  if (l_rx.var.peek.idx == 0U) {
586  l_rx.var.peek.offs = static_cast<std::uint16_t>(b);
587  l_rx.var.peek.idx += 8U;
588  }
589  else {
590  l_rx.var.peek.offs |= static_cast<std::uint16_t>(
591  static_cast<std::uint16_t>(b) << 8U);
592  tran_(WAIT4_PEEK_SIZE);
593  }
594  break;
595  }
596  case WAIT4_PEEK_SIZE: {
597  if ((b == 1U) || (b == 2U) || (b == 4U)) {
598  l_rx.var.peek.size = b;
599  tran_(WAIT4_PEEK_NUM);
600  }
601  else {
602  rxReportError_(static_cast<std::uint8_t>(QS_RX_PEEK));
603  tran_(ERROR_STATE);
604  }
605  break;
606  }
607  case WAIT4_PEEK_NUM: {
608  l_rx.var.peek.num = b;
609  tran_(WAIT4_PEEK_FRAME);
610  break;
611  }
612  case WAIT4_PEEK_FRAME: {
613  // keep ignoring the data until a frame is collected
614  break;
615  }
616  case WAIT4_POKE_OFFS: {
617  if (l_rx.var.poke.idx == 0U) {
618  l_rx.var.poke.offs = static_cast<std::uint16_t>(b);
619  l_rx.var.poke.idx = 1U;
620  }
621  else {
622  l_rx.var.poke.offs |= static_cast<std::uint16_t>(
623  static_cast<std::uint16_t>(b) << 8U);
624  tran_(WAIT4_POKE_SIZE);
625  }
626  break;
627  }
628  case WAIT4_POKE_SIZE: {
629  if ((b == 1U)
630  || (b == 2U)
631  || (b == 4U))
632  {
633  l_rx.var.poke.size = b;
634  tran_(WAIT4_POKE_NUM);
635  }
636  else {
637  rxReportError_((l_rx.var.poke.fill != 0U)
638  ? static_cast<std::uint8_t>(QS_RX_FILL)
639  : static_cast<std::uint8_t>(QS_RX_POKE));
640  tran_(ERROR_STATE);
641  }
642  break;
643  }
644  case WAIT4_POKE_NUM: {
645  if (b > 0U) {
646  l_rx.var.poke.num = b;
647  l_rx.var.poke.data = 0U;
648  l_rx.var.poke.idx = 0U;
649  tran_((l_rx.var.poke.fill != 0U)
650  ? WAIT4_FILL_DATA
651  : WAIT4_POKE_DATA);
652  }
653  else {
654  rxReportError_((l_rx.var.poke.fill != 0U)
655  ? static_cast<std::uint8_t>(QS_RX_FILL)
656  : static_cast<std::uint8_t>(QS_RX_POKE));
657  tran_(ERROR_STATE);
658  }
659  break;
660  }
661  case WAIT4_FILL_DATA: {
662  l_rx.var.poke.data |=
663  static_cast<std::uint32_t>(b) << l_rx.var.poke.idx;
664  l_rx.var.poke.idx += 8U;
665  if ((l_rx.var.poke.idx >> 3U) == l_rx.var.poke.size) {
666  tran_(WAIT4_FILL_FRAME);
667  }
668  break;
669  }
670  case WAIT4_POKE_DATA: {
671  l_rx.var.poke.data |=
672  static_cast<std::uint32_t>(b) << l_rx.var.poke.idx;
673  l_rx.var.poke.idx += 8U;
674  if ((l_rx.var.poke.idx >> 3U) == l_rx.var.poke.size) {
675  rxPoke_();
676  --l_rx.var.poke.num;
677  if (l_rx.var.poke.num == 0U) {
678  tran_(WAIT4_POKE_FRAME);
679  }
680  }
681  break;
682  }
683  case WAIT4_FILL_FRAME: {
684  // keep ignoring the data until a frame is collected
685  break;
686  }
687  case WAIT4_POKE_FRAME: {
688  // keep ignoring the data until a frame is collected
689  break;
690  }
691  case WAIT4_FILTER_LEN: {
692  if (b == static_cast<std::uint8_t>(sizeof(l_rx.var.flt.data))) {
693  l_rx.var.flt.idx = 0U;
694  tran_(WAIT4_FILTER_DATA);
695  }
696  else {
697  rxReportError_(l_rx.var.flt.recId);
698  tran_(ERROR_STATE);
699  }
700  break;
701  }
702  case WAIT4_FILTER_DATA: {
703  l_rx.var.flt.data[l_rx.var.flt.idx] = b;
704  ++l_rx.var.flt.idx;
705  if (l_rx.var.flt.idx == sizeof(l_rx.var.flt.data)) {
706  tran_(WAIT4_FILTER_FRAME);
707  }
708  break;
709  }
710  case WAIT4_FILTER_FRAME: {
711  // keep ignoring the data until a frame is collected
712  break;
713  }
714  case WAIT4_OBJ_KIND: {
715  if (b <= static_cast<std::uint8_t>(QS::SM_AO_OBJ)) {
716  l_rx.var.obj.kind = b;
717  l_rx.var.obj.addr = 0U;
718  l_rx.var.obj.idx = 0U;
719  tran_(WAIT4_OBJ_ADDR);
720  }
721  else {
722  rxReportError_(l_rx.var.obj.recId);
723  tran_(ERROR_STATE);
724  }
725  break;
726  }
727  case WAIT4_OBJ_ADDR: {
728  l_rx.var.obj.addr |=
729  static_cast<QSObj>(b) << l_rx.var.obj.idx;
730  l_rx.var.obj.idx += 8U;
731  if (l_rx.var.obj.idx
732  == (8U * static_cast<unsigned>(QS_OBJ_PTR_SIZE)))
733  {
734  tran_(WAIT4_OBJ_FRAME);
735  }
736  break;
737  }
738  case WAIT4_OBJ_FRAME: {
739  // keep ignoring the data until a frame is collected
740  break;
741  }
742  case WAIT4_QUERY_KIND: {
743  if (b < static_cast<std::uint8_t>(QS::MAX_OBJ)) {
744  l_rx.var.obj.kind = b;
745  tran_(WAIT4_QUERY_FRAME);
746  }
747  else {
748  rxReportError_(l_rx.var.obj.recId);
749  tran_(ERROR_STATE);
750  }
751  break;
752  }
753  case WAIT4_QUERY_FRAME: {
754  // keep ignoring the data until a frame is collected
755  break;
756  }
757  case WAIT4_EVT_PRIO: {
758  l_rx.var.evt.prio = b;
759  l_rx.var.evt.sig = 0U;
760  l_rx.var.evt.idx = 0U;
761  tran_(WAIT4_EVT_SIG);
762  break;
763  }
764  case WAIT4_EVT_SIG: {
765  l_rx.var.evt.sig |= static_cast<QSignal>(
766  static_cast<std::uint32_t>(b) << l_rx.var.evt.idx);
767  l_rx.var.evt.idx += 8U;
768  if (l_rx.var.evt.idx
769  == (8U *static_cast<unsigned>(Q_SIGNAL_SIZE)))
770  {
771  l_rx.var.evt.len = 0U;
772  l_rx.var.evt.idx = 0U;
773  tran_(WAIT4_EVT_LEN);
774  }
775  break;
776  }
777  case WAIT4_EVT_LEN: {
778  l_rx.var.evt.len |= static_cast<std::uint16_t>(
779  static_cast<unsigned>(b) << l_rx.var.evt.idx);
780  l_rx.var.evt.idx += 8U;
781  if (l_rx.var.evt.idx == (8U * 2U)) {
782  if ((l_rx.var.evt.len + sizeof(QEvt))
783  <= static_cast<std::uint16_t>(QF::poolGetMaxBlockSize()))
784  {
785  // report Ack before generating any other QS records
787 
788  l_rx.var.evt.e = QF::newX_(
789  (static_cast<std::uint_fast16_t>(l_rx.var.evt.len)
790  + sizeof(QEvt)),
791  0U, // margin
792  static_cast<enum_t>(l_rx.var.evt.sig));
793  // event allocated?
794  if (l_rx.var.evt.e != nullptr) {
795  l_rx.var.evt.p =
796  reinterpret_cast<std::uint8_t *>(l_rx.var.evt.e);
797  l_rx.var.evt.p += sizeof(QEvt);
798  if (l_rx.var.evt.len > 0U) {
799  tran_(WAIT4_EVT_PAR);
800  }
801  else {
802  tran_(WAIT4_EVT_FRAME);
803  }
804  }
805  else {
806  rxReportError_(static_cast<std::uint8_t>(QS_RX_EVENT));
807  tran_(ERROR_STATE);
808  }
809  }
810  else {
811  rxReportError_(static_cast<std::uint8_t>(QS_RX_EVENT));
812  tran_(ERROR_STATE);
813  }
814  }
815  break;
816  }
817  case WAIT4_EVT_PAR: { // event parameters
818  *l_rx.var.evt.p = b;
819  ++l_rx.var.evt.p;
820  --l_rx.var.evt.len;
821  if (l_rx.var.evt.len == 0U) {
822  tran_(WAIT4_EVT_FRAME);
823  }
824  break;
825  }
826  case WAIT4_EVT_FRAME: {
827  // keep ignoring the data until a frame is collected
828  break;
829  }
830 
831 #ifdef Q_UTEST
832  case WAIT4_TEST_SETUP_FRAME: {
833  // keep ignoring the data until a frame is collected
834  break;
835  }
836  case WAIT4_TEST_TEARDOWN_FRAME: {
837  // keep ignoring the data until a frame is collected
838  break;
839  }
840  case WAIT4_TEST_CONTINUE_FRAME: {
841  // keep ignoring the data until a frame is collected
842  break;
843  }
844  case WAIT4_TEST_PROBE_DATA: {
845  l_rx.var.tp.data |=
846  (static_cast<QSFun>(b) << l_rx.var.tp.idx);
847  l_rx.var.tp.idx += 8U;
848  if (l_rx.var.tp.idx == (8U * sizeof(std::uint32_t))) {
849  l_rx.var.tp.addr = 0U;
850  l_rx.var.tp.idx = 0U;
851  tran_(WAIT4_TEST_PROBE_ADDR);
852  }
853  break;
854  }
855  case WAIT4_TEST_PROBE_ADDR: {
856  l_rx.var.tp.addr |=
857  (static_cast<std::uint32_t>(b) << l_rx.var.tp.idx);
858  l_rx.var.tp.idx += 8U;
859  if (l_rx.var.tp.idx
860  == (8U * static_cast<unsigned>(QS_FUN_PTR_SIZE)))
861  {
862  tran_(WAIT4_TEST_PROBE_FRAME);
863  }
864  break;
865  }
866  case WAIT4_TEST_PROBE_FRAME: {
867  // keep ignoring the data until a frame is collected
868  break;
869  }
870 #endif // Q_UTEST
871 
872  case ERROR_STATE: {
873  // keep ignoring the data until a good frame is collected
874  break;
875  }
876  default: { // unexpected or unimplemented state
877  rxReportError_(0x45U);
878  tran_(ERROR_STATE);
879  break;
880  }
881  }
882 }
883 
884 //****************************************************************************
886  std::uint8_t i;
887  std::uint8_t *ptr;
889 
890  switch (state) {
891  case WAIT4_INFO_FRAME: {
892  // no need to report Ack or Done
893  QS_CRIT_E_();
894  QS_target_info_(0U); // send only Target info
895  QS_CRIT_X_();
896  break;
897  }
898  case WAIT4_RESET_FRAME: {
899  // no need to report Ack or Done, because Target resets
900  QS::onReset(); // reset the Target
901  break;
902  }
903  case WAIT4_CMD_PARAM1: // intentionally fall-through
904  case WAIT4_CMD_PARAM2: // intentionally fall-through
905  case WAIT4_CMD_PARAM3: // intentionally fall-through
906  case WAIT4_CMD_FRAME: {
908  QS::onCommand(l_rx.var.cmd.cmdId, l_rx.var.cmd.param1,
909  l_rx.var.cmd.param2, l_rx.var.cmd.param3);
910 #ifdef Q_UTEST
911  QS::processTestEvts_(); // process all events produced
912 #endif
914  break;
915  }
916  case WAIT4_TICK_FRAME: {
918 #ifdef Q_UTEST
919  QS::tickX_(l_rx.var.tick.rate, &QS::rxPriv_); // process tick
920  QS::processTestEvts_(); // process all events produced
921 #else
922  QF::tickX_(static_cast<std::uint_fast8_t>(l_rx.var.tick.rate),
923  &QS::rxPriv_);
924 #endif
926  break;
927  }
928  case WAIT4_PEEK_FRAME: {
929  // no need to report Ack or Done
930  QS_CRIT_E_();
932  ptr = (static_cast<std::uint8_t*>(
934  + l_rx.var.peek.offs);
935  QS_TIME_PRE_(); // timestamp
936  QS_U16_PRE_(l_rx.var.peek.offs); // data offset
937  QS_U8_PRE_(l_rx.var.peek.size); // data size
938  QS_U8_PRE_(l_rx.var.peek.num); // number of data items
939  for (i = 0U; i < l_rx.var.peek.num; ++i) {
940  switch (l_rx.var.peek.size) {
941  case 1:
942  QS_U8_PRE_(*(ptr + i));
943  break;
944  case 2:
945  QS_U16_PRE_(
946  *(reinterpret_cast<std::uint16_t*>(ptr) + i));
947  break;
948  case 4:
949  QS_U32_PRE_(
950  *(reinterpret_cast<std::uint32_t*>(ptr) + i));
951  break;
952  default:
953  break;
954  }
955  }
956  QS::endRec_();
957  QS_CRIT_X_();
958 
959  QS_REC_DONE(); // user callback (if defined)
960  break;
961  }
962  case WAIT4_POKE_DATA: {
963  // received less than expected poke data items
964  rxReportError_(static_cast<std::uint8_t>(QS_RX_POKE));
965  break;
966  }
967  case WAIT4_POKE_FRAME: {
969  // no need to report done
970  break;
971  }
972  case WAIT4_FILL_FRAME: {
974  ptr = (static_cast<std::uint8_t *>(
976  + l_rx.var.poke.offs);
977  for (i = 0U; i < l_rx.var.poke.num; ++i) {
978  switch (l_rx.var.poke.size) {
979  case 1:
980  *(ptr + i) =
981  static_cast<std::uint8_t>(l_rx.var.poke.data);
982  break;
983  case 2:
984  *(reinterpret_cast<std::uint16_t *>(ptr) + i) =
985  static_cast<std::uint16_t>(l_rx.var.poke.data);
986  break;
987  case 4:
988  *(reinterpret_cast<std::uint32_t *>(ptr) + i) =
989  l_rx.var.poke.data;
990  break;
991  default:
992  break;
993  }
994  }
995  break;
996  }
997  case WAIT4_FILTER_FRAME: {
998  rxReportAck_(static_cast<enum QSpyRxRecords>(l_rx.var.flt.recId));
999 
1000  // apply the received filters
1001  if (l_rx.var.flt.recId
1002  == static_cast<std::uint8_t>(QS_RX_GLB_FILTER))
1003  {
1004  for (i = 0U;
1005  i < static_cast<std::uint8_t>(sizeof(priv_.glbFilter));
1006  ++i)
1007  {
1008  priv_.glbFilter[i] = l_rx.var.flt.data[i];
1009  }
1010  // leave the "not maskable" filters enabled,
1011  // see qs.h, Miscellaneous QS records (not maskable)
1012  //
1013  priv_.glbFilter[0] |= 0x01U;
1014  priv_.glbFilter[7] |= 0xFCU;
1015  priv_.glbFilter[8] |= 0x7FU;
1016 
1017  // never enable the last 3 records (0x7D, 0x7E, 0x7F)
1018  priv_.glbFilter[15] &= 0x1FU;
1019  }
1020  else if (l_rx.var.flt.recId
1021  == static_cast<std::uint8_t>(QS_RX_LOC_FILTER))
1022  {
1023  for (i = 0U; i < Q_DIM(priv_.locFilter); ++i) {
1024  priv_.locFilter[i] = l_rx.var.flt.data[i];
1025  }
1026  // leave QS_ID == 0 always on
1027  priv_.locFilter[0] |= 0x01U;
1028  }
1029  else {
1030  rxReportError_(l_rx.var.flt.recId);
1031  }
1032 
1033  // no need to report Done
1034  break;
1035  }
1036  case WAIT4_OBJ_FRAME: {
1037  i = l_rx.var.obj.kind;
1038  if (i < static_cast<std::uint8_t>(QS::MAX_OBJ)) {
1039  if (l_rx.var.obj.recId
1040  == static_cast<std::uint8_t>(QS_RX_CURR_OBJ))
1041  {
1042  rxPriv_.currObj[i] =
1043  reinterpret_cast<void *>(l_rx.var.obj.addr);
1045  }
1046  else if (l_rx.var.obj.recId
1047  == static_cast<std::uint8_t>(QS_RX_AO_FILTER))
1048  {
1049  if (l_rx.var.obj.addr != 0U) {
1050  std::int_fast16_t filter =
1051  static_cast<std::int_fast16_t>(
1052  reinterpret_cast<QActive *>(
1053  l_rx.var.obj.addr)->m_prio);
1054  locFilter_((i == 0)
1055  ? filter
1056  :-filter);
1058  }
1059  else {
1061  }
1062  }
1063  else {
1064  rxReportError_(l_rx.var.obj.recId);
1065  }
1066  }
1067  // both SM and AO
1068  else if (i == static_cast<std::uint8_t>(QS::SM_AO_OBJ)) {
1069  if (l_rx.var.obj.recId
1070  == static_cast<std::uint8_t>(QS_RX_CURR_OBJ))
1071  {
1072  rxPriv_.currObj[SM_OBJ] = (void *)l_rx.var.obj.addr;
1073  rxPriv_.currObj[AO_OBJ] = (void *)l_rx.var.obj.addr;
1074  }
1075  rxReportAck_(
1076  static_cast<enum QSpyRxRecords>(l_rx.var.obj.recId));
1077  }
1078  else {
1079  rxReportError_(l_rx.var.obj.recId);
1080  }
1081  break;
1082  }
1083  case WAIT4_QUERY_FRAME: {
1084  queryCurrObj(l_rx.var.obj.kind);
1085  break;
1086  }
1087  case WAIT4_EVT_FRAME: {
1088  // NOTE: Ack was already reported in the WAIT4_EVT_LEN state
1089 #ifdef Q_UTEST
1090  QS::onTestEvt(l_rx.var.evt.e); // "massage" the event, if needed
1091 #endif // Q_UTEST
1092  // use 'i' as status, 0 == success,no-recycle
1093  i = 0U;
1094 
1095  if (l_rx.var.evt.prio == 0U) { // publish
1096  QF::publish_(l_rx.var.evt.e, &QS::rxPriv_, 0U);
1097  }
1098  else if (l_rx.var.evt.prio < QF_MAX_ACTIVE) {
1099  if (!QF::active_[l_rx.var.evt.prio]->POST_X(
1100  l_rx.var.evt.e,
1101  0U, // margin
1102  &QS::rxPriv_))
1103  {
1104  // failed QACTIVE_POST() recycles the event
1105  i = 0x80U; // failure, no recycle
1106  }
1107  }
1108  else if (l_rx.var.evt.prio == 255U) {
1109  // dispatch to the current SM object
1110  if (QS::rxPriv_.currObj[QS::SM_OBJ] != nullptr) {
1111  // increment the ref-ctr to simulate the situation
1112  // when the event is just retreived from a queue.
1113  // This is expected for the following QF::gc() call.
1114  //
1115  QF_EVT_REF_CTR_INC_(l_rx.var.evt.e);
1116 
1117  static_cast<QHsm *>(QS::rxPriv_.currObj[QS::SM_OBJ])
1118  ->dispatch(l_rx.var.evt.e, 0U);
1119  i = 0x01U; // success, recycle
1120  }
1121  else {
1122  i = 0x81U; // failure, recycle
1123  }
1124  }
1125  else if (l_rx.var.evt.prio == 254U) {
1126  // init the current SM object"
1127  if (QS::rxPriv_.currObj[QS::SM_OBJ] != nullptr) {
1128  // increment the ref-ctr to simulate the situation
1129  // when the event is just retreived from a queue.
1130  // This is expected for the following QF::gc() call.
1131  //
1132  QF_EVT_REF_CTR_INC_(l_rx.var.evt.e);
1133 
1134  static_cast<QHsm *>(QS::rxPriv_.currObj[QS::SM_OBJ])
1135  ->init(l_rx.var.evt.e, 0U);
1136  i = 0x01U; // success, recycle
1137  }
1138  else {
1139  i = 0x81U; // failure, recycle
1140  }
1141  }
1142  else if (l_rx.var.evt.prio == 253U) {
1143  // post to the current AO
1144  if (QS::rxPriv_.currObj[QS::AO_OBJ] != nullptr) {
1145  if (!static_cast<QActive *>(
1146  QS::rxPriv_.currObj[QS::AO_OBJ])->POST_X(
1147  l_rx.var.evt.e,
1148  0U, // margin
1149  &QS::rxPriv_))
1150  {
1151  // failed QACTIVE_POST() recycles the event
1152  i = 0x80U; // failure, no recycle
1153  }
1154  }
1155  else {
1156  i = 0x81U; // failure, recycle
1157  }
1158  }
1159  else {
1160  i = 0x81U; // failure, recycle
1161  }
1162 
1163  // recycle needed?
1164  if ((i & 1U) != 0U) {
1165  QF::gc(l_rx.var.evt.e);
1166  }
1167  // failure?
1168  if ((i & 0x80U) != 0U) {
1169  rxReportError_(static_cast<std::uint8_t>(QS_RX_EVENT));
1170  }
1171  else {
1172 #ifdef Q_UTEST
1173  QS::processTestEvts_(); // process all events produced
1174 #endif
1176  }
1177  break;
1178  }
1179 
1180 #ifdef Q_UTEST
1181  case WAIT4_TEST_SETUP_FRAME: {
1183  l_testData.tpNum = 0U; // clear Test-Probes
1184  l_testData.testTime = 0U; //clear time tick
1185  // don't clear current objects
1186  QS::onTestSetup(); // application-specific test setup
1187  // no need to report Done
1188  break;
1189  }
1190  case WAIT4_TEST_TEARDOWN_FRAME: {
1192  QS::onTestTeardown(); // application-specific test teardown
1193  // no need to report Done
1194  break;
1195  }
1196  case WAIT4_TEST_CONTINUE_FRAME: {
1198  QS::rxPriv_.inTestLoop = false; // exit the QUTest loop
1199  // no need to report Done
1200  break;
1201  }
1202  case WAIT4_TEST_PROBE_FRAME: {
1204  Q_ASSERT_ID(815,
1205  l_testData.tpNum
1206  < (sizeof(l_testData.tpBuf) / sizeof(l_testData.tpBuf[0])));
1207  l_testData.tpBuf[l_testData.tpNum] = l_rx.var.tp;
1208  ++l_testData.tpNum;
1209  // no need to report Done
1210  break;
1211  }
1212 #endif // Q_UTEST
1213 
1214  case ERROR_STATE: {
1215  // keep ignoring all bytes until new frame
1216  break;
1217  }
1218  default: {
1219  rxReportError_(0x47U);
1220  break;
1221  }
1222  }
1223 }
1224 
1225 //****************************************************************************
1226 static void rxHandleBadFrame_(std::uint8_t const state) noexcept {
1227  rxReportError_(0x50U); // error for all bad frames
1228  switch (state) {
1229  case WAIT4_EVT_FRAME: {
1230  Q_ASSERT_ID(910, l_rx.var.evt.e != nullptr);
1231  QF::gc(l_rx.var.evt.e); // don't leak an allocated event
1232  break;
1233  }
1234  default: {
1235  break;
1236  }
1237  }
1238 }
1239 
1240 //****************************************************************************
1241 static void rxReportAck_(enum QSpyRxRecords const recId) noexcept {
1243  QS_CRIT_E_();
1245  QS_U8_PRE_(recId); // record ID
1246  QS::endRec_();
1247  QS_CRIT_X_();
1248 
1249  QS_REC_DONE(); // user callback (if defined)
1250 }
1251 
1252 //****************************************************************************
1253 static void rxReportError_(std::uint8_t const code) noexcept {
1255  QS_CRIT_E_();
1257  QS_U8_PRE_(0x80U | code); // error code
1258  QS::endRec_();
1259  QS_CRIT_X_();
1260 
1261  QS_REC_DONE(); // user callback (if defined)
1262 }
1263 
1264 //****************************************************************************
1265 static void rxReportDone_(enum QSpyRxRecords const recId) noexcept {
1267  QS_CRIT_E_();
1269  QS_TIME_PRE_(); // timestamp
1270  QS_U8_PRE_(recId); // record ID
1271  QS::endRec_();
1272  QS_CRIT_X_();
1273 
1274  QS_REC_DONE(); // user callback (if defined)
1275 }
1276 
1277 //****************************************************************************
1278 static void rxPoke_(void) noexcept {
1279  std::uint8_t * const ptr =
1280  (static_cast<std::uint8_t *>(QS::rxPriv_.currObj[QS::AP_OBJ])
1281  + l_rx.var.poke.offs);
1282  switch (l_rx.var.poke.size) {
1283  case 1:
1284  *ptr = static_cast<std::uint8_t>(l_rx.var.poke.data);
1285  break;
1286  case 2:
1287  *reinterpret_cast<std::uint16_t *>(ptr)
1288  = static_cast<std::uint16_t>(l_rx.var.poke.data);
1289  break;
1290  case 4:
1291  *reinterpret_cast<std::uint32_t *>(ptr) = l_rx.var.poke.data;
1292  break;
1293  default:
1294  Q_ERROR_ID(900);
1295  break;
1296  }
1297 
1298  l_rx.var.poke.data = 0U;
1299  l_rx.var.poke.idx = 0U;
1300  l_rx.var.poke.offs += static_cast<std::uint16_t>(l_rx.var.poke.size);
1301 }
1302 
1303 //============================================================================
1304 #ifdef Q_UTEST
1305 
1306 //****************************************************************************
1318 std::uint32_t QS::getTestProbe_(void (* const api)(void)) noexcept {
1319  std::uint32_t data = 0U;
1320  for (std::uint8_t i = 0U; i < l_testData.tpNum; ++i) {
1321  if (l_testData.tpBuf[i].addr == reinterpret_cast<QSFun>(api)) {
1322  data = l_testData.tpBuf[i].data;
1323 
1325  QS_CRIT_E_();
1327  QS_TIME_PRE_(); // timestamp
1328  QS_FUN_PRE_(api); // the calling API
1329  QS_U32_PRE_(data); // the Test-Probe data
1330  QS::endRec_();
1331  QS_CRIT_X_();
1332 
1333  QS_REC_DONE(); // user callback (if defined)
1334 
1335  --l_testData.tpNum; // one less Test-Probe
1336  // move all remaining entries in the buffer up by one
1337  for (std::uint8_t j = i; j < l_testData.tpNum; ++j) {
1338  l_testData.tpBuf[j] = l_testData.tpBuf[j + 1U];
1339  }
1340  break; // we are done (Test-Probe retreived)
1341  }
1342  }
1343  return data;
1344 }
1345 
1346 //****************************************************************************
1348  return (++l_testData.testTime);
1349 }
1350 
1351 #endif // Q_UTEST
1352 
1353 } // namespace QP
1354 
unsigned int uint16_t
exact-width 16-bit unsigned int
Definition: 16bit/stdint.h:30
unsigned int uint_fast16_t
fast at-least 16-bit unsigned int
Definition: 16bit/stdint.h:38
unsigned long int uint32_t
exact-width 32-bit unsigned int
Definition: 16bit/stdint.h:31
signed int int_fast16_t
fast at-least 16-bit signed int
Definition: 16bit/stdint.h:37
unsigned long long uint64_t
exact-width 64-bit unsigned int
Definition: 16bit/stdint.h:32
unsigned char uint8_t
exact-width 8-bit unsigned int
Definition: 16bit/stdint.h:29
unsigned int uint_fast8_t
fast at-least 8-bit unsigned int
Definition: 16bit/stdint.h:36
QActive active object (based on QP::QHsm implementation)
Definition: qf.hpp:144
Native QF Event Queue class.
Definition: qequeue.hpp:123
static void gc(QEvt const *const e) noexcept
Recycle a dynamic event.
Definition: qf_dyn.cpp:219
static QEvt * newX_(std::uint_fast16_t const evtSize, std::uint_fast16_t const margin, enum_t const sig) noexcept
Internal QF implementation of creating new dynamic event.
Definition: qf_dyn.cpp:140
static QActive * active_[QF_MAX_ACTIVE+1U]
array of registered active objects
Definition: qf.hpp:580
static std::uint_fast16_t poolGetMaxBlockSize(void) noexcept
Obtain the block size of any registered event pools.
Definition: qf_dyn.cpp:345
static void tickX_(std::uint_fast8_t const tickRate, void const *const sender) noexcept
Processes all armed time events at every clock tick.
Definition: qf_time.cpp:78
static void publish_(QEvt const *const e, void const *const sender, std::uint_fast8_t const qs_id) noexcept
Publish event to the framework.
Definition: qf_ps.cpp:121
Hierarchical State Machine base class.
Definition: qep.hpp:269
Native QF memory pool class.
Definition: qmpool.hpp:106
void * currObj[MAX_OBJ]
current objects
Definition: qs.hpp:557
static struct QP::QS::QSrxPriv rxPriv_
static void setCurrObj(std::uint8_t obj_kind, void *obj_ptr) noexcept
Set the "current object" in the Target.
Definition: qs_rx.cpp:302
static QS priv_
Definition: qs.hpp:554
static QSTimeCtr onGetTime(void)
Callback to obtain a timestamp for a QS record.
Definition: qs_rx.cpp:1347
static void rxHandleGoodFrame_(std::uint8_t const state)
internal function to handle incoming (QS-RX) packet
Definition: qs_rx.cpp:885
static void onTestTeardown(void)
callback to teardown after a unit test inside the Target
static std::uint32_t getTestProbe_(void(*const api)(void)) noexcept
internal function to get the Test-Probe for a given API
Definition: qs_rx.cpp:1318
static void beginRec_(std::uint_fast8_t const rec) noexcept
Mark the begin of a QS record rec.
Definition: qs.cpp:410
static void onTestSetup(void)
callback to setup a unit test inside the Target
@ SM_OBJ
state machine object for QEP
Definition: qs.hpp:515
@ EQ_OBJ
raw queue object
Definition: qs.hpp:518
@ AO_OBJ
active object
Definition: qs.hpp:516
@ TE_OBJ
time event object
Definition: qs.hpp:519
@ MAX_OBJ
Definition: qs.hpp:521
@ AP_OBJ
generic Application-specific object
Definition: qs.hpp:520
@ MP_OBJ
event pool object
Definition: qs.hpp:517
std::uint8_t locFilter[16]
lobal on/off QS filter
Definition: qs.hpp:541
static void onReset(void)
callback function to reset the Target (to be implemented in the BSP)
static void endRec_(void) noexcept
Mark the end of a QS record rec.
Definition: qs.cpp:436
QSCtr head
offset to where next byte will be inserted
Definition: qs.hpp:560
bool inTestLoop
QUTest event loop is running.
Definition: qs.hpp:564
static void processTestEvts_(void)
internal function to process posted events during test
Definition: qutest.cpp:270
QSCtr end
offset of the end of the ring buffer
Definition: qs.hpp:559
static std::uint16_t rxGetNfree(void) noexcept
Obtain the number of free bytes in the QS RX data buffer.
Definition: qs_rx.cpp:283
static void locFilter_(std::int_fast16_t const filter) noexcept
Set/clear the local Filter for a given object-id.
Definition: qs.cpp:346
std::uint8_t glbFilter[16]
global on/off QS filter
Definition: qs.hpp:540
static void queryCurrObj(std::uint8_t obj_kind) noexcept
Query the "current object" in the Target.
Definition: qs_rx.cpp:314
static void onCommand(std::uint8_t cmdId, std::uint32_t param1, std::uint32_t param2, std::uint32_t param3)
Callback function to execute user commands (to be implemented in BSP)
static void rxInitBuf(std::uint8_t *const sto, std::uint16_t const stoSize) noexcept
Initialize the QS RX data buffer.
Definition: qs_rx.cpp:243
QSCtr tail
offset of where next record will be extracted
Definition: qs.hpp:546
@ SM_AO_OBJ
combination of SM and AO
Definition: qs.hpp:525
static void tickX_(std::uint_fast8_t const tickRate, void const *const sender) noexcept
internal function to process armed time events during test
Definition: qutest.cpp:302
std::uint8_t * buf
pointer to the start of the ring buffer
Definition: qs.hpp:558
static void rxParse(void)
Parse all bytes present in the QS RX data buffer.
Definition: qs_rx.cpp:370
static void onTestEvt(QEvt *e)
callback to "massage" the test event before dispatching/posting it
Time Event class.
Definition: qf.hpp:404
namespace associated with the QP/C++ framework
Definition: struct.dox:1
constexpr std::uint8_t QS_ESC
Escape character of the QS output protocol.
Definition: qs_pkg.hpp:258
void QS_target_info_(std::uint8_t const isReset) noexcept
send the Target info (object sizes, build time-stamp, QP version)
Definition: qs.cpp:464
static void rxReportAck_(enum QSpyRxRecords const recId) noexcept
Definition: qs_rx.cpp:1241
@ QS_TEST_PROBE_GET
reports that Test-Probe has been used
Definition: qs.hpp:151
@ QS_TARGET_DONE
reports completion of a user callback
Definition: qs.hpp:157
@ QS_OBJ_DICT
object dictionary entry
Definition: qs.hpp:153
@ QS_RX_STATUS
reports QS data receive status
Definition: qs.hpp:158
@ QS_QUERY_DATA
reports the data from "current object" query
Definition: qs.hpp:159
@ QS_PEEK_DATA
reports the data from the PEEK query
Definition: qs.hpp:160
static void rxReportDone_(enum QSpyRxRecords const recId) noexcept
Definition: qs_rx.cpp:1265
void QF_EVT_REF_CTR_INC_(QEvt const *const e) noexcept
increment the refCtr_ of an event e
Definition: qf_pkg.hpp:150
static void rxReportError_(std::uint8_t const code) noexcept
Definition: qs_rx.cpp:1253
static void rxPoke_(void) noexcept
Definition: qs_rx.cpp:1278
static void rxParseData_(std::uint8_t const b) noexcept
Definition: qs_rx.cpp:415
constexpr std::uint8_t QS_ESC_XOR
Escape modifier of the QS output protocol.
Definition: qs_pkg.hpp:264
static void rxHandleBadFrame_(std::uint8_t const state) noexcept
Definition: qs_rx.cpp:1226
constexpr std::uint8_t QS_GOOD_CHKSUM
Escape character of the QS output protocol.
Definition: qs_pkg.hpp:267
std::uint_fast16_t QSCtr
QS ring buffer counter and offset type.
Definition: qs.hpp:292
constexpr std::uint8_t QS_FRAME
Frame character of the QS output protocol.
Definition: qs_pkg.hpp:255
QSpyRxRecords
Quantum Spy Receive (RX) record types.
Definition: qs.hpp:575
@ QS_RX_RESET
reset the Target
Definition: qs.hpp:578
@ QS_RX_EVENT
inject an event to the Target (post/publish)
Definition: qs.hpp:592
@ QS_RX_LOC_FILTER
set local filters in the Target
Definition: qs.hpp:587
@ QS_RX_FILL
fill Target memory
Definition: qs.hpp:582
@ QS_RX_AO_FILTER
set local AO filter in the Target
Definition: qs.hpp:588
@ QS_RX_TICK
call QF_tick()
Definition: qs.hpp:579
@ QS_RX_PEEK
peek Target memory
Definition: qs.hpp:580
@ QS_RX_CURR_OBJ
set the "current-object" in the Target
Definition: qs.hpp:589
@ QS_RX_GLB_FILTER
set global filters in the Target
Definition: qs.hpp:586
@ QS_RX_POKE
poke Target memory
Definition: qs.hpp:581
@ QS_RX_INFO
query Target info (ver, config, tstamp)
Definition: qs.hpp:576
@ QS_RX_TEST_TEARDOWN
test teardown
Definition: qs.hpp:584
@ QS_RX_TEST_PROBE
set a Test-Probe in the Target
Definition: qs.hpp:585
@ QS_RX_TEST_SETUP
test setup
Definition: qs.hpp:583
@ QS_RX_COMMAND
execute a user-defined command in the Target
Definition: qs.hpp:577
@ QS_RX_TEST_CONTINUE
continue a test after QS_RX_TEST_WAIT()
Definition: qs.hpp:590
@ QS_RX_QUERY_CURR
query the "current object" in the Target
Definition: qs.hpp:591
std::uint16_t QSignal
QSignal represents the signal of an event.
Definition: qep.hpp:146
std::uint8_t QSTimeCtr
Definition: qs.hpp:281
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Define the user-specified module name for assertions in this file.
Definition: qassert.h:120
#define Q_ASSERT_ID(id_, test_)
General purpose assertion with user-specified assertion-id.
Definition: qassert.h:155
#define Q_REQUIRE_ID(id_, test_)
Assertion for checking preconditions with user-specified assertion-id.
Definition: qassert.h:279
#define Q_DIM(array_)
Helper macro to calculate static dimension of a 1-dim array_.
Definition: qassert.h:337
#define Q_ERROR_ID(id_)
Assertion with user-specified assertion-id for a wrong path.
Definition: qassert.h:211
int enum_t
alias for enumerations used for event signals
Definition: qep.hpp:82
#define Q_SIGNAL_SIZE
The size (in bytes) of the signal of an event. Valid values: 1U, 2U, or 4U; default 2U.
Definition: qep.hpp:65
Internal (package scope) QF/C++ interface.
#define QS_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qs.hpp:783
#define QS_TIME_PRE_()
Definition: qs.hpp:266
#define QS_REC_DONE()
macro to hook up user code when a QS record is produced
Definition: qs.hpp:740
#define QS_CRIT_X_()
This is an internal macro for exiting a critical section.
Definition: qs.hpp:803
#define QS_CRIT_E_()
This is an internal macro for entering a critical section.
Definition: qs.hpp:793
#define QS_U8_PRE_(data_)
Definition: qs_dummy.hpp:100
#define QS_OBJ_PRE_(obj_)
Definition: qs_dummy.hpp:107
#define QS_FUN_PRE_(fun_)
Definition: qs_dummy.hpp:108
#define QS_MPC_PRE_(ctr_)
Definition: qs_dummy.hpp:110
#define QS_TEC_PRE_(ctr_)
Definition: qs_dummy.hpp:112
#define QS_U16_PRE_(data_)
Definition: qs_dummy.hpp:102
#define QS_SIG_PRE_(sig_)
Definition: qs_dummy.hpp:105
#define QS_EQC_PRE_(ctr_)
Definition: qs_dummy.hpp:109
#define QS_U32_PRE_(data_)
Definition: qs_dummy.hpp:103
Internal (package scope) QS/C++ interface.
#define QS_STR_PRE_(msg_)
Internal QS macro to output a zero-terminated ASCII string data element.
Definition: qs_pkg.hpp:137
#define QS_FUN_PTR_SIZE
Definition: qs_port.h:50
#define QS_OBJ_PTR_SIZE
Definition: qs_port.h:47
QS/C++ port to a 32-bit CPU, generic compiler.
#define QF_MAX_ACTIVE
The maximum number of active objects in the application.
Definition: qxk/qf_port.hpp:57
QEvt base class.
Definition: qep.hpp:209