QP/C  7.0.0
Real-Time Embedded Framework
qs.c
Go to the documentation of this file.
1/*============================================================================
2* QP/C Real-Time Embedded Framework (RTEF)
3* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
4*
5* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
6*
7* This software is dual-licensed under the terms of the open source GNU
8* General Public License version 3 (or any later version), or alternatively,
9* under the terms of one of the closed source Quantum Leaps commercial
10* licenses.
11*
12* The terms of the open source GNU General Public License version 3
13* can be found at: <www.gnu.org/licenses/gpl-3.0>
14*
15* The terms of the closed source Quantum Leaps commercial licenses
16* can be found at: <www.state-machine.com/licensing>
17*
18* Redistributions in source code must retain this top-level comment block.
19* Plagiarizing this software to sidestep the license obligations is illegal.
20*
21* Contact information:
22* <www.state-machine.com>
23* <info@state-machine.com>
24============================================================================*/
32#define QP_IMPL /* this is QP implementation */
33#include "qs_port.h" /* QS port */
34#include "qs_pkg.h" /* QS package-scope interface */
35#include "qstamp.h" /* QP time-stamp */
36#include "qassert.h" /* QP embedded systems-friendly assertions */
37
39
40/*==========================================================================*/
41QSPrivAttr QS_priv_; /* QS private attributes */
42
43/*==========================================================================*/
68void QS_initBuf(uint8_t sto[], uint_fast16_t stoSize) {
69 /* the provided buffer must be at least 8 bytes long */
70 Q_REQUIRE_ID(100, stoSize > 8U);
71
72 QS_priv_.buf = &sto[0];
73 QS_priv_.end = (QSCtr)stoSize;
74 QS_priv_.head = 0U;
75 QS_priv_.tail = 0U;
76 QS_priv_.used = 0U;
77 QS_priv_.seq = 0U;
78 QS_priv_.chksum = 0U;
79 QS_priv_.critNest = 0U;
80
81 QS_glbFilter_(-(int_fast16_t)QS_ALL_RECORDS); /* all global filters OFF */
82 QS_locFilter_((int_fast16_t)QS_ALL_IDS); /* all local filters ON */
83 QS_priv_.locFilter_AP = (void *)0; /* deprecated "AP-filter" */
84
85 /* produce an empty record to "flush" the QS trace buffer */
86 QS_beginRec_((uint_fast8_t)QS_EMPTY);
87 QS_endRec_();
88
89 /* produce the reset record to inform QSPY of a new session */
90 QS_target_info_pre_(0xFFU); /* send Reset and Target info */
91
92 /* hold off flushing after successfull initialization (see QS_INIT()) */
93}
94
95/*==========================================================================*/
112void QS_glbFilter_(int_fast16_t const filter) {
113 bool const isRemove = (filter < 0);
114 uint8_t const rec = isRemove ? (uint8_t)(-filter) : (uint8_t)filter;
115 switch (rec) {
116 case QS_ALL_RECORDS: {
117 uint8_t const tmp = (isRemove ? 0x00U : 0xFFU);
118 uint_fast8_t i;
119 /* set all global filters (partially unrolled loop) */
120 for (i = 0U; i < Q_DIM(QS_priv_.glbFilter); i += 4U) {
121 QS_priv_.glbFilter[i ] = tmp;
122 QS_priv_.glbFilter[i + 1U] = tmp;
123 QS_priv_.glbFilter[i + 2U] = tmp;
124 QS_priv_.glbFilter[i + 3U] = tmp;
125 }
126 if (isRemove) {
127 /* leave the "not maskable" filters enabled,
128 * see qs.h, Miscellaneous QS records (not maskable)
129 */
130 QS_priv_.glbFilter[0] = 0x01U;
131 QS_priv_.glbFilter[7] = 0xFCU;
132 QS_priv_.glbFilter[8] = 0x7FU;
133 }
134 else {
135 /* never turn the last 3 records on (0x7D, 0x7E, 0x7F) */
136 QS_priv_.glbFilter[15] = 0x1FU;
137 }
138 break;
139 }
140 case QS_SM_RECORDS:
141 if (isRemove) {
142 QS_priv_.glbFilter[0] &= (uint8_t)(~0xFEU & 0xFFU);
143 QS_priv_.glbFilter[1] &= (uint8_t)(~0x03U & 0xFFU);
144 QS_priv_.glbFilter[6] &= (uint8_t)(~0x80U & 0xFFU);
145 QS_priv_.glbFilter[7] &= (uint8_t)(~0x03U & 0xFFU);
146 }
147 else {
148 QS_priv_.glbFilter[0] |= 0xFEU;
149 QS_priv_.glbFilter[1] |= 0x03U;
150 QS_priv_.glbFilter[6] |= 0x80U;
151 QS_priv_.glbFilter[7] |= 0x03U;
152 }
153 break;
154 case QS_AO_RECORDS:
155 if (isRemove) {
156 QS_priv_.glbFilter[1] &= (uint8_t)(~0xFCU & 0xFFU);
157 QS_priv_.glbFilter[2] &= (uint8_t)(~0x07U & 0xFFU);
158 QS_priv_.glbFilter[5] &= (uint8_t)(~0x20U & 0xFFU);
159 }
160 else {
161 QS_priv_.glbFilter[1] |= 0xFCU;
162 QS_priv_.glbFilter[2] |= 0x07U;
163 QS_priv_.glbFilter[5] |= 0x20U;
164 }
165 break;
166 case QS_EQ_RECORDS:
167 if (isRemove) {
168 QS_priv_.glbFilter[2] &= (uint8_t)(~0x78U & 0xFFU);
169 QS_priv_.glbFilter[5] &= (uint8_t)(~0x40U & 0xFFU);
170 }
171 else {
172 QS_priv_.glbFilter[2] |= 0x78U;
173 QS_priv_.glbFilter[5] |= 0x40U;
174 }
175 break;
176 case QS_MP_RECORDS:
177 if (isRemove) {
178 QS_priv_.glbFilter[3] &= (uint8_t)(~0x03U & 0xFFU);
179 QS_priv_.glbFilter[5] &= (uint8_t)(~0x80U & 0xFFU);
180 }
181 else {
182 QS_priv_.glbFilter[3] |= 0x03U;
183 QS_priv_.glbFilter[5] |= 0x80U;
184 }
185 break;
186 case QS_QF_RECORDS:
187 if (isRemove) {
188 QS_priv_.glbFilter[2] &= (uint8_t)(~0x80U & 0xFFU);
189 QS_priv_.glbFilter[3] &= (uint8_t)(~0xFCU & 0xFFU);
190 QS_priv_.glbFilter[4] &= (uint8_t)(~0xC0U & 0xFFU);
191 QS_priv_.glbFilter[5] &= (uint8_t)(~0x1FU & 0xFFU);
192 }
193 else {
194 QS_priv_.glbFilter[2] |= 0x80U;
195 QS_priv_.glbFilter[3] |= 0xFCU;
196 QS_priv_.glbFilter[4] |= 0xC0U;
197 QS_priv_.glbFilter[5] |= 0x1FU;
198 }
199 break;
200 case QS_TE_RECORDS:
201 if (isRemove) {
202 QS_priv_.glbFilter[4] &= (uint8_t)(~0x3FU & 0xFFU);
203 }
204 else {
205 QS_priv_.glbFilter[4] |= 0x3FU;
206 }
207 break;
208 case QS_SC_RECORDS:
209 if (isRemove) {
210 QS_priv_.glbFilter[6] &= (uint8_t)(~0x7FU & 0xFFU);
211 }
212 else {
213 QS_priv_.glbFilter[6] |= 0x7FU;
214 }
215 break;
216 case QS_U0_RECORDS:
217 if (isRemove) {
218 QS_priv_.glbFilter[12] &= (uint8_t)(~0xF0U & 0xFFU);
219 QS_priv_.glbFilter[13] &= (uint8_t)(~0x01U & 0xFFU);
220 }
221 else {
222 QS_priv_.glbFilter[12] |= 0xF0U;
223 QS_priv_.glbFilter[13] |= 0x01U;
224 }
225 break;
226 case QS_U1_RECORDS:
227 if (isRemove) {
228 QS_priv_.glbFilter[13] &= (uint8_t)(~0x3EU & 0xFFU);
229 }
230 else {
231 QS_priv_.glbFilter[13] |= 0x3EU;
232 }
233 break;
234 case QS_U2_RECORDS:
235 if (isRemove) {
236 QS_priv_.glbFilter[13] &= (uint8_t)(~0xC0U & 0xFFU);
237 QS_priv_.glbFilter[14] &= (uint8_t)(~0x07U & 0xFFU);
238 }
239 else {
240 QS_priv_.glbFilter[13] |= 0xC0U;
241 QS_priv_.glbFilter[14] |= 0x07U;
242 }
243 break;
244 case QS_U3_RECORDS:
245 if (isRemove) {
246 QS_priv_.glbFilter[14] &= (uint8_t)(~0xF8U & 0xFFU);
247 }
248 else {
249 QS_priv_.glbFilter[14] |= 0xF8U;
250 }
251 break;
252 case QS_U4_RECORDS:
253 if (isRemove) {
254 QS_priv_.glbFilter[15] &= 0x1FU;
255 }
256 else {
257 QS_priv_.glbFilter[15] |= 0x1FU;
258 }
259 break;
260 case QS_UA_RECORDS:
261 if (isRemove) {
262 QS_priv_.glbFilter[12] &= (uint8_t)(~0xF0U & 0xFFU);
263 QS_priv_.glbFilter[13] = 0U;
264 QS_priv_.glbFilter[14] = 0U;
265 QS_priv_.glbFilter[15] &= (uint8_t)(~0x1FU & 0xFFU);
266 }
267 else {
268 QS_priv_.glbFilter[12] |= 0xF0U;
269 QS_priv_.glbFilter[13] |= 0xFFU;
270 QS_priv_.glbFilter[14] |= 0xFFU;
271 QS_priv_.glbFilter[15] |= 0x1FU;
272 }
273 break;
274 default:
275 /* QS rec number can't exceed 0x7D, so no need for escaping */
276 Q_ASSERT_ID(210, rec < 0x7DU);
277
278 if (isRemove) {
279 QS_priv_.glbFilter[rec >> 3U]
280 &= (uint8_t)(~(1U << (rec & 7U)) & 0xFFU);
281 }
282 else {
283 QS_priv_.glbFilter[rec >> 3U]
284 |= (1U << (rec & 7U));
285 /* never turn the last 3 records on (0x7D, 0x7E, 0x7F) */
286 QS_priv_.glbFilter[15] &= 0x1FU;
287 }
288 break;
289 }
290}
291
292/*==========================================================================*/
308void QS_locFilter_(int_fast16_t const filter) {
309 bool const isRemove = (filter < 0);
310 uint8_t const qs_id = isRemove ? (uint8_t)(-filter) : (uint8_t)filter;
311 uint8_t const tmp = (isRemove ? 0x00U : 0xFFU);
312 uint_fast8_t i;
313 switch (qs_id) {
314 case QS_ALL_IDS:
315 /* set all local filters (partially unrolled loop) */
316 for (i = 0U; i < Q_DIM(QS_priv_.locFilter); i += 4U) {
317 QS_priv_.locFilter[i ] = tmp;
318 QS_priv_.locFilter[i + 1U] = tmp;
319 QS_priv_.locFilter[i + 2U] = tmp;
320 QS_priv_.locFilter[i + 3U] = tmp;
321 }
322 break;
323 case QS_AO_IDS:
324 for (i = 0U; i < 8U; i += 4U) {
325 QS_priv_.locFilter[i ] = tmp;
326 QS_priv_.locFilter[i + 1U] = tmp;
327 QS_priv_.locFilter[i + 2U] = tmp;
328 QS_priv_.locFilter[i + 3U] = tmp;
329 }
330 break;
331 case QS_EP_IDS:
332 i = 8U;
333 QS_priv_.locFilter[i ] = tmp;
334 QS_priv_.locFilter[i + 1U] = tmp;
335 break;
336 case QS_AP_IDS:
337 i = 12U;
338 QS_priv_.locFilter[i ] = tmp;
339 QS_priv_.locFilter[i + 1U] = tmp;
340 QS_priv_.locFilter[i + 2U] = tmp;
341 QS_priv_.locFilter[i + 3U] = tmp;
342 break;
343 default:
344 if (qs_id < 0x7FU) {
345 if (isRemove) {
346 QS_priv_.locFilter[qs_id >> 3U]
347 &= (uint8_t)(~(1U << (qs_id & 7U)) & 0xFFU);
348 }
349 else {
350 QS_priv_.locFilter[qs_id >> 3U]
351 |= (1U << (qs_id & 7U));
352 }
353 }
354 else {
355 Q_ERROR_ID(310); /* incorrect qs_id */
356 }
357 break;
358 }
359 QS_priv_.locFilter[0] |= 0x01U; /* leave QS_ID == 0 always on */
360}
361
362/*==========================================================================*/
371void QS_beginRec_(uint_fast8_t rec) {
372 uint8_t const b = (uint8_t)(QS_priv_.seq + 1U);
373 uint8_t chksum = 0U; /* reset the checksum */
374 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
375 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
376 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
377
378 QS_priv_.seq = b; /* store the incremented sequence num */
379 QS_priv_.used += 2U; /* 2 bytes about to be added */
380
382
383 chksum = (uint8_t)(chksum + rec); /* update checksum */
384 QS_INSERT_BYTE_((uint8_t)rec) /* rec byte does not need escaping */
385
386 QS_priv_.head = head; /* save the head */
387 QS_priv_.chksum = chksum; /* save the checksum */
388}
389
390/*==========================================================================*/
399void QS_endRec_(void) {
400 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
401 QSCtr head = QS_priv_.head;
402 QSCtr const end = QS_priv_.end;
403 uint8_t b = QS_priv_.chksum;
404 b ^= 0xFFU; /* invert the bits in the checksum */
405
406 QS_priv_.used += 2U; /* 2 bytes about to be added */
407
408 if ((b != QS_FRAME) && (b != QS_ESC)) {
410 }
411 else {
414 ++QS_priv_.used; /* account for the ESC byte */
415 }
416
417 QS_INSERT_BYTE_(QS_FRAME) /* do not escape this QS_FRAME */
418
419 QS_priv_.head = head; /* save the head */
420
421 /* overrun over the old data? */
422 if (QS_priv_.used > end) {
423 QS_priv_.used = end; /* the whole buffer is used */
424 QS_priv_.tail = head; /* shift the tail to the old data */
425 }
426}
427
428/*==========================================================================*/
430void QS_target_info_pre_(uint8_t isReset) {
431 static uint8_t const ZERO = (uint8_t)'0';
432 static uint8_t const * const TIME = (uint8_t const *)&Q_BUILD_TIME[0];
433 static uint8_t const * const DATE = (uint8_t const *)&Q_BUILD_DATE[0];
434 static union {
435 uint16_t u16;
436 uint8_t u8[2];
437 } endian_test;
438
439 endian_test.u16 = 0x0102U;
440 QS_beginRec_((uint_fast8_t)QS_TARGET_INFO);
441 QS_U8_PRE_(isReset);
442 QS_U16_PRE_(((endian_test.u8[0] == 0x01U) /* big endian? */
443 ? (0x8000U | QP_VERSION)
444 : QP_VERSION)); /* target endianness + version number */
445
446 /* send the object sizes... */
447 QS_U8_PRE_(Q_SIGNAL_SIZE | (QF_EVENT_SIZ_SIZE << 4U));
448
449#ifdef QF_EQUEUE_CTR_SIZE
450 QS_U8_PRE_(QF_EQUEUE_CTR_SIZE | (QF_TIMEEVT_CTR_SIZE << 4U));
451#else
452 QS_U8_PRE_(QF_TIMEEVT_CTR_SIZE << 4U);
453#endif /* QF_EQUEUE_CTR_SIZE */
454
455#ifdef QF_MPOOL_CTR_SIZE
456 QS_U8_PRE_(QF_MPOOL_SIZ_SIZE | (QF_MPOOL_CTR_SIZE << 4U));
457#else
458 QS_U8_PRE_(0U);
459#endif /* QF_MPOOL_CTR_SIZE */
460
463
464 /* send the limits... */
466 QS_U8_PRE_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE << 4U));
467
468 /* send the build time in three bytes (sec, min, hour)... */
469 QS_U8_PRE_((10U * (uint8_t)(TIME[6] - ZERO))
470 + (uint8_t)(TIME[7] - ZERO));
471 QS_U8_PRE_((10U * (uint8_t)(TIME[3] - ZERO))
472 + (uint8_t)(TIME[4] - ZERO));
473 if (Q_BUILD_TIME[0] == ' ') {
474 QS_U8_PRE_(TIME[1] - ZERO);
475 }
476 else {
477 QS_U8_PRE_((10U * (uint8_t)(TIME[0] - ZERO))
478 + (uint8_t)(TIME[1] - ZERO));
479 }
480
481 /* send the build date in three bytes (day, month, year) ... */
482 if (Q_BUILD_DATE[4] == ' ') {
483 QS_U8_PRE_(DATE[5] - ZERO);
484 }
485 else {
486 QS_U8_PRE_((10U * (uint8_t)(DATE[4] - ZERO))
487 + (uint8_t)(DATE[5] - ZERO));
488 }
489 /* convert the 3-letter month to a number 1-12 ... */
490 uint8_t b;
491 switch ((int_t)DATE[0] + (int_t)DATE[1] + (int_t)DATE[2]) {
492 case (int_t)'J' + (int_t)'a' + (int_t)'n':
493 b = 1U;
494 break;
495 case (int_t)'F' + (int_t)'e' + (int_t)'b':
496 b = 2U;
497 break;
498 case (int_t)'M' + (int_t)'a' + (int_t)'r':
499 b = 3U;
500 break;
501 case (int_t)'A' + (int_t)'p' + (int_t)'r':
502 b = 4U;
503 break;
504 case (int_t)'M' + (int_t)'a' + (int_t)'y':
505 b = 5U;
506 break;
507 case (int_t)'J' + (int_t)'u' + (int_t)'n':
508 b = 6U;
509 break;
510 case (int_t)'J' + (int_t)'u' + (int_t)'l':
511 b = 7U;
512 break;
513 case (int_t)'A' + (int_t)'u' + (int_t)'g':
514 b = 8U;
515 break;
516 case (int_t)'S' + (int_t)'e' + (int_t)'p':
517 b = 9U;
518 break;
519 case (int_t)'O' + (int_t)'c' + (int_t)'t':
520 b = 10U;
521 break;
522 case (int_t)'N' + (int_t)'o' + (int_t)'v':
523 b = 11U;
524 break;
525 case (int_t)'D' + (int_t)'e' + (int_t)'c':
526 b = 12U;
527 break;
528 default:
529 b = 0U;
530 break;
531 }
532 QS_U8_PRE_(b); /* store the month */
533 QS_U8_PRE_((10U * (uint8_t)(DATE[9] - ZERO))
534 + (uint8_t)(DATE[10] - ZERO));
535 QS_endRec_();
536}
537
538/*==========================================================================*/
545void QS_u8_fmt_(uint8_t format, uint8_t d) {
546 uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
547 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
548 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
549 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
550
551 QS_priv_.used += 2U; /* 2 bytes about to be added */
552
553 QS_INSERT_ESC_BYTE_(format)
555
556 QS_priv_.head = head; /* save the head */
557 QS_priv_.chksum = chksum; /* save the checksum */
558}
559
560/*==========================================================================*/
567void QS_u16_fmt_(uint8_t format, uint16_t d) {
568 uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
569 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
570 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
571 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
572 uint8_t b = (uint8_t)d;
573
574 QS_priv_.used += 3U; /* 3 bytes about to be added */
575
576 QS_INSERT_ESC_BYTE_(format)
578 b = (uint8_t)(d >> 8U);
580
581 QS_priv_.head = head; /* save the head */
582 QS_priv_.chksum = chksum; /* save the checksum */
583}
584
585/*==========================================================================*/
591void QS_u32_fmt_(uint8_t format, uint32_t d) {
592 uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
593 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
594 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
595 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
596 uint32_t x = d;
597
598 QS_priv_.used += 5U; /* 5 bytes about to be added */
599 QS_INSERT_ESC_BYTE_(format) /* insert the format byte */
600
601 /* insert 4 bytes... */
602 for (uint_fast8_t i = 4U; i != 0U; --i) {
603 QS_INSERT_ESC_BYTE_((uint8_t)x)
604 x >>= 8U;
605 }
606
607 QS_priv_.head = head; /* save the head */
608 QS_priv_.chksum = chksum; /* save the checksum */
609}
610
611/*==========================================================================*/
618void QS_u8_raw_(uint8_t d) {
619 uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
620 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
621 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
622 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
623
624 QS_priv_.used += 1U; /* 1 byte about to be added */
626
627 QS_priv_.head = head; /* save the head */
628 QS_priv_.chksum = chksum; /* save the checksum */
629}
630
631/*==========================================================================*/
637void QS_2u8_raw_(uint8_t d1, uint8_t d2) {
638 uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
639 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
640 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
641 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
642
643 QS_priv_.used += 2U; /* 2 bytes are about to be added */
646
647 QS_priv_.head = head; /* save the head */
648 QS_priv_.chksum = chksum; /* save the checksum */
649}
650
651/*==========================================================================*/
657void QS_u16_raw_(uint16_t d) {
658 uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
659 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
660 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
661 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
662 uint16_t x = d;
663
664 QS_priv_.used += 2U; /* 2 bytes are about to be added */
665
666 QS_INSERT_ESC_BYTE_((uint8_t)x)
667 x >>= 8U;
668 QS_INSERT_ESC_BYTE_((uint8_t)x)
669
670 QS_priv_.head = head; /* save the head */
671 QS_priv_.chksum = chksum; /* save the checksum */
672}
673
674/*==========================================================================*/
680void QS_u32_raw_(uint32_t d) {
681 uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
682 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
683 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
684 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
685 uint32_t x = d;
686
687 QS_priv_.used += 4U; /* 4 bytes are about to be added */
688 for (uint_fast8_t i = 4U; i != 0U; --i) {
689 QS_INSERT_ESC_BYTE_((uint8_t)x)
690 x >>= 8U;
691 }
692
693 QS_priv_.head = head; /* save the head */
694 QS_priv_.chksum = chksum; /* save the checksum */
695}
696
697/*==========================================================================*/
703void QS_obj_raw_(void const * const obj) {
704#if (QS_OBJ_PTR_SIZE == 1U)
705 QS_u8_raw_((uint8_t)obj);
706#elif (QS_OBJ_PTR_SIZE == 2U)
707 QS_u16_raw_((uint16_t)obj);
708#elif (QS_OBJ_PTR_SIZE == 4U)
709 QS_u32_raw_((uint32_t)obj);
710#elif (QS_OBJ_PTR_SIZE == 8U)
711 QS_u64_raw_((uint64_t)obj);
712#else
713 QS_u32_raw_((uint32_t)obj);
714#endif
715}
716
717/*==========================================================================*/
723void QS_str_raw_(char const *str) {
724 uint8_t chksum = QS_priv_.chksum; /* put in a temporary (register) */
725 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
726 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
727 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
728 QSCtr used = QS_priv_.used; /* put in a temporary (register) */
729
730 for (char const *s = str; *s != '\0'; ++s) {
731 chksum += (uint8_t)*s; /* update checksum */
732 QS_INSERT_BYTE_((uint8_t)*s) /* ASCII char doesn't need escaping */
733 ++used;
734 }
735 QS_INSERT_BYTE_((uint8_t)'\0') /* zero-terminate the string */
736 ++used;
737
738 QS_priv_.head = head; /* save the head */
739 QS_priv_.chksum = chksum; /* save the checksum */
740 QS_priv_.used = used; /* save # of used buffer space */
741}
742
743/*==========================================================================*/
755uint16_t QS_getByte(void) {
756 uint16_t ret;
757 if (QS_priv_.used == 0U) {
758 ret = QS_EOD; /* set End-Of-Data */
759 }
760 else {
761 uint8_t const * const buf = QS_priv_.buf; /* put in a temporary */
762 QSCtr tail = QS_priv_.tail; /* put in a temporary (register) */
763 ret = (uint16_t)buf[tail]; /* set the byte to return */
764 ++tail; /* advance the tail */
765 if (tail == QS_priv_.end) { /* tail wrap around? */
766 tail = 0U;
767 }
768 QS_priv_.tail = tail; /* update the tail */
769 --QS_priv_.used; /* one less byte used */
770 }
771 return ret; /* return the byte or EOD */
772}
773
774/*==========================================================================*/
798uint8_t const *QS_getBlock(uint16_t *pNbytes) {
799 QSCtr const used = QS_priv_.used; /* put in a temporary (register) */
800 uint8_t const *buf;
801
802 /* any bytes used in the ring buffer? */
803 if (used != 0U) {
804 QSCtr tail = QS_priv_.tail; /* put in a temporary (register) */
805 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
806 QSCtr n = (QSCtr)(end - tail);
807 if (n > used) {
808 n = used;
809 }
810 if (n > (QSCtr)(*pNbytes)) {
811 n = (QSCtr)(*pNbytes);
812 }
813 *pNbytes = (uint16_t)n; /* n-bytes available */
814 buf = &QS_priv_.buf[tail]; /* the bytes are at the tail */
815
816 QS_priv_.used = (QSCtr)(used - n);
817 tail += n;
818 if (tail == end) {
819 tail = 0U;
820 }
821 QS_priv_.tail = tail;
822 }
823
824 else { /* no bytes available */
825 *pNbytes = 0U; /* no bytes available right now */
826 buf = (uint8_t *)0; /* no bytes available right now */
827 }
828 return buf;
829}
830
831/*==========================================================================*/
836void QS_sig_dict_pre_(enum_t const sig, void const * const obj,
837 char const *name)
838{
840
841 QS_CRIT_E_();
842 QS_beginRec_((uint_fast8_t)QS_SIG_DICT);
843 QS_SIG_PRE_(sig);
844 QS_OBJ_PRE_(obj);
845 QS_str_raw_((*name == '&') ? &name[1] : name);
846 QS_endRec_();
847 QS_CRIT_X_();
848 QS_onFlush();
849}
850
851/*==========================================================================*/
856void QS_obj_dict_pre_(void const * const obj,
857 char const *name)
858{
860
861 QS_CRIT_E_();
862 QS_beginRec_((uint_fast8_t)QS_OBJ_DICT);
863 QS_OBJ_PRE_(obj);
864 QS_str_raw_((*name == '&') ? &name[1] : name);
865 QS_endRec_();
866 QS_CRIT_X_();
867 QS_onFlush();
868}
869
870/*==========================================================================*/
875void QS_obj_arr_dict_pre_(void const * const obj,
876 uint_fast16_t idx,
877 char const *name)
878{
879 Q_REQUIRE_ID(400, idx < 1000U);
880
881 /* format idx into a char buffer as "xxx\0" */
882 uint8_t idx_str[4];
883 uint_fast16_t tmp = idx;
884 uint8_t i;
885 idx_str[3] = 0U; /* zero-terminate */
886 idx_str[2] = (uint8_t)((uint8_t)'0' + (tmp % 10U));
887 tmp /= 10U;
888 idx_str[1] = (uint8_t)((uint8_t)'0' + (tmp % 10U));
889 if (idx_str[1] == (uint8_t)'0') {
890 i = 2U;
891 }
892 else {
893 tmp /= 10U;
894 idx_str[0] = (uint8_t)((uint8_t)'0' + (tmp % 10U));
895 if (idx_str[0] == (uint8_t)'0') {
896 i = 1U;
897 }
898 else {
899 i = 0U;
900 }
901 }
902
904 uint8_t j = ((*name == '&') ? 1U : 0U);
905
906 QS_CRIT_E_();
907 QS_beginRec_((uint_fast8_t)QS_OBJ_DICT);
908 QS_OBJ_PRE_(obj);
909 for (; name[j] != '\0'; ++j) {
910 QS_U8_PRE_(name[j]);
911 if (name[j] == '[') {
912 ++j;
913 break;
914 }
915 }
916 for (; idx_str[i] != 0U; ++i) {
917 QS_U8_PRE_(idx_str[i]);
918 }
919 /* skip chars until ']' */
920 for (; name[j] != '\0'; ++j) {
921 if (name[j] == ']') {
922 break;
923 }
924 }
925 for (; name[j] != '\0'; ++j) {
926 QS_U8_PRE_(name[j]);
927 }
928 QS_U8_PRE_(0U); /* zero-terminate */
929 QS_endRec_();
930 QS_CRIT_X_();
931 QS_onFlush();
932}
933
934/*==========================================================================*/
939void QS_fun_dict_pre_(void (* const fun)(void), char const *name) {
941
942 QS_CRIT_E_();
943 QS_beginRec_((uint_fast8_t)QS_FUN_DICT);
944 QS_FUN_PRE_(fun);
945 QS_str_raw_((*name == '&') ? &name[1] : name);
946 QS_endRec_();
947 QS_CRIT_X_();
948 QS_onFlush();
949}
950
951/*==========================================================================*/
957 char const * const name)
958{
960
961 QS_CRIT_E_();
962 QS_beginRec_((uint_fast8_t)QS_USR_DICT);
963 QS_u8_raw_((uint8_t)rec);
964 QS_str_raw_(name);
965 QS_endRec_();
966 QS_CRIT_X_();
967 QS_onFlush();
968}
969
970/*==========================================================================*/
976void QS_mem_fmt_(uint8_t const *blk, uint8_t size) {
977 uint8_t chksum = QS_priv_.chksum;
978 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
979 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
980 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
981 uint8_t const *pb = blk;
982
983 QS_priv_.used += ((QSCtr)size + 2U); /* size+2 bytes to be added */
984
985 QS_INSERT_BYTE_((uint8_t)QS_MEM_T)
986 chksum += (uint8_t)QS_MEM_T;
987
989 /* output the 'size' number of bytes */
990 for (uint8_t len = size; len > 0U; --len) {
992 ++pb;
993 }
994
995 QS_priv_.head = head; /* save the head */
996 QS_priv_.chksum = chksum; /* save the checksum */
997}
998
999/*==========================================================================*/
1005void QS_str_fmt_(char const *str) {
1006 uint8_t chksum = QS_priv_.chksum;
1007 uint8_t * const buf = QS_priv_.buf; /* put in a temporary (register) */
1008 QSCtr head = QS_priv_.head; /* put in a temporary (register) */
1009 QSCtr const end = QS_priv_.end; /* put in a temporary (register) */
1010 QSCtr used = QS_priv_.used; /* put in a temporary (register) */
1011
1012 used += 2U; /* account for the format byte and the terminating-0 */
1013 QS_INSERT_BYTE_((uint8_t)QS_STR_T)
1014 chksum += (uint8_t)QS_STR_T;
1015
1016 for (char const *s = str; *s != '\0'; ++s) {
1017 QS_INSERT_BYTE_((uint8_t)*s) /* ASCII char doesn't need escaping */
1018 chksum += (uint8_t)*s; /* update checksum */
1019 ++used;
1020 }
1021 QS_INSERT_BYTE_(0U) /* zero-terminate the string */
1022
1023 QS_priv_.head = head; /* save the head */
1024 QS_priv_.chksum = chksum; /* save the checksum */
1025 QS_priv_.used = used; /* save # of used buffer space */
1026}
1027
1028/*==========================================================================*/
1032void QS_ASSERTION(char const * const module,
1033 int_t const loc,
1034 uint32_t delay)
1035{
1037 QS_TIME_PRE_();
1038 QS_U16_PRE_(loc);
1039 QS_STR_PRE_((module != (char *)0) ? module : "?");
1041 QS_onFlush();
1042
1043 for (uint32_t volatile delay_ctr = delay; delay_ctr > 0U; --delay_ctr) {
1044 }
1045 QS_onCleanup();
1046}
1047
1048/*==========================================================================*/
1054 QS_TIME_PRE_();
1058}
1059
1062 QS_TIME_PRE_();
1066}
1067
1068/*==========================================================================*/
1072void QF_QS_ISR_ENTRY(uint8_t const isrnest, uint8_t const prio) {
1074 QS_TIME_PRE_();
1075 QS_2u8_raw_(isrnest, prio);
1077}
1078
1082void QF_QS_ISR_EXIT(uint8_t const isrnest, uint8_t const prio) {
1084 QS_TIME_PRE_();
1085 QS_2u8_raw_(isrnest, prio);
1087}
Customizable and memory-efficient assertions for embedded systems.
#define Q_DEFINE_THIS_MODULE(name_)
Definition: qassert.h:102
#define Q_ASSERT_ID(id_, test_)
Definition: qassert.h:135
#define Q_REQUIRE_ID(id_, test_)
Definition: qassert.h:252
#define Q_DIM(array_)
Definition: qassert.h:307
#define Q_ERROR_ID(id_)
Definition: qassert.h:187
signed int int_t
Definition: qep.h:57
#define QP_VERSION
Definition: qep.h:42
signed int enum_t
Definition: qep.h:60
#define Q_SIGNAL_SIZE
Definition: qep.h:83
QSPrivAttr QS_priv_
Definition: qs.c:41
uint8_t volatile chksum
Definition: qs.h:920
#define QS_CRIT_STAT_
Definition: qs.h:509
#define QS_TIME_PRE_()
Definition: qs.h:220
void const * locFilter_AP
Definition: qs.h:913
uint8_t * buf
Definition: qs.h:914
#define QS_CRIT_X_()
Definition: qs.h:531
@ QS_U2_RECORDS
Definition: qs.h:180
@ QS_MP_RECORDS
Definition: qs.h:174
@ QS_TE_RECORDS
Definition: qs.h:175
@ QS_SM_RECORDS
Definition: qs.h:171
@ QS_U0_RECORDS
Definition: qs.h:178
@ QS_U3_RECORDS
Definition: qs.h:181
@ QS_U4_RECORDS
Definition: qs.h:182
@ QS_AO_RECORDS
Definition: qs.h:172
@ QS_QF_RECORDS
Definition: qs.h:176
@ QS_SC_RECORDS
Definition: qs.h:177
@ QS_U1_RECORDS
Definition: qs.h:179
@ QS_EQ_RECORDS
Definition: qs.h:173
@ QS_ALL_RECORDS
Definition: qs.h:170
@ QS_UA_RECORDS
Definition: qs.h:183
#define QS_CRIT_E_()
Definition: qs.h:520
QSCtr volatile tail
Definition: qs.h:917
uint8_t glbFilter[16]
Definition: qs.h:911
QSCtr volatile used
Definition: qs.h:918
@ QS_STR_T
Definition: qs.h:611
@ QS_MEM_T
Definition: qs.h:612
uint_fast16_t QSCtr
Definition: qs.h:892
QSCtr end
Definition: qs.h:915
uint8_t locFilter[16]
Definition: qs.h:912
uint8_t volatile seq
Definition: qs.h:919
@ QS_ASSERT_FAIL
Definition: qs.h:152
@ QS_FUN_DICT
Definition: qs.h:145
@ QS_QF_CRIT_ENTRY
Definition: qs.h:110
@ QS_QF_CRIT_EXIT
Definition: qs.h:111
@ QS_OBJ_DICT
Definition: qs.h:144
@ QS_TARGET_INFO
Definition: qs.h:147
@ QS_QF_ISR_ENTRY
Definition: qs.h:112
@ QS_QF_ISR_EXIT
Definition: qs.h:113
@ QS_EMPTY
Definition: qs.h:55
@ QS_SIG_DICT
Definition: qs.h:143
@ QS_USR_DICT
Definition: qs.h:146
QSCtr volatile head
Definition: qs.h:916
uint8_t volatile critNest
Definition: qs.h:922
#define QS_EOD
Definition: qs.h:355
@ QS_EP_IDS
Definition: qs.h:198
@ QS_AO_IDS
Definition: qs.h:197
@ QS_ALL_IDS
Definition: qs.h:196
@ QS_AP_IDS
Definition: qs.h:200
Definition: qs.h:910
Internal (package scope) QS/C interface.
#define QS_U8_PRE_(data_)
Definition: qs_pkg.h:151
#define QS_BEGIN_NOCRIT_PRE_(rec_, qs_id_)
Definition: qs_pkg.h:138
#define QS_INSERT_ESC_BYTE_(b_)
Definition: qs_pkg.h:281
#define QS_OBJ_PRE_(obj_)
Definition: qs_pkg.h:179
#define QS_FUN_PRE_(fun_)
Definition: qs_pkg.h:182
#define QS_ESC
Definition: qs_pkg.h:70
#define QS_END_NOCRIT_PRE_()
Definition: qs_pkg.h:148
#define QS_U16_PRE_(data_)
Definition: qs_pkg.h:158
#define QS_ESC_XOR
Definition: qs_pkg.h:81
#define QS_SIG_PRE_(sig_)
Definition: qs_pkg.h:172
#define QS_FRAME
Definition: qs_pkg.h:67
#define QS_INSERT_BYTE_(b_)
Definition: qs_pkg.h:273
#define QS_STR_PRE_(msg_)
Definition: qs_pkg.h:164
char const Q_BUILD_TIME[9]
Definition: qstamp.c:45
char const Q_BUILD_DATE[12]
Definition: qstamp.c:42
Application build time-stamp interface.
#define QF_MAX_TICK_RATE
#define QF_MAX_ACTIVE
#define QS_TIME_SIZE
#define QS_FUN_PTR_SIZE
#define QS_OBJ_PTR_SIZE
void QS_locFilter_(int_fast16_t const filter)
Definition: qs.c:308
uint8_t const * QS_getBlock(uint16_t *pNbytes)
Definition: qs.c:798
void QS_endRec_(void)
Definition: qs.c:399
void QS_ASSERTION(char const *const module, int_t const loc, uint32_t delay)
Definition: qs.c:1032
void QS_onCleanup(void)
void QS_sig_dict_pre_(enum_t const sig, void const *const obj, char const *name)
Definition: qs.c:836
void QF_QS_ISR_ENTRY(uint8_t const isrnest, uint8_t const prio)
Definition: qs.c:1072
void QS_u16_raw_(uint16_t d)
Definition: qs.c:657
void QF_QS_CRIT_EXIT(void)
Definition: qs.c:1060
void QS_u16_fmt_(uint8_t format, uint16_t d)
Definition: qs.c:567
void QS_target_info_pre_(uint8_t isReset)
Definition: qs.c:430
void QS_u32_raw_(uint32_t d)
Definition: qs.c:680
void QS_initBuf(uint8_t sto[], uint_fast16_t stoSize)
Definition: qs.c:68
void QS_str_fmt_(char const *str)
Definition: qs.c:1005
void QS_u64_raw_(uint64_t d)
Definition: qs_64bit.c:43
void QS_fun_dict_pre_(void(*const fun)(void), char const *name)
Definition: qs.c:939
void QS_u32_fmt_(uint8_t format, uint32_t d)
Definition: qs.c:591
void QF_QS_ISR_EXIT(uint8_t const isrnest, uint8_t const prio)
Definition: qs.c:1082
void QS_usr_dict_pre_(enum_t const rec, char const *const name)
Definition: qs.c:956
void QS_u8_fmt_(uint8_t format, uint8_t d)
Definition: qs.c:545
void QS_str_raw_(char const *str)
Definition: qs.c:723
void QS_2u8_raw_(uint8_t d1, uint8_t d2)
Definition: qs.c:637
void QS_obj_dict_pre_(void const *const obj, char const *name)
Definition: qs.c:856
void QS_beginRec_(uint_fast8_t rec)
Definition: qs.c:371
void QS_onFlush(void)
void QS_u8_raw_(uint8_t d)
Definition: qs.c:618
uint16_t QS_getByte(void)
Definition: qs.c:755
void QS_glbFilter_(int_fast16_t const filter)
Definition: qs.c:112
void QS_obj_arr_dict_pre_(void const *const obj, uint_fast16_t idx, char const *name)
Definition: qs.c:875
void QS_obj_raw_(void const *const obj)
Definition: qs.c:703
void QF_QS_CRIT_ENTRY(void)
Definition: qs.c:1052
void QS_mem_fmt_(uint8_t const *blk, uint8_t size)
Definition: qs.c:976