QP/C++ 6.9.3
qs.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 "qstamp.hpp" // QP time-stamp
43 #include "qassert.h" // QP assertions
44 
45 namespace QP {
46 
48 
49 //****************************************************************************
50 QS QS::priv_; // QS private data
51 
52 //****************************************************************************
71 void QS::initBuf(std::uint8_t * const sto,
72  std::uint_fast16_t const stoSize) noexcept
73 {
74  // the provided buffer must be at least 8 bytes long
75  Q_REQUIRE_ID(100, stoSize > 8U);
76 
77  // This function initializes all the internal QS variables, so that the
78  // tracing can start correctly even if the startup code fails to clear
79  // any uninitialized data (as is required by the C Standard).
80  //
81  glbFilter_(-QS_ALL_RECORDS); // all global filters OFF
82  locFilter_(QS_ALL_IDS); // all local filters ON
83  priv_.locFilter_AP = nullptr; // deprecated "AP-filter"
84 
85  priv_.buf = sto;
86  priv_.end = static_cast<QSCtr>(stoSize);
87  priv_.head = 0U;
88  priv_.tail = 0U;
89  priv_.used = 0U;
90  priv_.seq = 0U;
91  priv_.chksum = 0U;
92  priv_.critNest = 0U;
93 
94  // produce an empty record to "flush" the QS trace buffer
95  beginRec_(QS_REC_NUM_(QS_EMPTY));
96  endRec_();
97 
98  // produce the Target info QS record
99  QS_target_info_(0xFFU);
100 
101  // wait with flushing after successfull initialization (see QS_INIT())
102 }
103 
104 //****************************************************************************
121 void QS::glbFilter_(std::int_fast16_t const filter) noexcept {
122  bool const isRemove = (filter < 0);
123  std::uint16_t const rec = isRemove
124  ? static_cast<std::uint16_t>(-filter)
125  : static_cast<std::uint16_t>(filter);
126  switch (rec) {
127  case QS_ALL_RECORDS: {
128  std::uint8_t const tmp = (isRemove ? 0x00U : 0xFFU);
130  // set all global filters (partially unrolled loop)
131  for (i = 0U; i < Q_DIM(priv_.glbFilter); i += 4U) {
132  priv_.glbFilter[i ] = tmp;
133  priv_.glbFilter[i + 1U] = tmp;
134  priv_.glbFilter[i + 2U] = tmp;
135  priv_.glbFilter[i + 3U] = tmp;
136  }
137  if (isRemove) {
138  // leave the "not maskable" filters enabled,
139  // see qs.h, Miscellaneous QS records (not maskable)
140  //
141  priv_.glbFilter[0] = 0x01U;
142  priv_.glbFilter[7] = 0xFCU;
143  priv_.glbFilter[8] = 0x7FU;
144  }
145  else {
146  // never turn the last 3 records on (0x7D, 0x7E, 0x7F)
147  priv_.glbFilter[15] = 0x1FU;
148  }
149  break;
150  }
151  case QS_SM_RECORDS:
152  if (isRemove) {
153  priv_.glbFilter[0] &=
154  static_cast<std::uint8_t>(~0xFEU & 0xFFU);
155  priv_.glbFilter[1] &=
156  static_cast<std::uint8_t>(~0x03U & 0xFFU);
157  priv_.glbFilter[6] &=
158  static_cast<std::uint8_t>(~0x80U & 0xFFU);
159  priv_.glbFilter[7] &=
160  static_cast<std::uint8_t>(~0x03U & 0xFFU);
161  }
162  else {
163  priv_.glbFilter[0] |= 0xFEU;
164  priv_.glbFilter[1] |= 0x03U;
165  priv_.glbFilter[6] |= 0x80U;
166  priv_.glbFilter[7] |= 0x03U;
167  }
168  break;
169  case QS_AO_RECORDS:
170  if (isRemove) {
171  priv_.glbFilter[1] &=
172  static_cast<std::uint8_t>(~0xFCU & 0xFFU);
173  priv_.glbFilter[2] &=
174  static_cast<std::uint8_t>(~0x07U & 0xFFU);
175  priv_.glbFilter[5] &=
176  static_cast<std::uint8_t>(~0x20U & 0xFFU);
177  }
178  else {
179  priv_.glbFilter[1] |= 0xFCU;
180  priv_.glbFilter[2] |= 0x07U;
181  priv_.glbFilter[5] |= 0x20U;
182  }
183  break;
184  case QS_EQ_RECORDS:
185  if (isRemove) {
186  priv_.glbFilter[2] &=
187  static_cast<std::uint8_t>(~0x78U & 0xFFU);
188  priv_.glbFilter[5] &=
189  static_cast<std::uint8_t>(~0x40U & 0xFFU);
190  }
191  else {
192  priv_.glbFilter[2] |= 0x78U;
193  priv_.glbFilter[5] |= 0x40U;
194  }
195  break;
196  case QS_MP_RECORDS:
197  if (isRemove) {
198  priv_.glbFilter[3] &=
199  static_cast<std::uint8_t>(~0x03U & 0xFFU);
200  priv_.glbFilter[5] &=
201  static_cast<std::uint8_t>(~0x80U & 0xFFU);
202  }
203  else {
204  priv_.glbFilter[3] |= 0x03U;
205  priv_.glbFilter[5] |= 0x80U;
206  }
207  break;
208  case QS_QF_RECORDS:
209  if (isRemove) {
210  priv_.glbFilter[2] &=
211  static_cast<std::uint8_t>(~0x80U & 0xFFU);
212  priv_.glbFilter[3] &=
213  static_cast<std::uint8_t>(~0xFCU & 0xFFU);
214  priv_.glbFilter[4] &=
215  static_cast<std::uint8_t>(~0xC0U & 0xFFU);
216  priv_.glbFilter[5] &=
217  static_cast<std::uint8_t>(~0x1FU & 0xFFU);
218  }
219  else {
220  priv_.glbFilter[2] |= 0x80U;
221  priv_.glbFilter[3] |= 0xFCU;
222  priv_.glbFilter[4] |= 0xC0U;
223  priv_.glbFilter[5] |= 0x1FU;
224  }
225  break;
226  case QS_TE_RECORDS:
227  if (isRemove) {
228  priv_.glbFilter[4] &=
229  static_cast<std::uint8_t>(~0x3FU & 0xFFU);
230  }
231  else {
232  priv_.glbFilter[4] |= 0x3FU;
233  }
234  break;
235  case QS_SC_RECORDS:
236  if (isRemove) {
237  priv_.glbFilter[6] &=
238  static_cast<std::uint8_t>(~0x7FU & 0xFFU);
239  }
240  else {
241  priv_.glbFilter[6] |= 0x7FU;
242  }
243  break;
244  case QS_U0_RECORDS:
245  if (isRemove) {
246  priv_.glbFilter[12] &=
247  static_cast<std::uint8_t>(~0xF0U & 0xFFU);
248  priv_.glbFilter[13] &=
249  static_cast<std::uint8_t>(~0x01U & 0xFFU);
250  }
251  else {
252  priv_.glbFilter[12] |= 0xF0U;
253  priv_.glbFilter[13] |= 0x01U;
254  }
255  break;
256  case QS_U1_RECORDS:
257  if (isRemove) {
258  priv_.glbFilter[13] &=
259  static_cast<std::uint8_t>(~0x3EU & 0xFFU);
260  }
261  else {
262  priv_.glbFilter[13] |= 0x3EU;
263  }
264  break;
265  case QS_U2_RECORDS:
266  if (isRemove) {
267  priv_.glbFilter[13] &=
268  static_cast<std::uint8_t>(~0xC0U & 0xFFU);
269  priv_.glbFilter[14] &=
270  static_cast<std::uint8_t>(~0x07U & 0xFFU);
271  }
272  else {
273  priv_.glbFilter[13] |= 0xC0U;
274  priv_.glbFilter[14] |= 0x07U;
275  }
276  break;
277  case QS_U3_RECORDS:
278  if (isRemove) {
279  priv_.glbFilter[14] &=
280  static_cast<std::uint8_t>(~0xF8U & 0xFFU);
281  }
282  else {
283  priv_.glbFilter[14] |= 0xF8U;
284  }
285  break;
286  case QS_U4_RECORDS:
287  if (isRemove) {
288  priv_.glbFilter[15] &= 0x1FU;
289  }
290  else {
291  priv_.glbFilter[15] |= 0x1FU;
292  }
293  break;
294  case QS_UA_RECORDS:
295  if (isRemove) {
296  priv_.glbFilter[12] &=
297  static_cast<std::uint8_t>(~0xF0U & 0xFFU);
298  priv_.glbFilter[13] = 0U;
299  priv_.glbFilter[14] = 0U;
300  priv_.glbFilter[15] &=
301  static_cast<std::uint8_t>(~0x1FU & 0xFFU);
302  }
303  else {
304  priv_.glbFilter[12] |= 0xF0U;
305  priv_.glbFilter[13] |= 0xFFU;
306  priv_.glbFilter[14] |= 0xFFU;
307  priv_.glbFilter[15] |= 0x1FU;
308  }
309  break;
310  default:
311  // QS rec number can't exceed 0x7D, so no need for escaping
312  Q_ASSERT_ID(210, rec < 0x7DU);
313 
314  if (isRemove) {
315  priv_.glbFilter[rec >> 3U]
316  &= static_cast<std::uint8_t>(~(1U << (rec & 7U)) & 0xFFU);
317  }
318  else {
319  priv_.glbFilter[rec >> 3U]
320  |= static_cast<std::uint8_t>(1U << (rec & 7U));
321  // never turn the last 3 records on (0x7D, 0x7E, 0x7F)
322  priv_.glbFilter[15] &= 0x1FU;
323  }
324  break;
325  }
326 }
327 
328 //****************************************************************************
346 void QS::locFilter_(std::int_fast16_t const filter) noexcept {
347  bool const isRemove = (filter < 0);
348  std::uint16_t const qs_id = isRemove
349  ? static_cast<std::uint16_t>(-filter)
350  : static_cast<std::uint16_t>(filter);
351  std::uint8_t const tmp = (isRemove ? 0x00U : 0xFFU);
353  switch (qs_id) {
354  case QS_ALL_IDS:
355  // set all global filters (partially unrolled loop)
356  for (i = 0U; i < Q_DIM(priv_.locFilter); i += 4U) {
357  priv_.locFilter[i ] = tmp;
358  priv_.locFilter[i + 1U] = tmp;
359  priv_.locFilter[i + 2U] = tmp;
360  priv_.locFilter[i + 3U] = tmp;
361  }
362  break;
363  case QS_AO_IDS:
364  for (i = 0U; i < 8U; i += 4U) {
365  priv_.locFilter[i ] = tmp;
366  priv_.locFilter[i + 1U] = tmp;
367  priv_.locFilter[i + 2U] = tmp;
368  priv_.locFilter[i + 3U] = tmp;
369  }
370  break;
371  case QS_EP_IDS:
372  i = 8U;
373  priv_.locFilter[i ] = tmp;
374  priv_.locFilter[i + 1U] = tmp;
375  break;
376  case QS_AP_IDS:
377  i = 12U;
378  priv_.locFilter[i ] = tmp;
379  priv_.locFilter[i + 1U] = tmp;
380  priv_.locFilter[i + 2U] = tmp;
381  priv_.locFilter[i + 3U] = tmp;
382  break;
383  default:
384  if (qs_id < 0x7FU) {
385  if (isRemove) {
386  priv_.locFilter[qs_id >> 3U] &=
387  static_cast<std::uint8_t>(
388  ~(1U << (qs_id & 7U)) & 0xFFU);
389  }
390  else {
391  priv_.locFilter[qs_id >> 3U]
392  |= (1U << (qs_id & 7U));
393  }
394  }
395  else {
396  Q_ERROR_ID(310); // incorrect qs_id
397  }
398  break;
399  }
400  priv_.locFilter[0] |= 0x01U; // leave QS_ID == 0 always on
401 }
402 
403 //****************************************************************************
410 void QS::beginRec_(std::uint_fast8_t const rec) noexcept {
411  std::uint8_t const b = priv_.seq + 1U;
412  std::uint8_t chksum_ = 0U; // reset the checksum
413  std::uint8_t * const buf_ = priv_.buf; // put in a temporary (register)
414  QSCtr head_ = priv_.head; // put in a temporary (register)
415  QSCtr const end_ = priv_.end; // put in a temporary (register)
416 
417  priv_.seq = b; // store the incremented sequence num
418  priv_.used += 2U; // 2 bytes about to be added
419 
421 
422  chksum_ += static_cast<std::uint8_t>(rec);
423  QS_INSERT_BYTE_(static_cast<std::uint8_t>(rec)) // no need for escaping
424 
425  priv_.head = head_; // save the head
426  priv_.chksum = chksum_; // save the checksum
427 }
428 
429 //****************************************************************************
436 void QS::endRec_(void) noexcept {
437  std::uint8_t * const buf_ = priv_.buf; // put in a temporary (register)
438  QSCtr head_ = priv_.head;
439  QSCtr const end_ = priv_.end;
440  std::uint8_t b = priv_.chksum;
441  b ^= 0xFFU; // invert the bits in the checksum
442 
443  priv_.used += 2U; // 2 bytes about to be added
444 
445  if ((b != QS_FRAME) && (b != QS_ESC)) {
446  QS_INSERT_BYTE_(b)
447  }
448  else {
451  ++priv_.used; // account for the ESC byte
452  }
453 
454  QS_INSERT_BYTE_(QS_FRAME) // do not escape this QS_FRAME
455 
456  priv_.head = head_; // save the head
457  if (priv_.used > end_) { // overrun over the old data?
458  priv_.used = end_; // the whole buffer is used
459  priv_.tail = head_; // shift the tail to the old data
460  }
461 }
462 
463 //****************************************************************************
464 void QS_target_info_(std::uint8_t const isReset) noexcept {
465  static constexpr std::uint8_t ZERO = static_cast<std::uint8_t>('0');
466  static std::uint8_t const * const TIME =
467  reinterpret_cast<std::uint8_t const *>(&BUILD_TIME[0]);
468  static std::uint8_t const * const DATE =
469  reinterpret_cast<std::uint8_t const *>(&BUILD_DATE[0]);
470 
472  QS::u8_raw_(isReset);
473 
474  static union {
475  std::uint16_t u16;
476  std::uint8_t u8[2];
477  } endian_test;
478  endian_test.u16 = 0x0102U;
479  // big endian ? add the 0x8000U flag
480  QS_U16_PRE_(((endian_test.u8[0] == 0x01U)
481  ? (0x8000U | QP_VERSION)
482  : QP_VERSION)); // target endianness + version number
483 
484  // send the object sizes...
486  | static_cast<std::uint8_t>(QF_EVENT_SIZ_SIZE << 4U));
487 
488 #ifdef QF_EQUEUE_CTR_SIZE
490  | static_cast<std::uint8_t>(QF_TIMEEVT_CTR_SIZE << 4U));
491 #else
492  QS::u8_raw_(static_cast<std::uint8_t>(QF_TIMEEVT_CTR_SIZE << 4U));
493 #endif // ifdef QF_EQUEUE_CTR_SIZE
494 
495 #ifdef QF_MPOOL_CTR_SIZE
497  | static_cast<std::uint8_t>(QF_MPOOL_CTR_SIZE << 4U));
498 #else
499  QS::u8_raw_(0U);
500 #endif // ifdef QF_MPOOL_CTR_SIZE
501 
504 
505  // send the limits...
507  QS::u8_raw_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE << 4U));
508 
509  // send the build time in three bytes (sec, min, hour)...
510  QS::u8_raw_((10U * (TIME[6] - ZERO)) + (TIME[7] - ZERO));
511  QS::u8_raw_((10U * (TIME[3] - ZERO)) + (TIME[4] - ZERO));
512  if (BUILD_TIME[0] == ' ') {
513  QS::u8_raw_(TIME[1] - ZERO);
514  }
515  else {
516  QS::u8_raw_((10U * (TIME[0] - ZERO)) + (TIME[1] - ZERO));
517  }
518 
519  // send the build date in three bytes (day, month, year) ...
520  if (BUILD_DATE[4] == ' ') {
521  QS::u8_raw_(DATE[5] - ZERO);
522  }
523  else {
524  QS::u8_raw_((10U * (DATE[4] - ZERO)) + (DATE[5] - ZERO));
525  }
526  // convert the 3-letter month to a number 1-12 ...
527  std::uint8_t b;
528  switch (DATE[0] + DATE[1] + DATE[2]) {
529  case 'J' + 'a' +'n':
530  b = 1U;
531  break;
532  case 'F' + 'e' + 'b':
533  b = 2U;
534  break;
535  case 'M' + 'a' +'r':
536  b = 3U;
537  break;
538  case 'A' + 'p' + 'r':
539  b = 4U;
540  break;
541  case 'M' + 'a' + 'y':
542  b = 5U;
543  break;
544  case 'J' + 'u' + 'n':
545  b = 6U;
546  break;
547  case 'J' + 'u' + 'l':
548  b = 7U;
549  break;
550  case 'A' + 'u' + 'g':
551  b = 8U;
552  break;
553  case 'S' + 'e' + 'p':
554  b = 9U;
555  break;
556  case 'O' + 'c' + 't':
557  b = 10U;
558  break;
559  case 'N' + 'o' + 'v':
560  b = 11U;
561  break;
562  case 'D' + 'e' + 'c':
563  b = 12U;
564  break;
565  default:
566  b = 0U;
567  break;
568  }
569  QS::u8_raw_(b); // store the month
570  QS::u8_raw_((10U * (DATE[9] - ZERO)) + (DATE[10] - ZERO));
571  QS::endRec_();
572 }
573 
574 //****************************************************************************
579 void QS::u8_fmt_(std::uint8_t const format, std::uint8_t const d) noexcept {
580  std::uint8_t chksum_ = priv_.chksum; // put in a temporary (register)
581  std::uint8_t *const buf_ = priv_.buf; // put in a temporary (register)
582  QSCtr head_ = priv_.head; // put in a temporary (register)
583  QSCtr const end_= priv_.end; // put in a temporary (register)
584 
585  priv_.used += 2U; // 2 bytes about to be added
586 
587  QS_INSERT_ESC_BYTE_(format)
589 
590  priv_.head = head_; // save the head
591  priv_.chksum = chksum_; // save the checksum
592 }
593 
594 //****************************************************************************
599 void QS::u16_fmt_(std::uint8_t format, std::uint16_t d) noexcept {
600  std::uint8_t chksum_ = priv_.chksum; // put in a temporary (register)
601  std::uint8_t * const buf_ = priv_.buf; // put in a temporary (register)
602  QSCtr head_ = priv_.head; // put in a temporary (register)
603  QSCtr const end_= priv_.end; // put in a temporary (register)
604 
605  priv_.used += 3U; // 3 bytes about to be added
606 
607  QS_INSERT_ESC_BYTE_(format)
608 
609  format = static_cast<std::uint8_t>(d);
610  QS_INSERT_ESC_BYTE_(format)
611 
612  d >>= 8U;
613  format = static_cast<std::uint8_t>(d);
614  QS_INSERT_ESC_BYTE_(format)
615 
616  priv_.head = head_; // save the head
617  priv_.chksum = chksum_; // save the checksum
618 }
619 
620 //****************************************************************************
624 void QS::u32_fmt_(std::uint8_t format, std::uint32_t d) noexcept {
625  std::uint8_t chksum_ = priv_.chksum; // put in a temporary (register)
626  std::uint8_t * const buf_= priv_.buf; // put in a temporary (register)
627  QSCtr head_ = priv_.head; // put in a temporary (register)
628  QSCtr const end_= priv_.end; // put in a temporary (register)
629 
630  priv_.used += static_cast<QSCtr>(5); // 5 bytes about to be added
631  QS_INSERT_ESC_BYTE_(format) // insert the format byte
632 
633  for (std::uint_fast8_t i = 4U; i != 0U; --i) {
634  format = static_cast<std::uint8_t>(d);
635  QS_INSERT_ESC_BYTE_(format)
636  d >>= 8U;
637  }
638 
639  priv_.head = head_; // save the head
640  priv_.chksum = chksum_; // save the checksum
641 }
642 
643 //****************************************************************************
646 void QS::usr_dict_pre_(enum_t const rec,
647  char_t const * const name) noexcept
648 {
650  QS_CRIT_E_();
651  beginRec_(static_cast<std::uint_fast8_t>(QS_USR_DICT));
652  QS_U8_PRE_(rec);
653  QS_STR_PRE_(name);
654  endRec_();
655  QS_CRIT_X_();
656  onFlush();
657 }
658 
659 //****************************************************************************
663 void QS::mem_fmt_(std::uint8_t const *blk, std::uint8_t size) noexcept {
664  std::uint8_t b = static_cast<std::uint8_t>(MEM_T);
665  std::uint8_t chksum_ = priv_.chksum + b;
666  std::uint8_t * const buf_= priv_.buf; // put in a temporary (register)
667  QSCtr head_ = priv_.head; // put in a temporary (register)
668  QSCtr const end_= priv_.end; // put in a temporary (register)
669 
670  // size+2 bytes to be added
671  priv_.used += static_cast<std::uint8_t>(size + 2U);
672 
673  QS_INSERT_BYTE_(b)
674  QS_INSERT_ESC_BYTE_(size)
675 
676  // output the 'size' number of bytes
677  for (; size != 0U; --size) {
678  b = *blk;
680  ++blk;
681  }
682 
683  priv_.head = head_; // save the head
684  priv_.chksum = chksum_; // save the checksum
685 }
686 
687 //****************************************************************************
691 void QS::str_fmt_(char_t const *s) noexcept {
692  std::uint8_t b = static_cast<std::uint8_t>(*s);
693  std::uint8_t chksum_ = static_cast<std::uint8_t>(
694  priv_.chksum + static_cast<std::uint8_t>(STR_T));
695  std::uint8_t * const buf_= priv_.buf; // put in a temporary (register)
696  QSCtr head_ = priv_.head; // put in a temporary (register)
697  QSCtr const end_= priv_.end; // put in a temporary (register)
698  QSCtr used_ = priv_.used; // put in a temporary (register)
699 
700  used_ += 2U; // the format byte and the terminating-0
701 
702  QS_INSERT_BYTE_(static_cast<std::uint8_t>(STR_T))
703  while (b != 0U) {
704  // ASCII characters don't need escaping
705  chksum_ += b; // update checksum
706  QS_INSERT_BYTE_(b)
707  ++s;
708  b = static_cast<std::uint8_t>(*s);
709  ++used_;
710  }
711  QS_INSERT_BYTE_(0U) // zero-terminate the string
712 
713  priv_.head = head_; // save the head
714  priv_.chksum = chksum_; // save the checksum
715  priv_.used = used_; // save # of used buffer space
716 }
717 
718 //****************************************************************************
722 void QS::u8_raw_(std::uint8_t const d) noexcept {
723  std::uint8_t chksum_ = priv_.chksum; // put in a temporary (register)
724  std::uint8_t * const buf_ = priv_.buf; // put in a temporary (register)
725  QSCtr head_ = priv_.head; // put in a temporary (register)
726  QSCtr const end_= priv_.end; // put in a temporary (register)
727 
728  priv_.used += 1U; // 1 byte about to be added
730 
731  priv_.head = head_; // save the head
732  priv_.chksum = chksum_; // save the checksum
733 }
734 
735 //****************************************************************************
739 void QS::u8u8_raw_(std::uint8_t const d1, std::uint8_t const d2) noexcept {
740  std::uint8_t chksum_ = priv_.chksum; // put in a temporary (register)
741  std::uint8_t * const buf_ = priv_.buf; // put in a temporary (register)
742  QSCtr head_ = priv_.head; // put in a temporary (register)
743  QSCtr const end_= priv_.end; // put in a temporary (register)
744 
745  priv_.used += 2U; // 2 bytes about to be added
748 
749  priv_.head = head_; // save the head
750  priv_.chksum = chksum_; // save the checksum
751 }
752 
753 //****************************************************************************
757 void QS::u16_raw_(std::uint16_t d) noexcept {
758  std::uint8_t b = static_cast<std::uint8_t>(d);
759  std::uint8_t chksum_ = priv_.chksum; // put in a temporary (register)
760  std::uint8_t * const buf_ = priv_.buf; // put in a temporary (register)
761  QSCtr head_ = priv_.head; // put in a temporary (register)
762  QSCtr const end_= priv_.end; // put in a temporary (register)
763 
764  priv_.used += 2U; // 2 bytes about to be added
765 
767 
768  d >>= 8U;
769  b = static_cast<std::uint8_t>(d);
771 
772  priv_.head = head_; // save the head
773  priv_.chksum = chksum_; // save the checksum
774 }
775 
776 //****************************************************************************
780 void QS::u32_raw_(std::uint32_t d) noexcept {
781  std::uint8_t chksum_ = priv_.chksum; // put in a temporary (register)
782  std::uint8_t * const buf_ = priv_.buf; // put in a temporary (register)
783  QSCtr head_ = priv_.head; // put in a temporary (register)
784  QSCtr const end_= priv_.end; // put in a temporary (register)
785 
786  priv_.used += 4U; // 4 bytes about to be added
787  for (std::uint_fast8_t i = 4U; i != 0U; --i) {
788  std::uint8_t const b = static_cast<std::uint8_t>(d);
790  d >>= 8U;
791  }
792 
793  priv_.head = head_; // save the head
794  priv_.chksum = chksum_; // save the checksum
795 }
796 
797 //****************************************************************************
801 void QS::obj_raw_(void const * const obj) noexcept {
802 #if (QS_OBJ_PTR_SIZE == 1U)
803  u8_raw_(reinterpret_cast<std::uint8_t>(obj));
804 #elif (QS_OBJ_PTR_SIZE == 2U)
805  u16_raw_(reinterpret_cast<std::uint16_t>(obj));
806 #elif (QS_OBJ_PTR_SIZE == 4U)
807  u32_raw_(reinterpret_cast<std::uint32_t>(obj));
808 #elif (QS_OBJ_PTR_SIZE == 8U)
809  u64_raw_(reinterpret_cast<std::uint64_t>(obj));
810 #else
811  u32_raw_(reinterpret_cast<std::uint32_t>(obj));
812 #endif
813 }
814 
815 //****************************************************************************
819 void QS::str_raw_(char_t const *s) noexcept {
820  std::uint8_t b = static_cast<std::uint8_t>(*s);
821  std::uint8_t chksum_ = priv_.chksum; // put in a temporary (register)
822  std::uint8_t * const buf_ = priv_.buf; // put in a temporary (register)
823  QSCtr head_ = priv_.head; // put in a temporary (register)
824  QSCtr const end_= priv_.end; // put in a temporary (register)
825  QSCtr used_ = priv_.used; // put in a temporary (register)
826 
827  while (b != 0U) {
828  chksum_ += b; // update checksum
829  QS_INSERT_BYTE_(b) // ASCII characters don't need escaping
830  ++s;
831  b = static_cast<std::uint8_t>(*s);
832  ++used_;
833  }
834  QS_INSERT_BYTE_(0U) // zero-terminate the string
835  ++used_;
836 
837  priv_.head = head_; // save the head
838  priv_.chksum = chksum_; // save the checksum
839  priv_.used = used_; // save # of used buffer space
840 }
841 
842 //****************************************************************************
852 std::uint16_t QS::getByte(void) noexcept {
853  std::uint16_t ret;
854  if (priv_.used == 0U) {
855  ret = QS_EOD; // set End-Of-Data
856  }
857  else {
858  std::uint8_t * const buf_ = priv_.buf; //put in a temporary (register)
859  QSCtr tail_ = priv_.tail; // put in a temporary (register)
860 
861  // the byte to return
862  ret = static_cast<std::uint16_t>(buf_[tail_]);
863 
864  ++tail_; // advance the tail
865  if (tail_ == priv_.end) { // tail wrap around?
866  tail_ = 0U;
867  }
868  priv_.tail = tail_; // update the tail
869  --priv_.used; // one less byte used
870  }
871  return ret; // return the byte or EOD
872 }
873 
874 //****************************************************************************
897 std::uint8_t const *QS::getBlock(std::uint16_t * const pNbytes) noexcept {
898  QSCtr const used_ = priv_.used; // put in a temporary (register)
899  std::uint8_t *buf_;
900 
901  // any bytes used in the ring buffer?
902  if (used_ == 0U) {
903  *pNbytes = 0U; // no bytes available right now
904  buf_ = nullptr; // no bytes available right now
905  }
906  else {
907  QSCtr tail_ = priv_.tail; // put in a temporary (register)
908  QSCtr const end_ = priv_.end; // put in a temporary (register)
909  QSCtr n = static_cast<QSCtr>(end_ - tail_);
910  if (n > used_) {
911  n = used_;
912  }
913  if (n > static_cast<QSCtr>(*pNbytes)) {
914  n = static_cast<QSCtr>(*pNbytes);
915  }
916  *pNbytes = static_cast<std::uint16_t>(n); // n-bytes available
917  buf_ = priv_.buf;
918  buf_ = &buf_[tail_]; // the bytes are at the tail
919 
920  priv_.used -= n;
921  tail_ += n;
922  if (tail_ == end_) {
923  tail_ = 0U;
924  }
925  priv_.tail = tail_;
926  }
927  return buf_;
928 }
929 
930 //****************************************************************************
933 void QS::sig_dict_pre_(enum_t const sig, void const * const obj,
934  char_t const *name) noexcept
935 {
937 
938  if (*name == '&') {
939  ++name;
940  }
941  QS_CRIT_E_();
942  beginRec_(static_cast<std::uint_fast8_t>(QS_SIG_DICT));
943  QS_SIG_PRE_(sig);
944  QS_OBJ_PRE_(obj);
945  QS_STR_PRE_(name);
946  endRec_();
947  QS_CRIT_X_();
948  onFlush();
949 }
950 
951 //****************************************************************************
954 void QS::obj_dict_pre_(void const * const obj,
955  char_t const *name) noexcept
956 {
958 
959  if (*name == '&') {
960  ++name;
961  }
962  QS_CRIT_E_();
963  beginRec_(static_cast<std::uint_fast8_t>(QS_OBJ_DICT));
964  QS_OBJ_PRE_(obj);
965  QS_STR_PRE_(name);
966  endRec_();
967  QS_CRIT_X_();
968  onFlush();
969 }
970 
971 //****************************************************************************
974 void QS::fun_dict_pre_(void (* const fun)(void),
975  char_t const *name) noexcept
976 {
978 
979  if (*name == '&') {
980  ++name;
981  }
982  QS_CRIT_E_();
983  beginRec_(static_cast<std::uint_fast8_t>(QS_FUN_DICT));
984  QS_FUN_PRE_(fun);
985  QS_STR_PRE_(name);
986  endRec_();
987  QS_CRIT_X_();
988  onFlush();
989 }
990 
991 //****************************************************************************
994 void QS::assertion_pre_(char_t const * const module, int_t const loc,
995  std::uint32_t delay)
996 {
998  QS_TIME_PRE_();
999  QS_U16_PRE_(loc);
1000  QS_STR_PRE_((module != nullptr) ? module : "?");
1002  QP::QS::onFlush();
1003  for (std::uint32_t volatile ctr = delay; ctr > 0U; --ctr) {
1004  }
1006 }
1007 
1008 //............................................................................
1011  QS_TIME_PRE_();
1012  ++QS::priv_.critNest;
1015 }
1016 
1017 //............................................................................
1020  QS_TIME_PRE_();
1022  --QS::priv_.critNest;
1024 }
1025 
1026 //............................................................................
1028  std::uint8_t const prio)
1029 {
1031  QS_TIME_PRE_();
1032  QS_U8_PRE_(isrnest);
1033  QS_U8_PRE_(prio);
1035 }
1036 
1037 //............................................................................
1038 void QS::isr_exit_pre_(std::uint8_t const isrnest,
1039  std::uint8_t const prio)
1040 {
1042  QS_TIME_PRE_();
1043  QS_U8_PRE_(isrnest);
1044  QS_U8_PRE_(prio);
1046 }
1047 
1048 } // namespace QP
1049 
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
QS logging facilities.
Definition: qs.hpp:302
static void assertion_pre_(char_t const *const module, int_t const loc, std::uint32_t delay)
internal function to produce the assertion failure trace record
Definition: qs.cpp:994
static void usr_dict_pre_(enum_t const rec, char_t const *const name) noexcept
Output user dictionary record.
Definition: qs.cpp:646
static void crit_entry_pre_(void)
internal function to produce the critical section entry record
Definition: qs.cpp:1009
static std::uint16_t getByte(void) noexcept
Byte-oriented interface to the QS data buffer.
Definition: qs.cpp:852
static void onCleanup(void)
Callback to cleanup the QS facility.
static void crit_exit_pre_(void)
internal function to produce the critical section exit record
Definition: qs.cpp:1018
static void u16_raw_(std::uint16_t d) noexcept
Output std::uint16_t data element without format information.
Definition: qs.cpp:757
static void str_raw_(char_t const *s) noexcept
Output zero-terminated ASCII string element without format information.
Definition: qs.cpp:819
static QS priv_
Definition: qs.hpp:554
static std::uint8_t const * getBlock(std::uint16_t *const pNbytes) noexcept
Block-oriented interface to the QS data buffer.
Definition: qs.cpp:897
static void onFlush(void)
Callback to flush the QS trace data to the host.
static void u32_fmt_(std::uint8_t format, std::uint32_t d) noexcept
Output std::uint32_t data element with format information.
Definition: qs.cpp:624
static void isr_exit_pre_(std::uint8_t const isrnest, std::uint8_t const prio)
internal function to produce the ISR exit record
Definition: qs.cpp:1038
static void str_fmt_(char_t const *s) noexcept
Output zero-terminated ASCII string element with format information.
Definition: qs.cpp:691
static void glbFilter_(std::int_fast16_t const filter) noexcept
Set/clear the global Filter for a given QS record.
Definition: qs.cpp:121
static void beginRec_(std::uint_fast8_t const rec) noexcept
Mark the begin of a QS record rec.
Definition: qs.cpp:410
static void fun_dict_pre_(void(*const fun)(void), char_t const *name) noexcept
Output function dictionary record.
Definition: qs.cpp:974
static void sig_dict_pre_(enum_t const sig, void const *const obj, char_t const *name) noexcept
Output signal dictionary record.
Definition: qs.cpp:933
static void isr_entry_pre_(std::uint8_t const isrnest, std::uint8_t const prio)
internal function to produce the ISR entry record
Definition: qs.cpp:1027
static void u8_fmt_(std::uint8_t const format, std::uint8_t const d) noexcept
Output std::uint8_t data element with format information.
Definition: qs.cpp:579
static void obj_raw_(void const *const obj) noexcept
Output obj pointer data element without format information.
Definition: qs.cpp:801
static void endRec_(void) noexcept
Mark the end of a QS record rec.
Definition: qs.cpp:436
static void u8_raw_(std::uint8_t const d) noexcept
output std::uint8_t data element without format information
Definition: qs.cpp:722
static void locFilter_(std::int_fast16_t const filter) noexcept
Set/clear the local Filter for a given object-id.
Definition: qs.cpp:346
static void u8u8_raw_(std::uint8_t const d1, std::uint8_t const d2) noexcept
output two std::uint8_t data elements without format information
Definition: qs.cpp:739
static void u32_raw_(std::uint32_t d) noexcept
Output std::uint32_t data element without format information.
Definition: qs.cpp:780
static void obj_dict_pre_(void const *const obj, char_t const *name) noexcept
Output object dictionary record.
Definition: qs.cpp:954
static void mem_fmt_(std::uint8_t const *blk, std::uint8_t size) noexcept
Output memory block of up to 255-bytes with format information.
Definition: qs.cpp:663
static void u16_fmt_(std::uint8_t format, std::uint16_t d) noexcept
output std::uint16_t data element with format information
Definition: qs.cpp:599
std::uint_fast8_t critNest
critical section nesting level
Definition: qs.hpp:552
namespace associated with the QP/C++ framework
Definition: struct.dox:1
char const BUILD_DATE[12]
the calendar date of the last translation of the form: "Mmm dd yyyy"
Definition: qstamp.cpp:15
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
@ QS_ASSERT_FAIL
assertion failed in the code
Definition: qs.hpp:161
@ QS_FUN_DICT
function dictionary entry
Definition: qs.hpp:154
@ QS_QF_CRIT_ENTRY
critical section was entered
Definition: qs.hpp:119
@ QS_QF_CRIT_EXIT
critical section was exited
Definition: qs.hpp:120
@ QS_OBJ_DICT
object dictionary entry
Definition: qs.hpp:153
@ QS_TARGET_INFO
reports the Target information
Definition: qs.hpp:156
@ QS_QF_ISR_ENTRY
an ISR was entered
Definition: qs.hpp:121
@ QS_QF_ISR_EXIT
an ISR was exited
Definition: qs.hpp:122
@ QS_EMPTY
QS record for cleanly starting a session.
Definition: qs.hpp:64
@ QS_SIG_DICT
signal dictionary entry
Definition: qs.hpp:152
@ QS_USR_DICT
user QS record dictionary entry
Definition: qs.hpp:155
constexpr std::uint16_t QS_EOD
Constant representing End-Of-Data condition returned from the QP::QS::getByte() function.
Definition: qs.hpp:296
char const BUILD_TIME[9]
the time of the last translation of the form: "hh:mm:ss"
Definition: qstamp.cpp:18
constexpr std::uint8_t QS_ESC_XOR
Escape modifier of the QS output protocol.
Definition: qs_pkg.hpp:264
@ QS_EP_IDS
event-pool IDs
Definition: qs.hpp:238
@ QS_AO_IDS
AO IDs (priorities)
Definition: qs.hpp:237
@ QS_ALL_IDS
all QS IDs
Definition: qs.hpp:236
@ QS_AP_IDS
Application-specific IDs.
Definition: qs.hpp:240
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
@ QS_U2_RECORDS
User Group 110-114 records.
Definition: qs.hpp:211
@ QS_MP_RECORDS
Memory Pools QS records.
Definition: qs.hpp:205
@ QS_TE_RECORDS
Time Events QS records.
Definition: qs.hpp:206
@ QS_SM_RECORDS
State Machine QS records.
Definition: qs.hpp:202
@ QS_U0_RECORDS
User Group 100-104 records.
Definition: qs.hpp:209
@ QS_U3_RECORDS
User Group 115-119 records.
Definition: qs.hpp:212
@ QS_U4_RECORDS
User Group 120-124 records.
Definition: qs.hpp:213
@ QS_AO_RECORDS
Active Object QS records.
Definition: qs.hpp:203
@ QS_QF_RECORDS
QF QS records.
Definition: qs.hpp:207
@ QS_SC_RECORDS
Scheduler QS records.
Definition: qs.hpp:208
@ QS_U1_RECORDS
User Group 105-109 records.
Definition: qs.hpp:210
@ QS_EQ_RECORDS
Event Queues QS records.
Definition: qs.hpp:204
@ QS_ALL_RECORDS
all QS records
Definition: qs.hpp:201
@ QS_UA_RECORDS
All User records.
Definition: qs.hpp:214
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
char char_t
typedef for character strings.
Definition: qassert.h:77
#define Q_ASSERT_ID(id_, test_)
General purpose assertion with user-specified assertion-id.
Definition: qassert.h:155
int int_t
typedef for assertions-ids and line numbers in assertions.
Definition: qassert.h:86
#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 QP_VERSION
The current QP version as a decimal constant XXYZ, where XX is a 2-digit.
Definition: qep.hpp:46
#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
#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_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_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Definition: qs_dummy.hpp:98
#define QS_OBJ_PRE_(obj_)
Definition: qs_dummy.hpp:107
#define QS_FUN_PRE_(fun_)
Definition: qs_dummy.hpp:108
#define QS_END_NOCRIT_PRE_()
Definition: qs_dummy.hpp:99
#define QS_U16_PRE_(data_)
Definition: qs_dummy.hpp:102
#define QS_SIG_PRE_(sig_)
Definition: qs_dummy.hpp:105
Internal (package scope) QS/C++ interface.
#define QS_INSERT_ESC_BYTE_(b_)
Internal QS macro to insert an escaped byte into the QS buffer.
Definition: qs_pkg.hpp:51
#define QS_REC_NUM_(enum_)
Internal QS macro to cast enumerated QS record number to uint8_t.
Definition: qs_pkg.hpp:250
#define QS_INSERT_BYTE_(b_)
Internal QS macro to insert an un-escaped byte into the QS buffer.
Definition: qs_pkg.hpp:43
#define QS_STR_PRE_(msg_)
Internal QS macro to output a zero-terminated ASCII string data element.
Definition: qs_pkg.hpp:137
#define QS_TIME_SIZE
Definition: qs_port.h:44
#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.
Application build time-stamp interface.
#define QF_EVENT_SIZ_SIZE
The size (in bytes) of the event-size representation in the QF. Valid values: 1U, 2U,...
Definition: qxk/qf_port.hpp:93
#define QF_EQUEUE_CTR_SIZE
The size (in bytes) of the ring-buffer counters used in the native QF event queue implementation....
#define QF_MAX_ACTIVE
The maximum number of active objects in the application.
Definition: qxk/qf_port.hpp:57
#define QF_TIMEEVT_CTR_SIZE
The size (in bytes) of the time event -counter representation in the QP::QTimeEvt class....
#define QF_MPOOL_SIZ_SIZE
The size (in bytes) of the block-size representation in the native QF event pool. Valid values: 1U,...
#define QF_MPOOL_CTR_SIZE
The size (in bytes) of the block-counter representation in the native QF event pool....
#define QF_MAX_EPOOL
The maximum number of event pools in the application.
Definition: qxk/qf_port.hpp:74