QP/C  7.3.4
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qs.c
Go to the documentation of this file.
1//$file${src::qs::qs.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpc.qm
4// File: ${src::qs::qs.c}
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) : qpc
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.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qs_port.h" // QS port
45#include "qs_pkg.h" // QS package-scope interface
46#include "qstamp.h" // QP time-stamp
47#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
48
49Q_DEFINE_THIS_MODULE("qs")
50
51// ensure that the predefined records don't overlap the
52// user records (application-specific).
54
55//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
56// Check for the minimum required QP version
57#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
58#error qpc version 7.3.0 or higher required
59#endif
60//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
61
62//$define${QS::QS-TX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
63
64//${QS::QS-TX::initBuf} ......................................................
65//! @static @public @memberof QS
66void QS_initBuf(
67 uint8_t * const sto,
68 uint_fast32_t const stoSize)
69{
70 QS_priv_.buf = &sto[0];
71 QS_priv_.end = (QSCtr)stoSize;
72 QS_priv_.head = 0U;
73 QS_priv_.tail = 0U;
74 QS_priv_.used = 0U;
75 QS_priv_.seq = 0U;
76 QS_priv_.chksum = 0U;
77 QS_priv_.critNest = 0U;
78
79 QS_glbFilter_(-(int_fast16_t)QS_ALL_RECORDS); // all global filters OFF
80 QS_locFilter_((int_fast16_t)QS_ALL_IDS); // all local filters ON
81 QS_priv_.locFilter_AP = (void *)0; // deprecated "AP-filter"
82
83 // produce an empty record to "flush" the QS trace buffer
84 QS_beginRec_((uint_fast8_t)QS_EMPTY);
85 QS_endRec_();
86
87 // produce the reset record to inform QSPY of a new session
88 QS_target_info_pre_(0xFFU);
89
90 // hold off flushing after successful initialization (see QS_INIT())
91}
92
93//${QS::QS-TX::getByte} ......................................................
94//! @static @public @memberof QS
95uint16_t QS_getByte(void) {
96 uint16_t ret;
97 if (QS_priv_.used == 0U) {
98 ret = QS_EOD; // set End-Of-Data
99 }
100 else {
101 uint8_t const * const buf = QS_priv_.buf; // put in a temporary
102 QSCtr tail = QS_priv_.tail; // put in a temporary (register)
103 ret = (uint16_t)buf[tail]; // set the byte to return
104 ++tail; // advance the tail
105 if (tail == QS_priv_.end) { // tail wrap around?
106 tail = 0U;
107 }
108 QS_priv_.tail = tail; // update the tail
109 --QS_priv_.used; // one less byte used
110 }
111 return ret; // return the byte or EOD
112}
113
114//${QS::QS-TX::getBlock} .....................................................
115//! @static @public @memberof QS
116uint8_t const * QS_getBlock(uint16_t * const pNbytes) {
117 QSCtr const used = QS_priv_.used; // put in a temporary (register)
118 uint8_t const *buf;
119
120 // any bytes used in the ring buffer?
121 if (used != 0U) {
122 QSCtr tail = QS_priv_.tail; // put in a temporary (register)
123 QSCtr const end = QS_priv_.end; // put in a temporary (register)
124 QSCtr n = (QSCtr)(end - tail);
125 if (n > used) {
126 n = used;
127 }
128 if (n > (QSCtr)(*pNbytes)) {
129 n = (QSCtr)(*pNbytes);
130 }
131 *pNbytes = (uint16_t)n; // n-bytes available
132 buf = &QS_priv_.buf[tail]; // the bytes are at the tail
133
134 QS_priv_.used = (QSCtr)(used - n);
135 tail += n;
136 if (tail == end) {
137 tail = 0U;
138 }
139 QS_priv_.tail = tail;
140 }
141 else { // no bytes available
142 *pNbytes = 0U; // no bytes available right now
143 buf = (uint8_t *)0; // no bytes available right now
144 }
145 return buf;
146}
147//$enddef${QS::QS-TX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
148
149#ifndef QF_MEM_ISOLATE
150//$define${QS::filters} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
151
152//${QS::filters::filt_} ......................................................
153//! @static @private @memberof QS
154QS_Filter QS_filt_;
155//$enddef${QS::filters} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
156#endif
157
158//============================================================================
159//! @cond INTERNAL
160
161//! @static @private @memberof QS
162QS_Attr QS_priv_;
163
164//............................................................................
165void QS_glbFilter_(int_fast16_t const filter) {
166 bool const isRemove = (filter < 0);
167 uint8_t const rec = isRemove ? (uint8_t)(-filter) : (uint8_t)filter;
168 switch (rec) {
169 case (uint8_t)QS_ALL_RECORDS: {
170 uint8_t const tmp = (isRemove ? 0x00U : 0xFFU);
171
172 // set all global filters (partially unrolled loop)
173 for (uint_fast8_t i = 0U;
174 i < Q_DIM(QS_filt_.glb);
175 i += 4U)
176 {
177 QS_filt_.glb[i ] = tmp;
178 QS_filt_.glb[i + 1U] = tmp;
179 QS_filt_.glb[i + 2U] = tmp;
180 QS_filt_.glb[i + 3U] = tmp;
181 }
182 if (isRemove) {
183 // leave the "not maskable" filters enabled,
184 // see qs.h, Miscellaneous QS records (not maskable)
185 QS_filt_.glb[0] = 0x01U;
186 QS_filt_.glb[6] = 0x40U;
187 QS_filt_.glb[7] = 0xFCU;
188 QS_filt_.glb[8] = 0x7FU;
189 }
190 else {
191 // never turn the last 3 records on (0x7D, 0x7E, 0x7F)
192 QS_filt_.glb[15] = 0x1FU;
193 }
194 break;
195 }
196 case (uint8_t)QS_SM_RECORDS:
197 if (isRemove) {
198 QS_filt_.glb[0] &= (uint8_t)(~0xFEU & 0xFFU);
199 QS_filt_.glb[1] &= (uint8_t)(~0x03U & 0xFFU);
200 QS_filt_.glb[6] &= (uint8_t)(~0x80U & 0xFFU);
201 QS_filt_.glb[7] &= (uint8_t)(~0x03U & 0xFFU);
202 }
203 else {
204 QS_filt_.glb[0] |= 0xFEU;
205 QS_filt_.glb[1] |= 0x03U;
206 QS_filt_.glb[6] |= 0x80U;
207 QS_filt_.glb[7] |= 0x03U;
208 }
209 break;
210 case (uint8_t)QS_AO_RECORDS:
211 if (isRemove) {
212 QS_filt_.glb[1] &= (uint8_t)(~0xFCU & 0xFFU);
213 QS_filt_.glb[2] &= (uint8_t)(~0x07U & 0xFFU);
214 QS_filt_.glb[5] &= (uint8_t)(~0x20U & 0xFFU);
215 }
216 else {
217 QS_filt_.glb[1] |= 0xFCU;
218 QS_filt_.glb[2] |= 0x07U;
219 QS_filt_.glb[5] |= 0x20U;
220 }
221 break;
222 case (uint8_t)QS_EQ_RECORDS:
223 if (isRemove) {
224 QS_filt_.glb[2] &= (uint8_t)(~0x78U & 0xFFU);
225 QS_filt_.glb[5] &= (uint8_t)(~0x40U & 0xFFU);
226 }
227 else {
228 QS_filt_.glb[2] |= 0x78U;
229 QS_filt_.glb[5] |= 0x40U;
230 }
231 break;
232 case (uint8_t)QS_MP_RECORDS:
233 if (isRemove) {
234 QS_filt_.glb[3] &= (uint8_t)(~0x03U & 0xFFU);
235 QS_filt_.glb[5] &= (uint8_t)(~0x80U & 0xFFU);
236 }
237 else {
238 QS_filt_.glb[3] |= 0x03U;
239 QS_filt_.glb[5] |= 0x80U;
240 }
241 break;
242 case (uint8_t)QS_QF_RECORDS:
243 if (isRemove) {
244 QS_filt_.glb[2] &= (uint8_t)(~0x80U & 0xFFU);
245 QS_filt_.glb[3] &= (uint8_t)(~0xFCU & 0xFFU);
246 QS_filt_.glb[4] &= (uint8_t)(~0xC0U & 0xFFU);
247 QS_filt_.glb[5] &= (uint8_t)(~0x1FU & 0xFFU);
248 }
249 else {
250 QS_filt_.glb[2] |= 0x80U;
251 QS_filt_.glb[3] |= 0xFCU;
252 QS_filt_.glb[4] |= 0xC0U;
253 QS_filt_.glb[5] |= 0x1FU;
254 }
255 break;
256 case (uint8_t)QS_TE_RECORDS:
257 if (isRemove) {
258 QS_filt_.glb[4] &= (uint8_t)(~0x3FU & 0xFFU);
259 }
260 else {
261 QS_filt_.glb[4] |= 0x3FU;
262 }
263 break;
264 case (uint8_t)QS_SC_RECORDS:
265 if (isRemove) {
266 QS_filt_.glb[6] &= (uint8_t)(~0x3FU & 0xFFU);
267 }
268 else {
269 QS_filt_.glb[6] |= 0x3FU;
270 }
271 break;
272 case (uint8_t)QS_SEM_RECORDS:
273 if (isRemove) {
274 QS_filt_.glb[8] &= (uint8_t)(~0x80U & 0xFFU);
275 QS_filt_.glb[9] &= (uint8_t)(~0x07U & 0xFFU);
276 }
277 else {
278 QS_filt_.glb[8] |= 0x80U;
279 QS_filt_.glb[9] |= 0x07U;
280 }
281 break;
282 case (uint8_t)QS_MTX_RECORDS:
283 if (isRemove) {
284 QS_filt_.glb[9] &= (uint8_t)(~0xF8U & 0xFFU);
285 QS_filt_.glb[10] &= (uint8_t)(~0x01U & 0xFFU);
286 }
287 else {
288 QS_filt_.glb[9] |= 0xF8U;
289 QS_filt_.glb[10] |= 0x01U;
290 }
291 break;
292 case (uint8_t)QS_U0_RECORDS:
293 if (isRemove) {
294 QS_filt_.glb[12] &= (uint8_t)(~0xF0U & 0xFFU);
295 QS_filt_.glb[13] &= (uint8_t)(~0x01U & 0xFFU);
296 }
297 else {
298 QS_filt_.glb[12] |= 0xF0U;
299 QS_filt_.glb[13] |= 0x01U;
300 }
301 break;
302 case (uint8_t)QS_U1_RECORDS:
303 if (isRemove) {
304 QS_filt_.glb[13] &= (uint8_t)(~0x3EU & 0xFFU);
305 }
306 else {
307 QS_filt_.glb[13] |= 0x3EU;
308 }
309 break;
310 case (uint8_t)QS_U2_RECORDS:
311 if (isRemove) {
312 QS_filt_.glb[13] &= (uint8_t)(~0xC0U & 0xFFU);
313 QS_filt_.glb[14] &= (uint8_t)(~0x07U & 0xFFU);
314 }
315 else {
316 QS_filt_.glb[13] |= 0xC0U;
317 QS_filt_.glb[14] |= 0x07U;
318 }
319 break;
320 case (uint8_t)QS_U3_RECORDS:
321 if (isRemove) {
322 QS_filt_.glb[14] &= (uint8_t)(~0xF8U & 0xFFU);
323 }
324 else {
325 QS_filt_.glb[14] |= 0xF8U;
326 }
327 break;
328 case (uint8_t)QS_U4_RECORDS:
329 if (isRemove) {
330 QS_filt_.glb[15] &= (uint8_t)(~0x1FU & 0xFFU);
331 }
332 else {
333 QS_filt_.glb[15] |= 0x1FU;
334 }
335 break;
336 case (uint8_t)QS_UA_RECORDS:
337 if (isRemove) {
338 QS_filt_.glb[12] &= (uint8_t)(~0xF0U & 0xFFU);
339 QS_filt_.glb[13] = 0U;
340 QS_filt_.glb[14] = 0U;
341 QS_filt_.glb[15] &= (uint8_t)(~0x1FU & 0xFFU);
342 }
343 else {
344 QS_filt_.glb[12] |= 0xF0U;
345 QS_filt_.glb[13] |= 0xFFU;
346 QS_filt_.glb[14] |= 0xFFU;
347 QS_filt_.glb[15] |= 0x1FU;
348 }
349 break;
350 default: {
353 // QS rec number must be below 0x7D, so no need for escaping
354 Q_ASSERT_INCRIT(210, rec < 0x7DU);
355 QS_CRIT_EXIT();
356
357 if (isRemove) {
358 QS_filt_.glb[rec >> 3U]
359 &= (uint8_t)(~(1U << (rec & 7U)) & 0xFFU);
360 }
361 else {
362 QS_filt_.glb[rec >> 3U]
363 |= (1U << (rec & 7U));
364 // never turn the last 3 records on (0x7D, 0x7E, 0x7F)
365 QS_filt_.glb[15] &= 0x1FU;
366 }
367 break;
368 }
369 }
370}
371
372//............................................................................
373void QS_locFilter_(int_fast16_t const filter) {
374 bool const isRemove = (filter < 0);
375 uint8_t const qsId = isRemove ? (uint8_t)(-filter) : (uint8_t)filter;
376 uint8_t const tmp = (isRemove ? 0x00U : 0xFFU);
377 uint_fast8_t i;
378 switch (qsId) {
379 case (uint8_t)QS_ALL_IDS:
380 // set all local filters (partially unrolled loop)
381 for (i = 0U; i < Q_DIM(QS_filt_.loc); i += 4U) {
382 QS_filt_.loc[i ] = tmp;
383 QS_filt_.loc[i + 1U] = tmp;
384 QS_filt_.loc[i + 2U] = tmp;
385 QS_filt_.loc[i + 3U] = tmp;
386 }
387 break;
388 case (uint8_t)QS_AO_IDS:
389 for (i = 0U; i < 8U; i += 4U) {
390 QS_filt_.loc[i ] = tmp;
391 QS_filt_.loc[i + 1U] = tmp;
392 QS_filt_.loc[i + 2U] = tmp;
393 QS_filt_.loc[i + 3U] = tmp;
394 }
395 break;
396 case (uint8_t)QS_EP_IDS:
397 i = 8U;
398 QS_filt_.loc[i ] = tmp;
399 QS_filt_.loc[i + 1U] = tmp;
400 break;
401 case (uint8_t)QS_AP_IDS:
402 i = 12U;
403 QS_filt_.loc[i ] = tmp;
404 QS_filt_.loc[i + 1U] = tmp;
405 QS_filt_.loc[i + 2U] = tmp;
406 QS_filt_.loc[i + 3U] = tmp;
407 break;
408 default: {
411 // qsId must be in range
412 Q_ASSERT_INCRIT(310, qsId < 0x7FU);
413 QS_CRIT_EXIT();
414 if (isRemove) {
415 QS_filt_.loc[qsId >> 3U]
416 &= (uint8_t)(~(1U << (qsId & 7U)) & 0xFFU);
417 }
418 else {
419 QS_filt_.loc[qsId >> 3U]
420 |= (1U << (qsId & 7U));
421 }
422 break;
423 }
424 }
425 QS_filt_.loc[0] |= 0x01U; // leave QS_ID == 0 always on
426}
427
428//............................................................................
429void QS_beginRec_(uint_fast8_t const rec) {
430 uint8_t const b = (uint8_t)(QS_priv_.seq + 1U);
431 uint8_t chksum = 0U; // reset the checksum
432 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
433 QSCtr head = QS_priv_.head; // put in a temporary (register)
434 QSCtr const end = QS_priv_.end; // put in a temporary (register)
435
436 QS_priv_.seq = b; // store the incremented sequence num
437 QS_priv_.used += 2U; // 2 bytes about to be added
438
439 QS_INSERT_ESC_BYTE_(b)
440
441 chksum = (uint8_t)(chksum + rec); // update checksum
442 QS_INSERT_BYTE_((uint8_t)rec) // rec byte does not need escaping
443
444 QS_priv_.head = head; // save the head
445 QS_priv_.chksum = chksum; // save the checksum
446}
447
448//............................................................................
449void QS_endRec_(void) {
450 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
451 QSCtr head = QS_priv_.head;
452 QSCtr const end = QS_priv_.end;
453 uint8_t b = QS_priv_.chksum;
454 b ^= 0xFFU; // invert the bits in the checksum
455
456 QS_priv_.used += 2U; // 2 bytes about to be added
457
458 if ((b != QS_FRAME) && (b != QS_ESC)) {
459 QS_INSERT_BYTE_(b)
460 }
461 else {
462 QS_INSERT_BYTE_(QS_ESC)
463 QS_INSERT_BYTE_(b ^ QS_ESC_XOR)
464 ++QS_priv_.used; // account for the ESC byte
465 }
466
467 QS_INSERT_BYTE_(QS_FRAME) // do not escape this QS_FRAME
468
469 QS_priv_.head = head; // save the head
470
471 // overrun over the old data?
472 if (QS_priv_.used > end) {
473 QS_priv_.used = end; // the whole buffer is used
474 QS_priv_.tail = head; // shift the tail to the old data
475 }
476}
477
478//............................................................................
479void QS_u8_raw_(uint8_t const d) {
480 uint8_t chksum = QS_priv_.chksum; // put in a temporary (register)
481 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
482 QSCtr head = QS_priv_.head; // put in a temporary (register)
483 QSCtr const end = QS_priv_.end; // put in a temporary (register)
484
485 QS_priv_.used += 1U; // 1 byte about to be added
486 QS_INSERT_ESC_BYTE_(d)
487
488 QS_priv_.head = head; // save the head
489 QS_priv_.chksum = chksum; // save the checksum
490}
491
492//............................................................................
493void QS_2u8_raw_(
494 uint8_t const d1,
495 uint8_t const d2)
496{
497 uint8_t chksum = QS_priv_.chksum; // put in a temporary (register)
498 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
499 QSCtr head = QS_priv_.head; // put in a temporary (register)
500 QSCtr const end = QS_priv_.end; // put in a temporary (register)
501
502 QS_priv_.used += 2U; // 2 bytes are about to be added
503 QS_INSERT_ESC_BYTE_(d1)
504 QS_INSERT_ESC_BYTE_(d2)
505
506 QS_priv_.head = head; // save the head
507 QS_priv_.chksum = chksum; // save the checksum
508}
509
510//............................................................................
511void QS_u16_raw_(uint16_t const d) {
512 uint8_t chksum = QS_priv_.chksum; // put in a temporary (register)
513 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
514 QSCtr head = QS_priv_.head; // put in a temporary (register)
515 QSCtr const end = QS_priv_.end; // put in a temporary (register)
516 uint16_t x = d;
517
518 QS_priv_.used += 2U; // 2 bytes are about to be added
519
520 QS_INSERT_ESC_BYTE_((uint8_t)x)
521 x >>= 8U;
522 QS_INSERT_ESC_BYTE_((uint8_t)x)
523
524 QS_priv_.head = head; // save the head
525 QS_priv_.chksum = chksum; // save the checksum
526}
527
528//............................................................................
529void QS_u32_raw_(uint32_t const d) {
530 uint8_t chksum = QS_priv_.chksum; // put in a temporary (register)
531 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
532 QSCtr head = QS_priv_.head; // put in a temporary (register)
533 QSCtr const end = QS_priv_.end; // put in a temporary (register)
534 uint32_t x = d;
535
536 QS_priv_.used += 4U; // 4 bytes are about to be added
537 for (uint_fast8_t i = 4U; i != 0U; --i) {
538 QS_INSERT_ESC_BYTE_((uint8_t)x)
539 x >>= 8U;
540 }
541
542 QS_priv_.head = head; // save the head
543 QS_priv_.chksum = chksum; // save the checksum
544}
545
546//............................................................................
547void QS_obj_raw_(void const * const obj) {
548 #if (QS_OBJ_PTR_SIZE == 1U)
549 QS_u8_raw_((uint8_t)obj);
550 #elif (QS_OBJ_PTR_SIZE == 2U)
551 QS_u16_raw_((uint16_t)obj);
552 #elif (QS_OBJ_PTR_SIZE == 4U)
553 QS_u32_raw_((uint32_t)obj);
554 #elif (QS_OBJ_PTR_SIZE == 8U)
555 QS_u64_raw_((uint64_t)obj);
556 #else
557 QS_u32_raw_((uint32_t)obj);
558 #endif
559}
560
561//............................................................................
562void QS_str_raw_(char const * const str) {
563 uint8_t chksum = QS_priv_.chksum; // put in a temporary (register)
564 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
565 QSCtr head = QS_priv_.head; // put in a temporary (register)
566 QSCtr const end = QS_priv_.end; // put in a temporary (register)
567 QSCtr used = QS_priv_.used; // put in a temporary (register)
568
569 for (char const *s = str; *s != '\0'; ++s) {
570 chksum += (uint8_t)*s; // update checksum
571 QS_INSERT_BYTE_((uint8_t)*s) // ASCII char doesn't need escaping
572 ++used;
573 }
574 QS_INSERT_BYTE_((uint8_t)'\0') // zero-terminate the string
575 ++used;
576
577 QS_priv_.head = head; // save the head
578 QS_priv_.chksum = chksum; // save the checksum
579 QS_priv_.used = used; // save # of used buffer space
580}
581
582//............................................................................
583void QS_u8_fmt_(
584 uint8_t const format,
585 uint8_t const d)
586{
587 uint8_t chksum = QS_priv_.chksum; // put in a temporary (register)
588 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
589 QSCtr head = QS_priv_.head; // put in a temporary (register)
590 QSCtr const end = QS_priv_.end; // put in a temporary (register)
591
592 QS_priv_.used += 2U; // 2 bytes about to be added
593
594 QS_INSERT_ESC_BYTE_(format)
595 QS_INSERT_ESC_BYTE_(d)
596
597 QS_priv_.head = head; // save the head
598 QS_priv_.chksum = chksum; // save the checksum
599}
600
601//............................................................................
602void QS_u16_fmt_(
603 uint8_t const format,
604 uint16_t const d)
605{
606 uint8_t chksum = QS_priv_.chksum; // put in a temporary (register)
607 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
608 QSCtr head = QS_priv_.head; // put in a temporary (register)
609 QSCtr const end = QS_priv_.end; // put in a temporary (register)
610 uint8_t b = (uint8_t)d;
611
612 QS_priv_.used += 3U; // 3 bytes about to be added
613
614 QS_INSERT_ESC_BYTE_(format)
615 QS_INSERT_ESC_BYTE_(b)
616 b = (uint8_t)(d >> 8U);
617 QS_INSERT_ESC_BYTE_(b)
618
619 QS_priv_.head = head; // save the head
620 QS_priv_.chksum = chksum; // save the checksum
621}
622
623//............................................................................
624void QS_u32_fmt_(
625 uint8_t const format,
626 uint32_t const d)
627{
628 uint8_t chksum = QS_priv_.chksum; // put in a temporary (register)
629 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
630 QSCtr head = QS_priv_.head; // put in a temporary (register)
631 QSCtr const end = QS_priv_.end; // put in a temporary (register)
632 uint32_t x = d;
633
634 QS_priv_.used += 5U; // 5 bytes about to be added
635 QS_INSERT_ESC_BYTE_(format) // insert the format byte
636
637 // insert 4 bytes...
638 for (uint_fast8_t i = 4U; i != 0U; --i) {
639 QS_INSERT_ESC_BYTE_((uint8_t)x)
640 x >>= 8U;
641 }
642
643 QS_priv_.head = head; // save the head
644 QS_priv_.chksum = chksum; // save the checksum
645}
646
647//............................................................................
648void QS_str_fmt_(char const * const str) {
649 uint8_t chksum = QS_priv_.chksum;
650 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
651 QSCtr head = QS_priv_.head; // put in a temporary (register)
652 QSCtr const end = QS_priv_.end; // put in a temporary (register)
653 QSCtr used = QS_priv_.used; // put in a temporary (register)
654
655 used += 2U; // account for the format byte and the terminating-0
656 QS_INSERT_BYTE_((uint8_t)QS_STR_T)
657 chksum += (uint8_t)QS_STR_T;
658
659 for (char const *s = str; *s != '\0'; ++s) {
660 QS_INSERT_BYTE_((uint8_t)*s) // ASCII char doesn't need escaping
661 chksum += (uint8_t)*s; // update checksum
662 ++used;
663 }
664 QS_INSERT_BYTE_(0U) // zero-terminate the string
665
666 QS_priv_.head = head; // save the head
667 QS_priv_.chksum = chksum; // save the checksum
668 QS_priv_.used = used; // save # of used buffer space
669}
670
671//............................................................................
672void QS_mem_fmt_(
673 uint8_t const * const blk,
674 uint8_t const size)
675{
676 uint8_t chksum = QS_priv_.chksum;
677 uint8_t * const buf = QS_priv_.buf; // put in a temporary (register)
678 QSCtr head = QS_priv_.head; // put in a temporary (register)
679 QSCtr const end = QS_priv_.end; // put in a temporary (register)
680 uint8_t const *pb = blk;
681
682 QS_priv_.used += ((QSCtr)size + 2U); // size+2 bytes to be added
683
684 QS_INSERT_BYTE_((uint8_t)QS_MEM_T)
685 chksum += (uint8_t)QS_MEM_T;
686
687 QS_INSERT_ESC_BYTE_(size)
688 // output the 'size' # bytes
689 for (uint8_t len = size; len > 0U; --len) {
690 QS_INSERT_ESC_BYTE_(*pb)
691 ++pb;
692 }
693
694 QS_priv_.head = head; // save the head
695 QS_priv_.chksum = chksum; // save the checksum
696}
697
698//............................................................................
699void QS_sig_dict_pre_(
700 QSignal const sig,
701 void const * const obj,
702 char const * const name)
703{
706 QS_MEM_SYS();
707
708 QS_beginRec_((uint_fast8_t)QS_SIG_DICT);
709 QS_SIG_PRE_(sig);
710 QS_OBJ_PRE_(obj);
711 QS_STR_PRE_((*name == '&') ? &name[1] : name);
712 QS_endRec_();
713
714 QS_MEM_APP();
715 QS_CRIT_EXIT();
716 QS_onFlush();
717}
718
719//............................................................................
720void QS_obj_dict_pre_(
721 void const * const obj,
722 char const * const name)
723{
726 QS_MEM_SYS();
727
728 QS_beginRec_((uint_fast8_t)QS_OBJ_DICT);
729 QS_OBJ_PRE_(obj);
730 QS_STR_PRE_((*name == '&') ? &name[1] : name);
731 QS_endRec_();
732
733 QS_MEM_APP();
734 QS_CRIT_EXIT();
735 QS_onFlush();
736}
737
738//............................................................................
739void QS_obj_arr_dict_pre_(
740 void const * const obj,
741 uint_fast16_t const idx,
742 char const * const name)
743{
746 Q_REQUIRE_INCRIT(400, idx < 1000U);
747 QS_CRIT_EXIT();
748
749 // format idx into a char buffer as "xxx\0"
750 uint8_t idx_str[4];
751 uint_fast16_t tmp = idx;
752 uint8_t i;
753 idx_str[3] = 0U; // zero-terminate
754 idx_str[2] = (uint8_t)((uint8_t)'0' + (tmp % 10U));
755 tmp /= 10U;
756 idx_str[1] = (uint8_t)((uint8_t)'0' + (tmp % 10U));
757 if (idx_str[1] == (uint8_t)'0') {
758 i = 2U;
759 }
760 else {
761 tmp /= 10U;
762 idx_str[0] = (uint8_t)((uint8_t)'0' + (tmp % 10U));
763 if (idx_str[0] == (uint8_t)'0') {
764 i = 1U;
765 }
766 else {
767 i = 0U;
768 }
769 }
770
771 uint8_t j = ((*name == '&') ? 1U : 0U);
772
774 QS_MEM_SYS();
775
776 QS_beginRec_((uint_fast8_t)QS_OBJ_DICT);
777 QS_OBJ_PRE_(obj);
778 for (; name[j] != '\0'; ++j) {
779 QS_U8_PRE_(name[j]);
780 if (name[j] == '[') {
781 ++j;
782 break;
783 }
784 }
785 for (; idx_str[i] != 0U; ++i) {
786 QS_U8_PRE_(idx_str[i]);
787 }
788 // skip chars until ']'
789 for (; name[j] != '\0'; ++j) {
790 if (name[j] == ']') {
791 break;
792 }
793 }
794 for (; name[j] != '\0'; ++j) {
795 QS_U8_PRE_(name[j]);
796 }
797 QS_U8_PRE_(0U); // zero-terminate
798 QS_endRec_();
799
800 QS_MEM_APP();
801 QS_CRIT_EXIT();
802 QS_onFlush();
803}
804
805//............................................................................
806void QS_fun_dict_pre_(
807 QSpyFunPtr const fun,
808 char const * const name)
809{
812 QS_MEM_SYS();
813
814 QS_beginRec_((uint_fast8_t)QS_FUN_DICT);
815 QS_FUN_PRE_(fun);
816 QS_STR_PRE_((*name == '&') ? &name[1] : name);
817 QS_endRec_();
818
819 QS_MEM_APP();
820 QS_CRIT_EXIT();
821 QS_onFlush();
822}
823
824//............................................................................
825void QS_usr_dict_pre_(
826 enum_t const rec,
827 char const * const name)
828{
831 QS_MEM_SYS();
832
833 QS_beginRec_((uint_fast8_t)QS_USR_DICT);
834 QS_U8_PRE_(rec);
835 QS_STR_PRE_(name);
836 QS_endRec_();
837
838 QS_MEM_APP();
839 QS_CRIT_EXIT();
840 QS_onFlush();
841}
842
843//............................................................................
844void QS_enum_dict_pre_(
845 enum_t const value,
846 uint8_t const group,
847 char const * const name)
848{
851 QS_MEM_SYS();
852
853 QS_beginRec_((uint_fast8_t)QS_ENUM_DICT);
854 QS_2U8_PRE_(value, group);
855 QS_STR_PRE_(name);
856 QS_endRec_();
857
858 QS_MEM_APP();
859 QS_CRIT_EXIT();
860 QS_onFlush();
861}
862
863//............................................................................
864void QS_assertion_pre_(
865 char const * const module,
866 int_t const id,
867 uint32_t const delay)
868{
869 // NOTE: called in a critical section
870
871 QS_beginRec_((uint_fast8_t)QS_ASSERT_FAIL);
872 QS_TIME_PRE_();
873 QS_U16_PRE_(id);
874 QS_STR_PRE_((module != (char *)0) ? module : "?");
875 QS_endRec_();
876 QS_onFlush();
877
878 // busy-wait until all QS data makes it over to the host
879 for (uint32_t volatile delay_ctr = delay;
880 delay_ctr > 0U; --delay_ctr)
881 {}
882 QS_onCleanup();
883}
884
885//............................................................................
886void QS_target_info_pre_(uint8_t const isReset) {
887 // NOTE: called in a critical section
888
889 static uint8_t const ZERO = (uint8_t)'0';
890 static uint8_t const * const TIME = (uint8_t const *)&Q_BUILD_TIME[0];
891 static uint8_t const * const DATE = (uint8_t const *)&Q_BUILD_DATE[0];
892 static union {
893 uint16_t u16;
894 uint8_t u8[2];
895 } endian_test;
896
897 endian_test.u16 = 0x0102U;
898 QS_beginRec_((uint_fast8_t)QS_TARGET_INFO);
899 QS_U8_PRE_(isReset);
900 QS_U16_PRE_(((endian_test.u8[0] == 0x01U) // big endian?
901 ? (0x8000U | QP_VERSION)
902 : QP_VERSION)); // target endianness + version number
903
904 // send the object sizes...
905 QS_U8_PRE_(Q_SIGNAL_SIZE | (QF_EVENT_SIZ_SIZE << 4U));
906
907#ifdef QF_EQUEUE_CTR_SIZE
908 QS_U8_PRE_(QF_EQUEUE_CTR_SIZE | (QF_TIMEEVT_CTR_SIZE << 4U));
909#else
910 QS_U8_PRE_(QF_TIMEEVT_CTR_SIZE << 4U);
911#endif // QF_EQUEUE_CTR_SIZE
912
913#ifdef QF_MPOOL_CTR_SIZE
914 QS_U8_PRE_(QF_MPOOL_SIZ_SIZE | (QF_MPOOL_CTR_SIZE << 4U));
915#else
916 QS_U8_PRE_(0U);
917#endif // QF_MPOOL_CTR_SIZE
918
919 QS_U8_PRE_(QS_OBJ_PTR_SIZE | (QS_FUN_PTR_SIZE << 4U));
920 QS_U8_PRE_(QS_TIME_SIZE);
921
922 // send the limits...
923 QS_U8_PRE_(QF_MAX_ACTIVE);
924 QS_U8_PRE_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE << 4U));
925
926 // send the build time in three bytes (sec, min, hour)...
927 QS_U8_PRE_((10U * (uint8_t)(TIME[6] - ZERO))
928 + (uint8_t)(TIME[7] - ZERO));
929 QS_U8_PRE_((10U * (uint8_t)(TIME[3] - ZERO))
930 + (uint8_t)(TIME[4] - ZERO));
931 if (Q_BUILD_TIME[0] == ' ') {
932 QS_U8_PRE_(TIME[1] - ZERO);
933 }
934 else {
935 QS_U8_PRE_((10U * (uint8_t)(TIME[0] - ZERO))
936 + (uint8_t)(TIME[1] - ZERO));
937 }
938
939 // send the build date in three bytes (day, month, year) ...
940 if (Q_BUILD_DATE[4] == ' ') {
941 QS_U8_PRE_(DATE[5] - ZERO);
942 }
943 else {
944 QS_U8_PRE_((10U * (uint8_t)(DATE[4] - ZERO))
945 + (uint8_t)(DATE[5] - ZERO));
946 }
947 // convert the 3-letter month to a number 1-12 ...
948 uint8_t b;
949 switch ((int_t)DATE[0] + (int_t)DATE[1] + (int_t)DATE[2]) {
950 case (int_t)'J' + (int_t)'a' + (int_t)'n':
951 b = 1U;
952 break;
953 case (int_t)'F' + (int_t)'e' + (int_t)'b':
954 b = 2U;
955 break;
956 case (int_t)'M' + (int_t)'a' + (int_t)'r':
957 b = 3U;
958 break;
959 case (int_t)'A' + (int_t)'p' + (int_t)'r':
960 b = 4U;
961 break;
962 case (int_t)'M' + (int_t)'a' + (int_t)'y':
963 b = 5U;
964 break;
965 case (int_t)'J' + (int_t)'u' + (int_t)'n':
966 b = 6U;
967 break;
968 case (int_t)'J' + (int_t)'u' + (int_t)'l':
969 b = 7U;
970 break;
971 case (int_t)'A' + (int_t)'u' + (int_t)'g':
972 b = 8U;
973 break;
974 case (int_t)'S' + (int_t)'e' + (int_t)'p':
975 b = 9U;
976 break;
977 case (int_t)'O' + (int_t)'c' + (int_t)'t':
978 b = 10U;
979 break;
980 case (int_t)'N' + (int_t)'o' + (int_t)'v':
981 b = 11U;
982 break;
983 case (int_t)'D' + (int_t)'e' + (int_t)'c':
984 b = 12U;
985 break;
986 default:
987 b = 0U;
988 break;
989 }
990 QS_U8_PRE_(b); // store the month
991 QS_U8_PRE_((10U * (uint8_t)(DATE[9] - ZERO))
992 + (uint8_t)(DATE[10] - ZERO));
993 QS_endRec_();
994}
995
996//! @endcond
int int_t
Definition qp.h:106
#define QP_VERSION
Definition qp.h:47
uint16_t QSignal
Definition qp.h:131
int enum_t
Definition qp.h:109
#define Q_DIM(array_)
Definition qp.h:535
#define QF_EVENT_SIZ_SIZE
Definition qp_config.h:148
#define QS_TIME_SIZE
Definition qp_config.h:200
#define QF_MAX_TICK_RATE
Definition qp_config.h:130
#define QF_EQUEUE_CTR_SIZE
Definition qp_config.h:164
#define QS_FUN_PTR_SIZE
Definition qp_config.h:216
#define QF_MAX_ACTIVE
Definition qp_config.h:112
#define QF_TIMEEVT_CTR_SIZE
Definition qp_config.h:156
#define QS_OBJ_PTR_SIZE
Definition qp_config.h:208
#define QF_MPOOL_SIZ_SIZE
Definition qp_config.h:180
#define QF_MPOOL_CTR_SIZE
Definition qp_config.h:172
#define QF_MAX_EPOOL
Definition qp_config.h:121
#define Q_SIGNAL_SIZE
Definition qp_config.h:101
@ QS_ASSERT_FAIL
assertion failed in the code
Definition qs.h:178
@ QS_U2_RECORDS
User Group 110-114 records.
Definition qs.h:215
#define QS_CRIT_STAT
Definition qs.h:568
@ QS_ENUM_DICT
enumeration dictionary entry
Definition qs.h:159
@ QS_FUN_DICT
function dictionary entry
Definition qs.h:171
#define QS_TIME_PRE_()
Definition qs.h:450
@ QS_MP_RECORDS
Memory Pools QS records.
Definition qs.h:207
@ QS_STR_T
zero-terminated ASCII string format
Definition qs.h:664
@ QS_MEM_T
up to 255-bytes memory block format
Definition qs.h:665
@ QS_TE_RECORDS
Time Events QS records.
Definition qs.h:208
@ QS_EP_IDS
event-pool IDs
Definition qs.h:249
@ QS_USER
the first record available to QS users
Definition qs.h:225
@ QS_PRE_MAX
the # predefined signals
Definition qs.h:196
@ QS_AO_IDS
AO IDs (priorities)
Definition qs.h:248
@ QS_SM_RECORDS
State Machine QS records.
Definition qs.h:204
@ QS_OBJ_DICT
object dictionary entry
Definition qs.h:170
@ QS_U0_RECORDS
User Group 100-104 records.
Definition qs.h:213
#define QS_MEM_APP()
Definition qs.h:588
@ QS_TARGET_INFO
reports the Target information
Definition qs.h:173
@ QS_U3_RECORDS
User Group 115-119 records.
Definition qs.h:216
@ QS_MTX_RECORDS
Mutex QS records.
Definition qs.h:212
@ QS_U4_RECORDS
User Group 120-124 records.
Definition qs.h:217
@ QS_AO_RECORDS
Active Object QS records.
Definition qs.h:205
@ QS_SEM_RECORDS
Semaphore QS records.
Definition qs.h:211
@ QS_QF_RECORDS
QF QS records.
Definition qs.h:209
@ QS_SC_RECORDS
Scheduler QS records.
Definition qs.h:210
@ QS_EMPTY
QS record for cleanly starting a session.
Definition qs.h:79
@ QS_ALL_IDS
all QS IDs
Definition qs.h:247
@ QS_SIG_DICT
signal dictionary entry
Definition qs.h:169
@ QS_U1_RECORDS
User Group 105-109 records.
Definition qs.h:214
@ QS_EQ_RECORDS
Event Queues QS records.
Definition qs.h:206
@ QS_USR_DICT
user QS record dictionary entry
Definition qs.h:172
#define QS_CRIT_EXIT()
Definition qs.h:578
#define QS_MEM_SYS()
Definition qs.h:583
@ QS_ALL_RECORDS
all maskable QS records
Definition qs.h:203
#define QS_EOD
Definition qs.h:558
#define QS_CRIT_ENTRY()
Definition qs.h:573
@ QS_UA_RECORDS
All User records.
Definition qs.h:218
@ QS_AP_IDS
Application-specific IDs.
Definition qs.h:251
QS/C package-scope interface.
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define Q_ASSERT_STATIC(expr_)
Definition qsafe.h:154
#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)
char const Q_BUILD_TIME[9]
the time of the last translation of the form: "hh:mm:ss"
Definition qstamp.c:49
char const Q_BUILD_DATE[12]
the calendar date of the last translation of the form: "Mmm dd yyyy"
Definition qstamp.c:46
QS type for output filters (global and local)
Definition qs.h:316
uint8_t glb[16]
Definition qs.h:318
uint8_t loc[16]
Definition qs.h:319