QP/C++  7.3.3
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qs.cpp
Go to the documentation of this file.
1//$file${src::qs::qs.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpcpp.qm
4// File: ${src::qs::qs.cpp}
5//
6// This code has been generated by QM 6.1.1 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// This code is covered by the following QP license:
10// License # : LicenseRef-QL-dual
11// Issued to : Any user of the QP/C++ real-time embedded framework
12// Framework(s) : qpcpp
13// Support ends : 2024-12-31
14// License scope:
15//
16// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17//
18// Q u a n t u m L e a P s
19// ------------------------
20// Modern Embedded Software
21//
22// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
23//
24// This software is dual-licensed under the terms of the open source GNU
25// General Public License version 3 (or any later version), or alternatively,
26// under the terms of one of the closed source Quantum Leaps commercial
27// licenses.
28//
29// The terms of the open source GNU General Public License version 3
30// can be found at: <www.gnu.org/licenses/gpl-3.0>
31//
32// The terms of the closed source Quantum Leaps commercial licenses
33// can be found at: <www.state-machine.com/licensing>
34//
35// Redistributions in source code must retain this top-level comment block.
36// Plagiarizing this software to sidestep the license obligations is illegal.
37//
38// Contact information:
39// <www.state-machine.com/licensing>
40// <info@state-machine.com>
41//
42//$endhead${src::qs::qs.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qs_port.hpp" // QS port
45#include "qs_pkg.hpp" // QS package-scope internal interface
46#include "qstamp.hpp" // QP time-stamp
47#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
48
49// unnamed namespace for local definitions with internal linkage
50namespace {
51Q_DEFINE_THIS_MODULE("qs")
52} // unnamed namespace
53
54//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
55// Check for the minimum required QP version
56#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
57#error qpcpp version 7.3.0 or higher required
58#endif
59//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
60
61//$define${QS::QS-TX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
62namespace QP {
63namespace QS {
64
65//${QS::QS-TX::initBuf} ......................................................
67 std::uint8_t * const sto,
68 std::uint_fast32_t const stoSize) noexcept
69{
70 priv_.buf = sto;
71 priv_.end = static_cast<QSCtr>(stoSize);
72 priv_.head = 0U;
73 priv_.tail = 0U;
74 priv_.used = 0U;
75 priv_.seq = 0U;
76 priv_.chksum = 0U;
77 priv_.critNest = 0U;
78
79 glbFilter_(-static_cast<enum_t>(QS_ALL_RECORDS));// all global filters OFF
80 locFilter_(static_cast<enum_t>(QS_ALL_IDS)); // all local filters ON
81 priv_.locFilter_AP = nullptr; // deprecated "AP-filter"
82
83 // produce an empty record to "flush" the QS trace buffer
84 beginRec_(QS_REC_NUM_(QS_EMPTY));
85 endRec_();
86
87 // produce the reset record to inform QSPY of a new session
88 target_info_pre_(0xFFU);
89
90 // hold off flushing after successful initialization (see QS_INIT())
91}
92
93//${QS::QS-TX::getByte} ......................................................
94std::uint16_t getByte() noexcept {
95 // NOTE: Must be called IN critical section.
96 // Also requires system-level memory access (QF_MEM_SYS()).
97
98 std::uint16_t ret;
99 if (priv_.used == 0U) {
100 ret = QS_EOD; // set End-Of-Data
101 }
102 else {
103 std::uint8_t const * const buf = priv_.buf; // put in a temporary
104 QSCtr tail = priv_.tail; // put in a temporary (register)
105 ret = static_cast<std::uint16_t>(buf[tail]); // set the byte to return
106 ++tail; // advance the tail
107 if (tail == priv_.end) { // tail wrap around?
108 tail = 0U;
109 }
110 priv_.tail = tail; // update the tail
111 priv_.used = (priv_.used - 1U); // one less byte used
112 }
113 return ret; // return the byte or EOD
114}
115
116//${QS::QS-TX::getBlock} .....................................................
117std::uint8_t const * getBlock(std::uint16_t * const pNbytes) noexcept {
118 // NOTE: Must be called IN critical section.
119 // Also requires system-level memory access (QF_MEM_SYS()).
120
121 QSCtr const used = priv_.used; // put in a temporary (register)
122 std::uint8_t *buf;
123
124 // any bytes used in the ring buffer?
125 if (used != 0U) {
126 QSCtr tail = priv_.tail; // put in a temporary (register)
127 QSCtr const end = priv_.end; // put in a temporary (register)
128 QSCtr n = static_cast<QSCtr>(end - tail);
129 if (n > used) {
130 n = used;
131 }
132 if (n > static_cast<QSCtr>(*pNbytes)) {
133 n = static_cast<QSCtr>(*pNbytes);
134 }
135 *pNbytes = static_cast<std::uint16_t>(n); // n-bytes available
136 buf = priv_.buf;
137 buf = &buf[tail]; // the bytes are at the tail
138
139 priv_.used = static_cast<QSCtr>(used - n);
140 tail += n;
141 if (tail == end) {
142 tail = 0U;
143 }
144 priv_.tail = tail;
145 }
146 else { // no bytes available
147 *pNbytes = 0U; // no bytes available right now
148 buf = nullptr; // no bytes available right now
149 }
150 return buf;
151}
152
153} // namespace QS
154} // namespace QP
155//$enddef${QS::QS-TX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
156
157#ifndef QF_MEM_ISOLATE
158//$define${QS::filters} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
159namespace QP {
160namespace QS {
161
162//${QS::filters::filt_} ......................................................
164
165} // namespace QS
166} // namespace QP
167//$enddef${QS::filters} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
168#endif
169
170//============================================================================
171//! @cond INTERNAL
172
173namespace QP {
174namespace QS {
175
176//............................................................................
177Attr priv_;
178
179//............................................................................
180void glbFilter_(std::int_fast16_t const filter) noexcept {
181 bool const isRemove = (filter < 0);
182 std::uint16_t const rec = isRemove
183 ? static_cast<std::uint16_t>(-filter)
184 : static_cast<std::uint16_t>(filter);
185 switch (rec) {
186 case QS_ALL_RECORDS: {
187 std::uint8_t const tmp = (isRemove ? 0x00U : 0xFFU);
188 std::uint_fast8_t i;
189 // set all global filters (partially unrolled loop)
190 for (i = 0U; i < Q_DIM(filt_.glb); i += 4U) {
191 filt_.glb[i ] = tmp;
192 filt_.glb[i + 1U] = tmp;
193 filt_.glb[i + 2U] = tmp;
194 filt_.glb[i + 3U] = tmp;
195 }
196 if (isRemove) {
197 // leave the "not maskable" filters enabled,
198 // see qs.h, Miscellaneous QS records (not maskable)
199 //
200 filt_.glb[0] = 0x01U;
201 filt_.glb[6] = 0x40U;
202 filt_.glb[7] = 0xFCU;
203 filt_.glb[8] = 0x7FU;
204 }
205 else {
206 // never turn the last 3 records on (0x7D, 0x7E, 0x7F)
207 filt_.glb[15] = 0x1FU;
208 }
209 break;
210 }
211 case QS_SM_RECORDS:
212 if (isRemove) {
213 filt_.glb[0] &= static_cast<std::uint8_t>(~0xFEU & 0xFFU);
214 filt_.glb[1] &= static_cast<std::uint8_t>(~0x03U & 0xFFU);
215 filt_.glb[6] &= static_cast<std::uint8_t>(~0x80U & 0xFFU);
216 filt_.glb[7] &= static_cast<std::uint8_t>(~0x03U & 0xFFU);
217 }
218 else {
219 filt_.glb[0] |= 0xFEU;
220 filt_.glb[1] |= 0x03U;
221 filt_.glb[6] |= 0x80U;
222 filt_.glb[7] |= 0x03U;
223 }
224 break;
225 case QS_AO_RECORDS:
226 if (isRemove) {
227 filt_.glb[1] &= static_cast<std::uint8_t>(~0xFCU & 0xFFU);
228 filt_.glb[2] &= static_cast<std::uint8_t>(~0x07U & 0xFFU);
229 filt_.glb[5] &= static_cast<std::uint8_t>(~0x20U & 0xFFU);
230 }
231 else {
232 filt_.glb[1] |= 0xFCU;
233 filt_.glb[2] |= 0x07U;
234 filt_.glb[5] |= 0x20U;
235 }
236 break;
237 case QS_EQ_RECORDS:
238 if (isRemove) {
239 filt_.glb[2] &= static_cast<std::uint8_t>(~0x78U & 0xFFU);
240 filt_.glb[5] &= static_cast<std::uint8_t>(~0x40U & 0xFFU);
241 }
242 else {
243 filt_.glb[2] |= 0x78U;
244 filt_.glb[5] |= 0x40U;
245 }
246 break;
247 case QS_MP_RECORDS:
248 if (isRemove) {
249 filt_.glb[3] &= static_cast<std::uint8_t>(~0x03U & 0xFFU);
250 filt_.glb[5] &= static_cast<std::uint8_t>(~0x80U & 0xFFU);
251 }
252 else {
253 filt_.glb[3] |= 0x03U;
254 filt_.glb[5] |= 0x80U;
255 }
256 break;
257 case QS_QF_RECORDS:
258 if (isRemove) {
259 filt_.glb[2] &= static_cast<std::uint8_t>(~0x80U & 0xFFU);
260 filt_.glb[3] &= static_cast<std::uint8_t>(~0xFCU & 0xFFU);
261 filt_.glb[4] &= static_cast<std::uint8_t>(~0xC0U & 0xFFU);
262 filt_.glb[5] &= static_cast<std::uint8_t>(~0x1FU & 0xFFU);
263 }
264 else {
265 filt_.glb[2] |= 0x80U;
266 filt_.glb[3] |= 0xFCU;
267 filt_.glb[4] |= 0xC0U;
268 filt_.glb[5] |= 0x1FU;
269 }
270 break;
271 case QS_TE_RECORDS:
272 if (isRemove) {
273 filt_.glb[4] &= static_cast<std::uint8_t>(~0x3FU & 0xFFU);
274 }
275 else {
276 filt_.glb[4] |= 0x3FU;
277 }
278 break;
279 case QS_SC_RECORDS:
280 if (isRemove) {
281 filt_.glb[6] &= static_cast<std::uint8_t>(~0x3FU & 0xFFU);
282 }
283 else {
284 filt_.glb[6] |= 0x3FU;
285 }
286 break;
287 case QS_SEM_RECORDS:
288 if (isRemove) {
289 filt_.glb[8] &= static_cast<std::uint8_t>(~0x80U & 0xFFU);
290 filt_.glb[9] &= static_cast<std::uint8_t>(~0x07U & 0xFFU);
291 }
292 else {
293 filt_.glb[8] |= 0x80U;
294 filt_.glb[9] |= 0x07U;
295 }
296 break;
297 case QS_MTX_RECORDS:
298 if (isRemove) {
299 filt_.glb[9] &= static_cast<std::uint8_t>(~0xF8U & 0xFFU);
300 filt_.glb[10] &= static_cast<std::uint8_t>(~0x01U & 0xFFU);
301 }
302 else {
303 filt_.glb[9] |= 0xF8U;
304 filt_.glb[10] |= 0x01U;
305 }
306 break;
307 case QS_U0_RECORDS:
308 if (isRemove) {
309 filt_.glb[12] &= static_cast<std::uint8_t>(~0xF0U & 0xFFU);
310 filt_.glb[13] &= static_cast<std::uint8_t>(~0x01U & 0xFFU);
311 }
312 else {
313 filt_.glb[12] |= 0xF0U;
314 filt_.glb[13] |= 0x01U;
315 }
316 break;
317 case QS_U1_RECORDS:
318 if (isRemove) {
319 filt_.glb[13] &= static_cast<std::uint8_t>(~0x3EU & 0xFFU);
320 }
321 else {
322 filt_.glb[13] |= 0x3EU;
323 }
324 break;
325 case QS_U2_RECORDS:
326 if (isRemove) {
327 filt_.glb[13] &= static_cast<std::uint8_t>(~0xC0U & 0xFFU);
328 filt_.glb[14] &= static_cast<std::uint8_t>(~0x07U & 0xFFU);
329 }
330 else {
331 filt_.glb[13] |= 0xC0U;
332 filt_.glb[14] |= 0x07U;
333 }
334 break;
335 case QS_U3_RECORDS:
336 if (isRemove) {
337 filt_.glb[14] &= static_cast<std::uint8_t>(~0xF8U & 0xFFU);
338 }
339 else {
340 filt_.glb[14] |= 0xF8U;
341 }
342 break;
343 case QS_U4_RECORDS:
344 if (isRemove) {
345 filt_.glb[15] &= static_cast<std::uint8_t>(~0x1FU & 0xFFU);
346 }
347 else {
348 filt_.glb[15] |= 0x1FU;
349 }
350 break;
351 case QS_UA_RECORDS:
352 if (isRemove) {
353 filt_.glb[12] &= static_cast<std::uint8_t>(~0xF0U & 0xFFU);
354 filt_.glb[13] = 0U;
355 filt_.glb[14] = 0U;
356 filt_.glb[15] &= static_cast<std::uint8_t>(~0x1FU & 0xFFU);
357 }
358 else {
359 filt_.glb[12] |= 0xF0U;
360 filt_.glb[13] |= 0xFFU;
361 filt_.glb[14] |= 0xFFU;
362 filt_.glb[15] |= 0x1FU;
363 }
364 break;
365 default: {
368 // QS rec number must be below 0x7D, so no need for escaping
369 Q_ASSERT_INCRIT(210, rec < 0x7DU);
370 QS_CRIT_EXIT();
371
372 if (isRemove) {
373 filt_.glb[rec >> 3U]
374 &= static_cast<std::uint8_t>(~(1U << (rec & 7U)) & 0xFFU);
375 }
376 else {
377 filt_.glb[rec >> 3U]
378 |= static_cast<std::uint8_t>(1U << (rec & 7U));
379 // never turn the last 3 records on (0x7D, 0x7E, 0x7F)
380 filt_.glb[15] &= 0x1FU;
381 }
382 break;
383 }
384 }
385}
386
387//............................................................................
388void locFilter_(std::int_fast16_t const filter) noexcept {
389 bool const isRemove = (filter < 0);
390 std::uint16_t const qsId = isRemove
391 ? static_cast<std::uint16_t>(-filter)
392 : static_cast<std::uint16_t>(filter);
393 std::uint8_t const tmp = (isRemove ? 0x00U : 0xFFU);
394 std::uint_fast8_t i;
395 switch (qsId) {
396 case QS_ALL_IDS:
397 // set all local filters (partially unrolled loop)
398 for (i = 0U; i < Q_DIM(filt_.loc); i += 4U) {
399 filt_.loc[i ] = tmp;
400 filt_.loc[i + 1U] = tmp;
401 filt_.loc[i + 2U] = tmp;
402 filt_.loc[i + 3U] = tmp;
403 }
404 break;
405 case QS_AO_IDS:
406 for (i = 0U; i < 8U; i += 4U) {
407 filt_.loc[i ] = tmp;
408 filt_.loc[i + 1U] = tmp;
409 filt_.loc[i + 2U] = tmp;
410 filt_.loc[i + 3U] = tmp;
411 }
412 break;
413 case QS_EP_IDS:
414 i = 8U;
415 filt_.loc[i ] = tmp;
416 filt_.loc[i + 1U] = tmp;
417 break;
418 case QS_AP_IDS:
419 i = 12U;
420 filt_.loc[i ] = tmp;
421 filt_.loc[i + 1U] = tmp;
422 filt_.loc[i + 2U] = tmp;
423 filt_.loc[i + 3U] = tmp;
424 break;
425 default: {
428 // qsId must be in range
429 Q_ASSERT_INCRIT(310, qsId < 0x7FU);
430 QS_CRIT_EXIT();
431 if (isRemove) {
432 filt_.loc[qsId >> 3U] &=
433 static_cast<std::uint8_t>(
434 ~(1U << (qsId & 7U)) & 0xFFU);
435 }
436 else {
437 filt_.loc[qsId >> 3U]
438 |= (1U << (qsId & 7U));
439 }
440 break;
441 }
442 }
443 filt_.loc[0] |= 0x01U; // leave QS_ID == 0 always on
444}
445
446//............................................................................
447void beginRec_(std::uint_fast8_t const rec) noexcept {
448 std::uint8_t const b = priv_.seq + 1U;
449 std::uint8_t chksum = 0U; // reset the checksum
450 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
451 QSCtr head = priv_.head; // put in a temporary (register)
452 QSCtr const end = priv_.end; // put in a temporary (register)
453
454 priv_.seq = b; // store the incremented sequence num
455 priv_.used = (priv_.used + 2U); // 2 bytes about to be added
456
457 QS_INSERT_ESC_BYTE_(b)
458
459 chksum += static_cast<std::uint8_t>(rec);
460 QS_INSERT_BYTE_(static_cast<std::uint8_t>(rec)) // no need for escaping
461
462 priv_.head = head; // save the head
463 priv_.chksum = chksum; // save the checksum
464}
465
466//............................................................................
467void endRec_() noexcept {
468 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
469 QSCtr head = priv_.head;
470 QSCtr const end = priv_.end;
471 std::uint8_t b = priv_.chksum;
472 b ^= 0xFFU; // invert the bits in the checksum
473
474 priv_.used = (priv_.used + 2U); // 2 bytes about to be added
475
476 if ((b != QS_FRAME) && (b != QS_ESC)) {
477 QS_INSERT_BYTE_(b)
478 }
479 else {
480 QS_INSERT_BYTE_(QS_ESC)
481 QS_INSERT_BYTE_(b ^ QS_ESC_XOR)
482 priv_.used = (priv_.used + 1U); // account for the ESC byte
483 }
484
485 QS_INSERT_BYTE_(QS_FRAME) // do not escape this QS_FRAME
486
487 priv_.head = head; // save the head
488 if (priv_.used > end) { // overrun over the old data?
489 priv_.used = end; // the whole buffer is used
490 priv_.tail = head; // shift the tail to the old data
491 }
492}
493
494//............................................................................
495void u8_raw_(std::uint8_t const d) noexcept {
496 std::uint8_t chksum = priv_.chksum; // put in a temporary (register)
497 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
498 QSCtr head = priv_.head; // put in a temporary (register)
499 QSCtr const end = priv_.end; // put in a temporary (register)
500
501 priv_.used = (priv_.used + 1U); // 1 byte about to be added
502 QS_INSERT_ESC_BYTE_(d)
503
504 priv_.head = head; // save the head
505 priv_.chksum = chksum; // save the checksum
506}
507
508//............................................................................
509void u8u8_raw_(
510 std::uint8_t const d1,
511 std::uint8_t const d2) noexcept
512{
513 std::uint8_t chksum = priv_.chksum; // put in a temporary (register)
514 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
515 QSCtr head = priv_.head; // put in a temporary (register)
516 QSCtr const end = priv_.end; // put in a temporary (register)
517
518 priv_.used = (priv_.used + 2U); // 2 bytes about to be added
519 QS_INSERT_ESC_BYTE_(d1)
520 QS_INSERT_ESC_BYTE_(d2)
521
522 priv_.head = head; // save the head
523 priv_.chksum = chksum; // save the checksum
524}
525
526//............................................................................
527void u16_raw_(std::uint16_t d) noexcept {
528 std::uint8_t b = static_cast<std::uint8_t>(d);
529 std::uint8_t chksum = priv_.chksum; // put in a temporary (register)
530 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
531 QSCtr head = priv_.head; // put in a temporary (register)
532 QSCtr const end = priv_.end; // put in a temporary (register)
533
534 priv_.used = (priv_.used + 2U); // 2 bytes about to be added
535
536 QS_INSERT_ESC_BYTE_(b)
537
538 d >>= 8U;
539 b = static_cast<std::uint8_t>(d);
540 QS_INSERT_ESC_BYTE_(b)
541
542 priv_.head = head; // save the head
543 priv_.chksum = chksum; // save the checksum
544}
545
546//............................................................................
547void u32_raw_(std::uint32_t d) noexcept {
548 std::uint8_t chksum = priv_.chksum; // put in a temporary (register)
549 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
550 QSCtr head = priv_.head; // put in a temporary (register)
551 QSCtr const end = priv_.end; // put in a temporary (register)
552
553 priv_.used = (priv_.used + 4U); // 4 bytes about to be added
554 for (std::uint_fast8_t i = 4U; i != 0U; --i) {
555 std::uint8_t const b = static_cast<std::uint8_t>(d);
556 QS_INSERT_ESC_BYTE_(b)
557 d >>= 8U;
558 }
559
560 priv_.head = head; // save the head
561 priv_.chksum = chksum; // save the checksum
562}
563
564//............................................................................
565void obj_raw_(void const * const obj) noexcept {
566 #if (QS_OBJ_PTR_SIZE == 1U)
567 u8_raw_(reinterpret_cast<std::uint8_t>(obj));
568 #elif (QS_OBJ_PTR_SIZE == 2U)
569 u16_raw_(reinterpret_cast<std::uint16_t>(obj));
570 #elif (QS_OBJ_PTR_SIZE == 4U)
571 u32_raw_(reinterpret_cast<std::uint32_t>(obj));
572 #elif (QS_OBJ_PTR_SIZE == 8U)
573 u64_raw_(reinterpret_cast<std::uint64_t>(obj));
574 #else
575 u32_raw_(reinterpret_cast<std::uint32_t>(obj));
576 #endif
577}
578
579//............................................................................
580void str_raw_(char const * s) noexcept {
581 std::uint8_t b = static_cast<std::uint8_t>(*s);
582 std::uint8_t chksum = priv_.chksum; // put in a temporary (register)
583 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
584 QSCtr head = priv_.head; // put in a temporary (register)
585 QSCtr const end = priv_.end; // put in a temporary (register)
586 QSCtr used = priv_.used; // put in a temporary (register)
587
588 while (b != 0U) {
589 chksum += b; // update checksum
590 QS_INSERT_BYTE_(b) // ASCII characters don't need escaping
591 ++s;
592 b = static_cast<std::uint8_t>(*s);
593 ++used;
594 }
595 QS_INSERT_BYTE_(0U) // zero-terminate the string
596 ++used;
597
598 priv_.head = head; // save the head
599 priv_.chksum = chksum; // save the checksum
600 priv_.used = used; // save # of used buffer space
601}
602
603//............................................................................
604void u8_fmt_(
605 std::uint8_t const format,
606 std::uint8_t const d) noexcept
607{
608 std::uint8_t chksum = priv_.chksum; // put in a temporary (register)
609 std::uint8_t *const buf = priv_.buf; // put in a temporary (register)
610 QSCtr head = priv_.head; // put in a temporary (register)
611 QSCtr const end = priv_.end; // put in a temporary (register)
612
613 priv_.used = (priv_.used + 2U); // 2 bytes about to be added
614
615 QS_INSERT_ESC_BYTE_(format)
616 QS_INSERT_ESC_BYTE_(d)
617
618 priv_.head = head; // save the head
619 priv_.chksum = chksum; // save the checksum
620}
621
622//............................................................................
623void u16_fmt_(
624 std::uint8_t format,
625 std::uint16_t d) noexcept
626{
627 std::uint8_t chksum = priv_.chksum; // put in a temporary (register)
628 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
629 QSCtr head = priv_.head; // put in a temporary (register)
630 QSCtr const end = priv_.end; // put in a temporary (register)
631
632 priv_.used = (priv_.used + 3U); // 3 bytes about to be added
633
634 QS_INSERT_ESC_BYTE_(format)
635
636 format = static_cast<std::uint8_t>(d);
637 QS_INSERT_ESC_BYTE_(format)
638
639 d >>= 8U;
640 format = static_cast<std::uint8_t>(d);
641 QS_INSERT_ESC_BYTE_(format)
642
643 priv_.head = head; // save the head
644 priv_.chksum = chksum; // save the checksum
645}
646
647//............................................................................
648void u32_fmt_(
649 std::uint8_t format,
650 std::uint32_t d) noexcept
651{
652 std::uint8_t chksum = priv_.chksum; // put in a temporary (register)
653 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
654 QSCtr head = priv_.head; // put in a temporary (register)
655 QSCtr const end = priv_.end; // put in a temporary (register)
656
657 priv_.used = (priv_.used + 5U); // 5 bytes about to be added
658 QS_INSERT_ESC_BYTE_(format) // insert the format byte
659
660 for (std::uint_fast8_t i = 4U; i != 0U; --i) {
661 format = static_cast<std::uint8_t>(d);
662 QS_INSERT_ESC_BYTE_(format)
663 d >>= 8U;
664 }
665
666 priv_.head = head; // save the head
667 priv_.chksum = chksum; // save the checksum
668}
669
670//............................................................................
671void str_fmt_(char const * s) noexcept {
672 std::uint8_t b = static_cast<std::uint8_t>(*s);
673 std::uint8_t chksum = static_cast<std::uint8_t>(
674 priv_.chksum + static_cast<std::uint8_t>(STR_T));
675 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
676 QSCtr head = priv_.head; // put in a temporary (register)
677 QSCtr const end = priv_.end; // put in a temporary (register)
678 QSCtr used = priv_.used; // put in a temporary (register)
679
680 used += 2U; // the format byte and the terminating-0
681
682 QS_INSERT_BYTE_(static_cast<std::uint8_t>(STR_T))
683 while (b != 0U) {
684 // ASCII characters don't need escaping
685 chksum += b; // update checksum
686 QS_INSERT_BYTE_(b)
687 ++s;
688 b = static_cast<std::uint8_t>(*s);
689 ++used;
690 }
691 QS_INSERT_BYTE_(0U) // zero-terminate the string
692
693 priv_.head = head; // save the head
694 priv_.chksum = chksum; // save the checksum
695 priv_.used = used; // save # of used buffer space
696}
697
698//............................................................................
699void mem_fmt_(
700 std::uint8_t const * blk,
701 std::uint8_t size) noexcept
702{
703 std::uint8_t b = static_cast<std::uint8_t>(MEM_T);
704 std::uint8_t chksum = priv_.chksum + b;
705 std::uint8_t * const buf = priv_.buf; // put in a temporary (register)
706 QSCtr head = priv_.head; // put in a temporary (register)
707 QSCtr const end = priv_.end; // put in a temporary (register)
708
709 priv_.used = (priv_.used + size + 2U); // size+2 bytes to be added
710
711 QS_INSERT_BYTE_(b)
712 QS_INSERT_ESC_BYTE_(size)
713
714 // output the 'size' number of bytes
715 for (; size != 0U; --size) {
716 b = *blk;
717 QS_INSERT_ESC_BYTE_(b)
718 ++blk;
719 }
720
721 priv_.head = head; // save the head
722 priv_.chksum = chksum; // save the checksum
723}
724
725//............................................................................
726void sig_dict_pre_(
727 QSignal const sig,
728 void const * const obj,
729 char const * const name) noexcept
730{
733 QS_MEM_SYS();
734
735 beginRec_(static_cast<std::uint_fast8_t>(QS_SIG_DICT));
736 QS_SIG_PRE_(sig);
737 QS_OBJ_PRE_(obj);
738 QS_STR_PRE_((*name == '&') ? &name[1] : name);
739 endRec_();
740
741 QS_MEM_APP();
742 QS_CRIT_EXIT();
743 onFlush();
744}
745
746//............................................................................
747void obj_dict_pre_(
748 void const * const obj,
749 char const * const name) noexcept
750{
753 QS_MEM_SYS();
754
755 beginRec_(static_cast<std::uint_fast8_t>(QS_OBJ_DICT));
756 QS_OBJ_PRE_(obj);
757 QS_STR_PRE_((*name == '&') ? &name[1] : name);
758 endRec_();
759
760 QS_MEM_APP();
761 QS_CRIT_EXIT();
762 onFlush();
763}
764
765//............................................................................
766void obj_arr_dict_pre_(
767 void const * const obj,
768 std::uint_fast16_t const idx,
769 char const * const name) noexcept
770{
773 Q_REQUIRE_INCRIT(400, idx < 1000U);
774 QS_CRIT_EXIT();
775
776 // format idx into a char buffer as "xxx\0"
777 std::uint8_t idx_str[4];
778 std::uint_fast16_t tmp = idx;
779 std::uint8_t i;
780 idx_str[3] = 0U; // zero-terminate
781 idx_str[2] = static_cast<std::uint8_t>(
782 static_cast<std::uint8_t>('0') + (tmp % 10U));
783 tmp /= 10U;
784 idx_str[1] = static_cast<std::uint8_t>(
785 static_cast<std::uint8_t>('0') + (tmp % 10U));
786 if (idx_str[1] == static_cast<std::uint8_t>('0')) {
787 i = 2U;
788 }
789 else {
790 tmp /= 10U;
791 idx_str[0] = static_cast<std::uint8_t>(
792 static_cast<std::uint8_t>('0') + (tmp % 10U));
793 if (idx_str[0] == static_cast<std::uint8_t>('0')) {
794 i = 1U;
795 }
796 else {
797 i = 0U;
798 }
799 }
800
801 std::uint8_t j = ((*name == '&') ? 1U : 0U);
802
804 QS_MEM_SYS();
805
806 beginRec_(static_cast<std::uint_fast8_t>(QS_OBJ_DICT));
807 QS_OBJ_PRE_(obj);
808 for (; name[j] != '\0'; ++j) {
809 QS_U8_PRE_(name[j]);
810 if (name[j] == '[') {
811 ++j;
812 break;
813 }
814 }
815 for (; idx_str[i] != 0U; ++i) {
816 QS_U8_PRE_(idx_str[i]);
817 }
818 // skip chars until ']'
819 for (; name[j] != '\0'; ++j) {
820 if (name[j] == ']') {
821 break;
822 }
823 }
824 for (; name[j] != '\0'; ++j) {
825 QS_U8_PRE_(name[j]);
826 }
827 QS_U8_PRE_(0U); // zero-terminate
828 endRec_();
829
830 QS_MEM_APP();
831 QS_CRIT_EXIT();
832 onFlush();
833}
834
835//............................................................................
836void fun_dict_pre_(
837 QSpyFunPtr fun,
838 char const * const name) noexcept
839{
842 QS_MEM_SYS();
843
844 beginRec_(static_cast<std::uint_fast8_t>(QS_FUN_DICT));
845 QS_FUN_PRE_(fun);
846 QS_STR_PRE_((*name == '&') ? &name[1] : name);
847 endRec_();
848
849 QS_MEM_APP();
850 QS_CRIT_EXIT();
851 onFlush();
852}
853
854//............................................................................
855void usr_dict_pre_(
856 enum_t const rec,
857 char const * const name) noexcept
858{
861 QS_MEM_SYS();
862
863 beginRec_(static_cast<std::uint_fast8_t>(QS_USR_DICT));
864 QS_U8_PRE_(rec);
865 QS_STR_PRE_(name);
866 endRec_();
867
868 QS_MEM_APP();
869 QS_CRIT_EXIT();
870 onFlush();
871}
872
873//............................................................................
874void enum_dict_pre_(
875 enum_t const value,
876 std::uint8_t const group,
877 char const * const name) noexcept
878{
881 QS_MEM_SYS();
882
883 beginRec_(static_cast<std::uint_fast8_t>(QS_ENUM_DICT));
884 QS_2U8_PRE_(static_cast<std::uint8_t>(value), group);
885 QS_STR_PRE_(name);
886 endRec_();
887
888 QS_MEM_APP();
889 QS_CRIT_EXIT();
890 onFlush();
891}
892
893//............................................................................
894void assertion_pre_(
895 char const * const module,
896 int_t const id,
897 std::uint32_t const delay) noexcept
898{
899 // NOTE: called in a critical section
900
901 beginRec_(static_cast<std::uint_fast8_t>(QS_ASSERT_FAIL));
902 QS_TIME_PRE_();
903 QS_U16_PRE_(id);
904 QS_STR_PRE_((module != nullptr) ? module : "?");
905 endRec_();
906 onFlush();
907
908 // busy-wait until all QS data makes it over to the host
909 for (std::uint32_t volatile ctr = delay; ctr > 0U; ) {
910 ctr = (ctr - 1U);
911 }
913}
914
915//............................................................................
916void crit_entry_pre_() noexcept {
917 beginRec_(static_cast<std::uint_fast8_t>(QS_QF_CRIT_ENTRY));
918 QS_TIME_PRE_();
919 priv_.critNest = (priv_.critNest + 1U);
920 QS_U8_PRE_(priv_.critNest);
921 endRec_();
922}
923
924//............................................................................
925void crit_exit_pre_() noexcept {
926 beginRec_(static_cast<std::uint_fast8_t>(QS_QF_CRIT_EXIT));
927 QS_TIME_PRE_();
928 QS_U8_PRE_(QS::priv_.critNest);
929 priv_.critNest = (priv_.critNest - 1U);
930 endRec_();
931}
932
933//............................................................................
934void isr_entry_pre_(
935 std::uint8_t const isrnest,
936 std::uint8_t const prio) noexcept
937{
938 beginRec_(static_cast<std::uint_fast8_t>(QS_QF_ISR_ENTRY));
939 QS_TIME_PRE_();
940 QS_U8_PRE_(isrnest);
941 QS_U8_PRE_(prio);
942 endRec_();
943}
944
945//............................................................................
946void isr_exit_pre_(
947 std::uint8_t const isrnest,
948 std::uint8_t const prio) noexcept
949{
950 beginRec_(static_cast<std::uint_fast8_t>(QS_QF_ISR_EXIT));
951 QS_TIME_PRE_();
952 QS_U8_PRE_(isrnest);
953 QS_U8_PRE_(prio);
954 endRec_();
955}
956
957//............................................................................
958void target_info_pre_(std::uint8_t const isReset) {
959 // NOTE: called in a critical section
960
961 static constexpr std::uint8_t ZERO = static_cast<std::uint8_t>('0');
962 static std::uint8_t const * const TIME =
963 reinterpret_cast<std::uint8_t const *>(&BUILD_TIME[0]);
964 static std::uint8_t const * const DATE =
965 reinterpret_cast<std::uint8_t const *>(&BUILD_DATE[0]);
966
967 beginRec_(static_cast<std::uint_fast8_t>(QS_TARGET_INFO));
968 u8_raw_(isReset);
969
970 static union {
971 std::uint16_t u16;
972 std::uint8_t u8[2];
973 } endian_test;
974 endian_test.u16 = 0x0102U;
975 // big endian ? add the 0x8000U flag
976 QS_U16_PRE_(((endian_test.u8[0] == 0x01U)
977 ? (0x8000U | QP_VERSION)
978 : QP_VERSION)); // target endianness + version number
979
980 // send the object sizes...
981 u8_raw_(Q_SIGNAL_SIZE
982 | static_cast<std::uint8_t>(QF_EVENT_SIZ_SIZE << 4U));
983
984#ifdef QF_EQUEUE_CTR_SIZE
985 u8_raw_(QF_EQUEUE_CTR_SIZE
986 | static_cast<std::uint8_t>(QF_TIMEEVT_CTR_SIZE << 4U));
987#else
988 QS::u8_raw_(static_cast<std::uint8_t>(QF_TIMEEVT_CTR_SIZE << 4U));
989#endif // ifdef QF_EQUEUE_CTR_SIZE
990
991#ifdef QF_MPOOL_CTR_SIZE
992 QS::u8_raw_(QF_MPOOL_SIZ_SIZE
993 | static_cast<std::uint8_t>(QF_MPOOL_CTR_SIZE << 4U));
994#else
995 QS::u8_raw_(0U);
996#endif // ifdef QF_MPOOL_CTR_SIZE
997
998 QS::u8_raw_(QS_OBJ_PTR_SIZE | (QS_FUN_PTR_SIZE << 4U));
999 QS::u8_raw_(QS_TIME_SIZE);
1000
1001 // send the limits...
1002 QS::u8_raw_(QF_MAX_ACTIVE);
1003 QS::u8_raw_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE << 4U));
1004
1005 // send the build time in three bytes (sec, min, hour)...
1006 QS::u8_raw_((10U * (TIME[6] - ZERO)) + (TIME[7] - ZERO));
1007 QS::u8_raw_((10U * (TIME[3] - ZERO)) + (TIME[4] - ZERO));
1008 if (BUILD_TIME[0] == static_cast<std::uint8_t>(' ')) {
1009 QS::u8_raw_(TIME[1] - ZERO);
1010 }
1011 else {
1012 QS::u8_raw_((10U * (TIME[0] - ZERO)) + (TIME[1] - ZERO));
1013 }
1014
1015 // send the build date in three bytes (day, month, year) ...
1016 if (BUILD_DATE[4] == static_cast<std::uint8_t>(' ')) {
1017 QS::u8_raw_(DATE[5] - ZERO);
1018 }
1019 else {
1020 QS::u8_raw_((10U * (DATE[4] - ZERO)) + (DATE[5] - ZERO));
1021 }
1022 // convert the 3-letter month to a number 1-12 ...
1023 std::uint8_t b;
1024 switch (DATE[0] + DATE[1] + DATE[2]) {
1025 case 'J' + 'a' +'n':
1026 b = 1U;
1027 break;
1028 case 'F' + 'e' + 'b':
1029 b = 2U;
1030 break;
1031 case 'M' + 'a' +'r':
1032 b = 3U;
1033 break;
1034 case 'A' + 'p' + 'r':
1035 b = 4U;
1036 break;
1037 case 'M' + 'a' + 'y':
1038 b = 5U;
1039 break;
1040 case 'J' + 'u' + 'n':
1041 b = 6U;
1042 break;
1043 case 'J' + 'u' + 'l':
1044 b = 7U;
1045 break;
1046 case 'A' + 'u' + 'g':
1047 b = 8U;
1048 break;
1049 case 'S' + 'e' + 'p':
1050 b = 9U;
1051 break;
1052 case 'O' + 'c' + 't':
1053 b = 10U;
1054 break;
1055 case 'N' + 'o' + 'v':
1056 b = 11U;
1057 break;
1058 case 'D' + 'e' + 'c':
1059 b = 12U;
1060 break;
1061 default:
1062 b = 0U;
1063 break;
1064 }
1065 QS::u8_raw_(b); // store the month
1066 QS::u8_raw_((10U * (DATE[9] - ZERO)) + (DATE[10] - ZERO));
1067 QS::endRec_();
1068}
1069
1070} // namespace QS
1071} // namespace QP
1072
1073//! @endcond
QS type for output filters (global and local)
Definition qs.hpp:312
std::uint8_t glb[16]
Definition qs.hpp:314
std::uint8_t loc[16]
Definition qs.hpp:315
QF::Attr priv_
Definition qf_act.cpp:78
Filter filt_
Definition qs.cpp:163
std::uint16_t getByte() noexcept
Definition qs.cpp:94
@ STR_T
zero-terminated ASCII string format
Definition qs.hpp:704
@ MEM_T
up to 255-bytes memory block format
Definition qs.hpp:705
std::uint8_t const * getBlock(std::uint16_t *const pNbytes) noexcept
Definition qs.cpp:117
void onFlush()
void onCleanup()
void initBuf(std::uint8_t *const sto, std::uint_fast32_t const stoSize) noexcept
Definition qs.cpp:66
QP/C++ framework.
Definition qequeue.hpp:50
std::uint16_t QSignal
Definition qp.hpp:130
char const BUILD_DATE[12]
Definition qstamp.cpp:46
void(*)() QSpyFunPtr
Definition qs.hpp:283
@ QS_EP_IDS
event-pool IDs
Definition qs.hpp:237
@ QS_AP_IDS
Application-specific IDs.
Definition qs.hpp:239
@ QS_ALL_IDS
all QS IDs
Definition qs.hpp:235
@ QS_AO_IDS
AO IDs (priorities)
Definition qs.hpp:236
@ QS_MTX_RECORDS
Mutex QS records.
Definition qs.hpp:203
@ QS_UA_RECORDS
All User records.
Definition qs.hpp:209
@ QS_SEM_RECORDS
Semaphore QS records.
Definition qs.hpp:202
@ QS_ALL_RECORDS
all maskable QS records
Definition qs.hpp:194
@ QS_U0_RECORDS
User Group 100-104 records.
Definition qs.hpp:204
@ QS_EQ_RECORDS
Event Queues QS records.
Definition qs.hpp:197
@ QS_SC_RECORDS
Scheduler QS records.
Definition qs.hpp:201
@ QS_U2_RECORDS
User Group 110-114 records.
Definition qs.hpp:206
@ QS_SM_RECORDS
State Machine QS records.
Definition qs.hpp:195
@ QS_U4_RECORDS
User Group 120-124 records.
Definition qs.hpp:208
@ QS_U3_RECORDS
User Group 115-119 records.
Definition qs.hpp:207
@ QS_AO_RECORDS
Active Object QS records.
Definition qs.hpp:196
@ QS_TE_RECORDS
Time Events QS records.
Definition qs.hpp:199
@ QS_U1_RECORDS
User Group 105-109 records.
Definition qs.hpp:205
@ QS_MP_RECORDS
Memory Pools QS records.
Definition qs.hpp:198
@ QS_QF_RECORDS
QF QS records.
Definition qs.hpp:200
char const BUILD_TIME[9]
Definition qstamp.cpp:47
@ QS_FUN_DICT
function dictionary entry
Definition qs.hpp:163
@ QS_ASSERT_FAIL
assertion failed in the code
Definition qs.hpp:170
@ QS_USR_DICT
user QS record dictionary entry
Definition qs.hpp:164
@ QS_ENUM_DICT
enumeration dictionary entry
Definition qs.hpp:151
@ QS_SIG_DICT
signal dictionary entry
Definition qs.hpp:161
@ QS_OBJ_DICT
object dictionary entry
Definition qs.hpp:162
@ QS_QF_CRIT_ENTRY
critical section was entered
Definition qs.hpp:126
@ QS_QF_CRIT_EXIT
critical section was exited
Definition qs.hpp:127
@ QS_QF_ISR_ENTRY
an ISR was entered
Definition qs.hpp:128
@ QS_TARGET_INFO
reports the Target information
Definition qs.hpp:165
@ QS_QF_ISR_EXIT
an ISR was exited
Definition qs.hpp:129
@ QS_EMPTY
QS record for cleanly starting a session.
Definition qs.hpp:71
int int_t
Definition qp.hpp:105
int enum_t
Definition qp.hpp:108
#define QP_VERSION
Definition qp.hpp:47
#define Q_DIM(array_)
Definition qp.hpp:544
#define QF_EVENT_SIZ_SIZE
#define QS_TIME_SIZE
#define QF_MAX_TICK_RATE
#define QF_EQUEUE_CTR_SIZE
#define QS_FUN_PTR_SIZE
#define QF_MAX_ACTIVE
#define QF_TIMEEVT_CTR_SIZE
#define QS_OBJ_PTR_SIZE
#define QF_MPOOL_SIZ_SIZE
#define QF_MPOOL_CTR_SIZE
#define QF_MAX_EPOOL
#define Q_SIGNAL_SIZE
#define QS_CRIT_STAT
Definition qs.hpp:590
#define QS_TIME_PRE_()
Definition qs.hpp:473
#define QS_MEM_APP()
Definition qs.hpp:610
#define QS_CRIT_EXIT()
Definition qs.hpp:600
#define QS_MEM_SYS()
Definition qs.hpp:605
#define QS_EOD
Definition qs.hpp:580
#define QS_CRIT_ENTRY()
Definition qs.hpp:595
QS/C++ package-scope interface.
QS/C++ port to a 32-bit CPU, generic C++ compiler.
QP Functional Safety (FuSa) Subsystem.
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:72
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:136
Date/time for time-stamping the QP builds (used in QS software tracing)