1 /*
2  * Trace Recorder for Tracealyzer v4.6.6
3  * Copyright 2021 Percepio AB
4  * www.percepio.com
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #ifndef TRC_RECORDER_H
10 #define TRC_RECORDER_H
11 
12 /**
13  * @file
14  *
15  * @brief The public API of the Percepio trace recorder.
16  */
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 /**
23  * @brief Trace Recorder APIs
24  * @defgroup trace_recorder_apis Trace Recorder APIs
25  * @{
26  * @}
27  */
28 
29 #define TRC_ACKNOWLEDGED (0xABC99123)
30 
31 #include <trcDefines.h>
32 #include <trcConfig.h>
33 #include <trcKernelPortConfig.h>
34 #include <trcTypes.h>
35 
36 #ifndef TRC_CFG_TEST_MODE
37 #define TRC_CFG_TEST_MODE 0
38 #endif
39 
40 /* Unless defined by the kernel port, we assume there is no support for
41  * the classic snapshot mode and default to streaming mode where
42  * the new RingBuffer snapshot mode provides snapshot functionality.
43  */
44 #ifndef TRC_CFG_RECORDER_MODE
45 #define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_STREAMING
46 #endif
47 
48 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
49 #include <trcSnapshotConfig.h>
50 #include <trcKernelPortSnapshotConfig.h>
51 
52 /* Calls xTraceError if the _assert condition is false. For void functions,
53 where no return value is to be provided. */
54 #define TRC_ASSERT_VOID(_assert, _err) if (! (_assert)){ prvTraceError(_err); return; }
55 
56 /* Calls xTraceError if the _assert condition is false. For non-void functions,
57 where a return value is to be provided. */
58 #define TRC_ASSERT_RET(_assert, _err, _return) if (! (_assert)){ prvTraceError(_err); return _return; }
59 
60 typedef uint8_t traceUBChannel;
61 typedef uint8_t traceObjectClass;
62 
63 #undef traceHandle
64 #if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1)
65 typedef uint16_t traceHandle;
66 #else /* (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) */
67 typedef uint8_t traceHandle;
68 #endif /* (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) */
69 
70 #undef TraceISRHandle_t
71 #define TraceISRHandle_t traceHandle
72 
73 #include <trcHardwarePort.h>
74 #include <trcKernelPort.h>
75 
76 /* Not yet available in snapshot mode */
77 #define vTraceConsoleChannelPrintF(fmt, ...) (void)
78 #define xTraceConsoleChannelPrintF(fmt, ...) (void)
79 #define prvTraceStoreEvent_None(...)
80 #define prvTraceStoreEvent_Handle(...)
81 #define prvTraceStoreEvent_Param(...)
82 #define prvTraceStoreEvent_HandleParam(...)
83 #define prvTraceStoreEvent_ParamParam(...)
84 #define prvTraceStoreEvent_HandleParamParam(...)
85 #define prvTraceStoreEvent_ParamParamParam(...)
86 
87 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) */
88 
89 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
90 #include <trcStreamingConfig.h>
91 #include <trcKernelPortStreamingConfig.h>
92 
93 /* Unless specified in trcConfig.h we assume this is a single core target */
94 #ifndef TRC_CFG_CORE_COUNT
95 #define TRC_CFG_CORE_COUNT 1
96 #endif
97 
98 /* Unless specified in trcConfig.h we assume this is a single core target */
99 #ifndef TRC_CFG_GET_CURRENT_CORE
100 #define TRC_CFG_GET_CURRENT_CORE() 0
101 #endif
102 
103 /* Unless specified in trcConfig.h or trcKernelPortConfig.h we assume
104  * GCC statement expressions aren't supported. */
105 #ifndef TRC_CFG_USE_GCC_STATEMENT_EXPR
106 #define TRC_CFG_USE_GCC_STATEMENT_EXPR 0
107 #endif
108 
109 /* Backwards compatibility */
110 #undef traceHandle
111 #define traceHandle TraceISRHandle_t
112 
113 /* Maximum event size */
114 #define TRC_MAX_BLOB_SIZE (16 * sizeof(uint32_t))
115 
116 /* Platform name length */
117 #define TRC_PLATFORM_CFG_LENGTH 8
118 
119 /* Header size */
120 #define TRC_HEADER_BUFFER_SIZE (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + (sizeof(char) * (TRC_PLATFORM_CFG_LENGTH)) + sizeof(uint16_t) + sizeof(uint8_t) + sizeof(uint8_t))
121 
122 typedef struct TraceHeaderBuffer
123 {
124 	uint8_t buffer[TRC_HEADER_BUFFER_SIZE];
125 } TraceHeaderBuffer_t;
126 
127 #include <trcHardwarePort.h>
128 #include <trcKernelPort.h>
129 #include <trcString.h>
130 #include <trcStaticBuffer.h>
131 #include <trcError.h>
132 #include <trcEvent.h>
133 #include <trcEventBuffer.h>
134 #include <trcMultiCoreEventBuffer.h>
135 #include <trcTimestamp.h>
136 #include <trcEntryTable.h>
137 #include <trcStreamPort.h>
138 #include <trcISR.h>
139 #include <trcTask.h>
140 #include <trcObject.h>
141 #include <trcPrint.h>
142 #include <trcHeap.h>
143 #include <trcExtension.h>
144 #include <trcUtility.h>
145 #include <trcStackMonitor.h>
146 #include <trcInternalEventBuffer.h>
147 #include <trcDiagnostics.h>
148 #include <trcAssert.h>
149 
150 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
151 
152 /* These includes offer functionality for Streaming mode only, but they are included here in order to avoid compilation errors */
153 #include <trcInterval.h>
154 #include <trcStateMachine.h>
155 #include <trcCounter.h>
156 
157 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
158 
159 /******************************************************************************/
160 /*** Common API - both Snapshot and Streaming mode ****************************/
161 /******************************************************************************/
162 
163 /**
164  * @brief
165  *
166  * Initializes the recorder data. xTraceInitialize() or xTraceEnable(...)
167  * must be called before any attempts at adding trace data/information.
168  * See xTraceEnable(...) for more information.
169  *
170  * @retval TRC_FAIL Failure
171  * @retval TRC_SUCCESS Success
172  */
173 traceResult xTraceInitialize(void);
174 
175 /**
176  * @brief
177  *
178  * This function enables tracing.
179  * To use the trace recorder, the startup must call xTraceInitialize() or
180  * xTraceEnable(...) before any RTOS calls are made (including "create" calls).
181  * Three start options are provided:
182  *
183  * 	TRC_START: Starts the tracing directly. In snapshot mode this allows for
184  * 	starting the trace at any point in your code, assuming xTraceInitialize()
185  * 	has been called in the startup. Can also be used for streaming without
186  * 	Tracealyzer control, e.g. to a local flash file system (assuming such a
187  * 	"stream port", see trcStreamPort.h).
188  *
189  * 	TRC_START_AWAIT_HOST: For streaming mode only. Initializes the trace recorder
190  * 	if necessary and waits for a Start command from Tracealyzer ("Start Recording"
191  * 	button). This call is intentionally blocking! By calling xTraceEnable with
192  * 	this option from the startup code, you start tracing at this point and capture
193  * 	the early events.
194  *
195  * 	TRC_START_FROM_HOST: For streaming mode only. Initializes the trace recorder
196  * 	if necessary and creates a task that waits for a Start command from
197  * 	Tracealyzer ("Start Recording" button). This call is not blocking.
198  *
199  * @example Usage examples
200  *
201  * 	Snapshot trace, from startup:
202  * 		<board init>
203  * 		xTraceEnable(TRC_START); // Will call xTraceInitialize()
204  * 		<RTOS init>
205  *
206  * 	Snapshot trace, from a later point:
207  * 		<board init>
208  * 		xTraceInitialize();
209  * 		<RTOS init>
210  * 		...
211  * 		xTraceEnable(TRC_START); // e.g., in task context, at some relevant event
212  *
213  * 	Streaming trace, from startup (can only be used with certain stream ports):
214  *		<board startup>
215  *		xTraceInitialize();
216  *		<RTOS startup>
217  * 		xTraceEnable(TRC_START);
218  *
219  * 	Streaming trace, from startup:
220  *		<board init>
221  *		xTraceEnable(TRC_START_AWAIT_HOST); // Blocks!
222  *		<RTOS init>
223  *
224  * 	Streaming trace, from a later point:
225  *		<board startup>
226  *		xTraceInitialize();
227  *		<RTOS startup>
228  * 		xTraceEnable(TRC_START);
229  *
230  * 	Streaming trace, system executes normally until host starts tracing:
231  *		<board startup>
232  *		xTraceInitialize();
233  *		<RTOS startup>
234  *		xTraceEnable(TRC_START_FROM_HOST)
235  *
236  * @param[in] uiStartOption Start option.
237  *
238  * @retval TRC_FAIL Failure
239  * @retval TRC_SUCCESS Success
240  */
241 traceResult	xTraceEnable(uint32_t uiStartOption);
242 
243 /**
244  * @brief Disables tracing.
245  *
246  * @retval TRC_FAIL Failure
247  * @retval TRC_SUCCESS Success
248  */
249 traceResult xTraceDisable(void);
250 
251 /**
252  * @brief
253  *
254  * For snapshot mode only: Sets the "filter group" to assign when creating
255  * RTOS objects, such as tasks, queues, semaphores and mutexes. This together
256  * with vTraceSetFilterMask allows you to control what events that are recorded,
257  * based on the objects they refer to.
258  *
259  * There are 16 filter groups named FilterGroup0 .. FilterGroup15.
260  *
261  * Note: We don't recommend filtering out the Idle task, so make sure to call
262  * vTraceSetFilterGroup just before initializing the RTOS, in order to assign
263  * such "default" objects to the right Filter Group (typically group 0).
264  *
265  * Example:
266  *
267  *		// Assign tasks T1 to FilterGroup0 (default)
268  *		<Create Task T1>
269  *
270  *		// Assign Q1 and Q2 to FilterGroup1
271  *		vTraceSetFilterGroup(FilterGroup1);
272  *		<Create Queue Q1>
273  *		<Create Queue Q2>
274  *
275  *		// Assigns Q3 to FilterGroup2
276  *		vTraceSetFilterGroup(FilterGroup2);
277  *		<Create Queue Q3>
278  *
279  *		// Only include FilterGroup0 and FilterGroup2, exclude FilterGroup1 (Q1 and Q2) from the trace
280  *		vTraceSetFilterMask( FilterGroup0 | FilterGroup2 );
281  *
282  *		// Assign the default RTOS objects (e.g. Idle task) to FilterGroup0
283  *		vTraceSetFilterGroup(FilterGroup0);
284  *		<Start the RTOS scheduler>
285  *
286  * Note that you may define your own names for the filter groups using
287  * preprocessor definitions, to make the code easier to understand.
288  *
289  * Example:
290  *
291  *		#define BASE FilterGroup0
292  *		#define USB_EVENTS FilterGroup1
293  *		#define CAN_EVENTS FilterGroup2
294  *
295  * Note that filtering per event type (regardless of object) is also available
296  * in trcKernelPortConfig.h for certain kernels.
297  *
298  * @param[in] filterGroup Filter group
299  */
300 void vTraceSetFilterGroup(uint16_t filterGroup);
301 
302 /**
303  * @brief
304  *
305  * For snapshot mode only: Sets the "filter mask" that is used to filter
306  * the events by object. This can be used to reduce the trace data rate, i.e.,
307  * if your streaming interface is a bottleneck or if you want longer snapshot
308  * traces without increasing the buffer size.
309  *
310  * Note: There are two kinds of filters in the recorder. The other filter type
311  * excludes all events of certain kinds (e.g., OS ticks). See trcConfig.h.
312  *
313  * The filtering is based on bitwise AND with the Filter Group ID, assigned
314  * to RTOS objects such as tasks, queues, semaphores and mutexes.
315  * This together with vTraceSetFilterGroup allows you to control what
316  * events that are recorded, based on the objects they refer to.
317  *
318  * See example for vTraceSetFilterGroup.
319  *
320  * @param[in] filterMask Filter mask
321  */
322 void vTraceSetFilterMask(uint16_t filterMask);
323 
324 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
325 
326 #include <stdarg.h>
327 
328 /**
329  * @brief Returns lower 16 bits of a value
330  *
331  * @param[in] value The starting value
332  */
333 #define TRACE_GET_LOW16(value) ((uint16_t)((value) & 0x0000FFFF))
334 
335 /**
336  * @brief Returns upper 16 bits
337  *
338  * @param[in] value The starting value
339  */
340 #define TRACE_GET_HIGH16(value) ((uint16_t)(((value) >> 16) & 0x0000FFFF))
341 
342 /**
343  * @brief Sets lower 16 bits
344  *
345  * @param[in] current The starting value
346  * @param[in] value The value to set
347  */
348 #define TRACE_SET_LOW16(current, value)  (((current) & 0xFFFF0000) | (value))
349 
350 /**
351  * @brief Sets upper 16 bits
352  *
353  * @param[in] current The starting value
354  * @param[in] value The value to set
355  */
356 #define TRACE_SET_HIGH16(current, value) (((current) & 0x0000FFFF) | (((uint32_t)(value)) << 16))
357 
358 #if defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)
359 /**
360  * @brief Adds a task to the stack monitor
361  *
362  * @param[in] task The task
363  */
364 void prvAddTaskToStackMonitor(void* task);
365 
366 /**
367  * @brief Remove a task from the stack monitor
368  *
369  * @param[in] task The task
370  */
371 void prvRemoveTaskFromStackMonitor(void* task);
372 
373 /**
374  * @brief Reports on the current stack usage
375  */
376 void prvReportStackUsage(void);
377 
378 #else /* defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */
379 
380 #define prvAddTaskToStackMonitor(task)
381 #define prvRemoveTaskFromStackMonitor(task)
382 #define prvReportStackUsage()
383 
384 #endif /* defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */
385 
386 /**
387  * @internal Deprecated - Registers an ISR
388  */
389 traceHandle xTraceSetISRProperties(const char* szName, uint8_t uiPriority);
390 
391 /**
392  * @brief
393  *
394  * Registers an ISR.
395  *
396  * Example:
397  *	 #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt
398  *	 ...
399  *	 TraceISRHandle_t Timer1Handle;
400  *	 xTraceISRRegister("ISRTimer1", PRIO_ISR_TIMER1, &Timer1Handle);
401  *
402  * @param[in] szName ISR name
403  * @param[in] uiPriority ISR priority
404  * @param[in] pxISRHandle
405  *
406  * @retval TRC_FAIL Failure
407  * @retval TRC_SUCCESS Success
408  */
409 traceResult xTraceISRRegister(const char* szName, uint32_t uiPriority, TraceISRHandle_t* pxISRHandle);
410 
411 /**
412  * @brief
413  *
414  * Registers the beginning of an Interrupt Service Routine, using a TraceISRHandle_t
415  * provided by xTraceISRRegister.
416  *
417  * Example:
418  *	 #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt
419  *	 ...
420  *	 TraceISRHandle_t Timer1Handle;
421  *	 xTraceISRRegister("ISRTimer1", PRIO_ISR_TIMER1, &Timer1Handle);
422  *	 ...
423  *	 void ISR_handler()
424  *	 {
425  *		 xTraceISRBegin(Timer1Handle);
426  *		 ...
427  *		 xTraceISREnd(0);
428  *	 }
429  *
430  * @param[in] xHandle Handle for the previously registered ISR
431  *
432  * @retval TRC_FAIL Failure
433  * @retval TRC_SUCCESS Success
434  */
435 traceResult xTraceISRBegin(TraceISRHandle_t xHandle);
436 
437 #define vTraceStoreISRBegin(__handle) (void)xTraceISRBegin((TraceISRHandle_t)(__handle))
438 
439 /**
440  * @brief
441  *
442  * Registers the end of an Interrupt Service Routine.
443  *
444  * The parameter pendingISR indicates if the interrupt has requested a
445  * task-switch (= 1), e.g., by signaling a semaphore. Otherwise (= 0) the
446  * interrupt is assumed to return to the previous context.
447  *
448  * Example:
449  *	 #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt
450  *	 ...
451  *	 TraceISRHandle_t Timer1Handle;
452  *	 xTraceISRRegister("ISRTimer1", PRIO_ISR_TIMER1, &Timer1Handle);
453  *	 ...
454  *	 void ISR_handler()
455  *	 {
456  *		 xTraceISRBegin(Timer1Handle);
457  *		 ...
458  *		 xTraceISREnd(0);
459  *	 }
460  *
461  * @param[in] pendingISR Flag that indicates whether an ISR is pending
462  *
463  * @retval TRC_FAIL Failure
464  * @retval TRC_SUCCESS Success
465  */
466 traceResult xTraceISREnd(int pendingISR);
467 
468 #define vTraceStoreISREnd(__pendingISR) (void)xTraceISREnd(__pendingISR)
469 
470 /**
471  * @brief Query if recorder is enabled
472  *
473  * @retval 1 if recorder is enabled
474  * @retval 0 if recorder is disabled
475  */
476 uint32_t xTraceIsRecorderEnabled(void);
477 
478 /**
479  * @brief
480  *
481  * @retval 1 if recorder is initialized
482  * @retval 0 if recorder isn't initialized
483  */
484 uint32_t xTraceIsRecorderInitialized(void);
485 
486 /**
487  * @brief
488  *
489  * Creates an event that ends the current task instance at this very instant.
490  * This makes the viewer to splits the current fragment at this point and begin
491  * a new actor instance, even if no task-switch has occurred.
492  *
493  * @retval TRC_FAIL Failure
494  * @retval TRC_SUCCESS Success
495  */
496 traceResult xTraceTaskInstanceFinishedNow(void);
497 
498 /**
499  * @brief
500  *
501  * Marks the current "task instance" as finished on the next kernel call.
502  *
503  * If that kernel call is blocking, the instance ends after the blocking event
504  * and the corresponding return event is then the start of the next instance.
505  * If the kernel call is not blocking, the viewer instead splits the current
506  * fragment right before the kernel call, which makes this call the first event
507  * of the next instance.
508  *
509  * @retval TRC_FAIL Failure
510  * @retval TRC_SUCCESS Success
511  */
512 traceResult xTraceTaskInstanceFinishedNext(void);
513 
514 /**
515  * @brief Registers a string and returns a handle that can be used when tracing
516  *
517  * @param[in] label Label
518  * @param[out] pxString String handle
519  *
520  * @retval TRC_FAIL Failure
521  * @retval TRC_SUCCESS Success
522  */
523 traceResult xTraceStringRegister(const char* label, TraceStringHandle_t* pxString);
524 
525 /**
526  * @brief Registers a string and returns a handle that can be used when tracing
527  *
528  * @deprecated Backwards compatibility
529  *
530  * @param[in] name Name.
531  *
532  * @return TraceStringHandle_t String handle
533  */
534 TraceStringHandle_t xTraceRegisterString(const char* name);
535 
536 #if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
537 /**
538  * @brief
539  *
540  * Generates "User Events", with formatted text and data, similar to a "printf".
541  * User Events can be used for very efficient logging from your application code.
542  * It is very fast since the actual string formatting is done on the host side,
543  * when the trace is displayed. The execution time is just some microseconds on
544  * a 32-bit MCU.
545  *
546  * User Events are shown as yellow labels in the main trace view of $PNAME.
547  *
548  * An advantage of User Events is that data can be plotted in the "User Event
549  * Signal Plot" view, visualizing any data you log as User Events, discrete
550  * states or control system signals (e.g. system inputs or outputs).
551  *
552  * You may group User Events into User Event Channels. The yellow User Event
553  * labels show the logged string, preceded by the channel name within brackets.
554  *
555  * Example:
556  *
557  *  "[MyChannel] Hello World!"
558  *
559  * The User Event Channels are shown in the View Filter, which makes it easy to
560  * select what User Events you wish to display. User Event Channels are created
561  * using xTraceStringRegister().
562  *
563  * Example:
564  *
565  *	 TraceStringHandle_t adc_uechannel;
566  *	 xTraceStringRegister("ADC User Events", &adc_uechannel);
567  *	 ...
568  *	 xTracePrintF(adc_uechannel,
569  *				 "ADC channel %d: %d volts",
570  *				 ch, adc_reading);
571  *
572  * The following format specifiers are supported in both modes:
573  * %d - signed integer.
574  * %u - unsigned integer.
575  * %X - hexadecimal, uppercase.
576  * %x - hexadecimal, lowercase.
577  * %s - string (see comment below)
578  *
579  * For integer formats (%d, %u, %x, %X) you may also use width and padding.
580  * If using -42 as data argument, two examples are:
581  *    "%05d" -> "-0042"
582  *     "%5d" -> "  -42".
583  *
584  * String arguments are supported in both snapshot and streaming, but in streaming
585  * mode you need to use xTraceStringRegister and use the returned TraceStringHandle_t as
586  * the argument. In snapshot you simply provide a char* as argument.
587  *
588  * Snapshot: xTracePrintF(myChn, "my string: %s", str);
589  * Streaming: xTracePrintF(myChn, "my string: %s", strTraceString);
590  *
591  * In snapshot mode you can specify 8-bit or 16-bit arguments to reduce RAM usage:
592  *     %hd -> 16 bit (h) signed integer (d).
593  *     %bu -> 8 bit (b) unsigned integer (u).
594  *
595  * However, in streaming mode all data arguments are assumed to be 32 bit wide.
596  * Width specifiers (e.g. %hd) are accepted but ignored (%hd treated like %d).
597  *
598  * The maximum event size also differs between the modes. In streaming this is
599  * limited by a maximum payload size of 52 bytes, including format string and
600  * data arguments. So if using one data argument, the format string is limited
601  * to 48 byte, etc. If this is exceeded,  the format string is truncated and you
602  * get a warning in Tracealyzer.
603  *
604  * In snapshot mode you are limited to maximum 15 arguments, that must not exceed
605  * 32 bytes in total (not counting the format string). If exceeded, the recorder
606  * logs an internal error (displayed when opening the trace) and stops recording.
607  *
608  * @param[in] chn Channel.
609  * @param[in] fmt Formatting.
610  * @param[in] ...
611  *
612  * @retval TRC_FAIL Failure
613  * @retval TRC_SUCCESS Success
614  */
615 traceResult xTracePrintF(TraceStringHandle_t chn, const char* fmt, ...);
616 #else
617 #define xTracePrintF(chn, fmt, ...) ((void)(chn), (void)(fmt), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */
618 #endif
619 
620 #if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
621 /**
622  * @brief
623  *
624  * xTracePrintF variant that accepts a va_list.
625  * See xTracePrintF documentation for further details.
626  *
627  * @param[in] eventLabel
628  * @param[in] formatStr
629  * @param[in] vl
630  *
631  * @retval TRC_FAIL Failure
632  * @retval TRC_SUCCESS Success
633  */
634 traceResult xTraceVPrintF(TraceStringHandle_t eventLabel, const char* formatStr, va_list vl);
635 #else
636 #define xTraceVPrintF(chn, formatStr, vl) ((void)(chn), (void)(formatStr), (void)(vl), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */
637 #endif
638 
639 #if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
640 /**
641  * @brief A faster version of xTracePrintF, that only allows for logging a string.
642  *
643  * Example:
644  *
645  *	 TraceStringHandle_t chn;
646  *	 xTraceStringRegister("MyChannel", &chn);
647  *	 ...
648  *	 xTracePrint(chn, "Hello World!");
649  *
650  * @param[in] chn Channel.
651  * @param[in] str String.
652  *
653  * @retval TRC_FAIL Failure
654  * @retval TRC_SUCCESS Success
655  */
656 traceResult xTracePrint(TraceStringHandle_t chn, const char* str);
657 #else
658 #define xTracePrint(chn, str) ((void)(chn), (void)(str), TRC_SUCCESS)
659 #endif
660 
661 /******************************************************************************/
662 /*** Extended API for Snapshot mode *******************************************/
663 /******************************************************************************/
664 
665 /**
666  * @brief Trace stop callback type.
667  */
668 typedef void(*TRACE_STOP_HOOK)(void);
669 
670 /**
671  * @brief Sets a function to be called when the recorder is stopped.
672  *
673  * @note Snapshot mode only!
674  *
675  * @param[in] stopHookFunction
676  */
677 void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction);
678 
679 /**
680  * @brief
681  *
682  * Resets the recorder.
683  *
684  * Only necessary if a restart is desired - this is not
685  * needed in the startup initialization.
686  *
687  * @note Snapshot mode only!
688  */
689 void vTraceClear(void);
690 
691 /*****************************************************************************/
692 /*** INTERNAL SNAPSHOT FUNCTIONS *********************************************/
693 /*****************************************************************************/
694 
695 #define TRC_UNUSED
696 
697 #ifndef TRC_CFG_INCLUDE_OBJECT_DELETE
698 #define TRC_CFG_INCLUDE_OBJECT_DELETE 0
699 #endif
700 
701 #ifndef TRC_CFG_INCLUDE_READY_EVENTS
702 #define TRC_CFG_INCLUDE_READY_EVENTS 1
703 #endif
704 
705 #ifndef TRC_CFG_INCLUDE_OSTICK_EVENTS
706 #define TRC_CFG_INCLUDE_OSTICK_EVENTS 0
707 #endif
708 
709 /* This macro will create a task in the object table */
710 #undef trcKERNEL_HOOKS_TASK_CREATE
711 #define trcKERNEL_HOOKS_TASK_CREATE(SERVICE, CLASS, pxTCB) \
712 	if ((pxTCB) != 0) \
713 	{ \
714 		TRACE_SET_OBJECT_NUMBER(TASK, pxTCB); \
715 		TRACE_SET_OBJECT_FILTER(TASK, pxTCB, CurrentFilterGroup); \
716 		prvTraceSetObjectName(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_NAME(pxTCB)); \
717 		prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \
718 		if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
719 			if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
720 				prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \
721 	} \
722 	else \
723 	{ \
724 		/* pxTCB is null */ \
725 		if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
726 		{ \
727 			prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, 0); \
728 		} \
729 	}
730 
731 /* This macro will remove the task and store it in the event buffer */
732 #undef trcKERNEL_HOOKS_TASK_DELETE
733 #define trcKERNEL_HOOKS_TASK_DELETE(SERVICE, SERVICE_NAME, SERVICE_PROP, pxTCB) \
734 	if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
735 		if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
736 			prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \
737 	prvTraceStoreObjectNameOnCloseEvent(SERVICE_NAME, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \
738 	prvTraceStoreObjectPropertiesOnCloseEvent(SERVICE_PROP, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \
739 	prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \
740 	prvTraceSetObjectState(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TASK_STATE_INSTANCE_NOT_ACTIVE); \
741 	prvTraceFreeObjectHandle(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
742 
743 
744 /* This macro will setup a task in the object table */
745 #undef trcKERNEL_HOOKS_OBJECT_CREATE
746 #define trcKERNEL_HOOKS_OBJECT_CREATE(SERVICE, CLASS, pxObject) \
747 	TRACE_SET_OBJECT_NUMBER(CLASS, pxObject); \
748 	TRACE_SET_OBJECT_FILTER(CLASS, pxObject, CurrentFilterGroup); \
749 	prvMarkObjectAsUsed(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject),  TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));\
750 	if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
751 		if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
752 			prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \
753 	prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), 0);
754 
755 /* This macro will setup a task in the object table */
756 #undef trcKERNEL_HOOKS_OBJECT_CREATE_FAILED
757 #define trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(SERVICE, TRACE_CLASS)\
758 	if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
759 	{ \
760 		prvTraceStoreKernelCall(SERVICE, TRACE_CLASS, 0); \
761 	}
762 
763 /* This macro will remove the object and store it in the event buffer */
764 #undef trcKERNEL_HOOKS_OBJECT_DELETE
765 #define trcKERNEL_HOOKS_OBJECT_DELETE(SERVICE, SERVICE_NAME, SERVICE_PROP, CLASS, pxObject) \
766 	if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
767 		if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
768 			prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \
769 	prvTraceStoreObjectNameOnCloseEvent(SERVICE_NAME, TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \
770 	prvTraceStoreObjectPropertiesOnCloseEvent(SERVICE_PROP, TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \
771 	prvTraceFreeObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
772 
773 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */
774 #undef trcKERNEL_HOOKS_KERNEL_SERVICE
775 #define trcKERNEL_HOOKS_KERNEL_SERVICE(SERVICE, CLASS, pxObject) \
776 	if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
777 		if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
778 			prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
779 
780 /* This macro will create a call to a kernel service with a certain result, with a null object as parameter */
781 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT
782 #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT(SERVICE, TRACECLASS) \
783 	if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
784 		prvTraceStoreKernelCall(SERVICE, TRACECLASS, 0);
785 
786 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */
787 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM
788 #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(SERVICE, CLASS, pxObject, param) \
789 	if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
790 		if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
791 			prvTraceStoreKernelCallWithParam(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint32_t)param);
792 
793 /* This macro will create a call to a kernel service with a certain result, with a null object and other value as parameter */
794 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM
795 #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM(SERVICE, TRACECLASS, param) \
796 	if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
797 		prvTraceStoreKernelCallWithParam(SERVICE, TRACECLASS, 0, param);
798 
799 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */
800 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY
801 #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(SERVICE, param) \
802 	if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
803 		prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, (uint32_t)param);
804 
805 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */
806 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR
807 #define trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(SERVICE, CLASS, pxObject) \
808 	if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
809 		prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
810 
811 /* This macro will create a call to a kernel service with a certain result, with a null object as parameter */
812 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_FROM_ISR
813 #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_FROM_ISR(SERVICE, TRACECLASS) \
814 	prvTraceStoreKernelCall(SERVICE, TRACECLASS, 0);
815 
816 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */
817 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR
818 #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(SERVICE, CLASS, pxObject, param) \
819 	if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
820 		prvTraceStoreKernelCallWithParam(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint32_t)param);
821 
822 /* This macro will create a call to a kernel service with a certain result, with a null object and other value as parameter */
823 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM_FROM_ISR
824 #define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM_FROM_ISR(SERVICE, TRACECLASS, param) \
825 	prvTraceStoreKernelCallWithParam(SERVICE, TRACECLASS, 0, param);
826 
827 /* This macro will create a call to a kernel service with a certain result, with an object as parameter */
828 #undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR
829 #define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR(SERVICE, param) \
830 	prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, (uint32_t)param);
831 
832 /* This macro will set the state for an object */
833 #undef trcKERNEL_HOOKS_SET_OBJECT_STATE
834 #define trcKERNEL_HOOKS_SET_OBJECT_STATE(CLASS, pxObject, STATE) \
835 	prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint8_t)STATE);
836 
837 /* This macro will flag a certain task as a finished instance */
838 #undef trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED
839 #define trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED() \
840 	if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
841 		prvTraceSetTaskInstanceFinished(TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()));
842 
843 #if (TRC_CFG_INCLUDE_READY_EVENTS == 1)
844 /* This macro will create an event to indicate that a task became Ready */
845 #undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE
846 #define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB) \
847 	if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
848 		prvTraceStoreTaskReady(TRACE_GET_TASK_NUMBER(pxTCB));
849 #else /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/
850 #undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE
851 #define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB)
852 #endif /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/
853 
854 /* This macro will update the internal tick counter and call prvTracePortGetTimeStamp(0) to update the internal counters */
855 #undef trcKERNEL_HOOKS_INCREMENT_TICK
856 #define trcKERNEL_HOOKS_INCREMENT_TICK() \
857 	{ \
858 		extern uint32_t uiTraceTickCount; \
859 		uiTraceTickCount++; \
860 		prvTracePortGetTimeStamp(0); \
861 	}
862 
863 #if (TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)
864 /* This macro will create an event indicating that the OS tick count has increased */
865 #undef trcKERNEL_HOOKS_NEW_TIME
866 #define trcKERNEL_HOOKS_NEW_TIME(SERVICE, xValue) \
867 	prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue);
868 #else /*(TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)*/
869 #undef trcKERNEL_HOOKS_NEW_TIME
870 #define trcKERNEL_HOOKS_NEW_TIME(SERVICE, xValue)
871 #endif /*(TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)*/
872 
873 /* This macro will create a task switch event to the currently executing task */
874 #undef trcKERNEL_HOOKS_TASK_SWITCH
875 #define trcKERNEL_HOOKS_TASK_SWITCH( pxTCB ) \
876 	if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
877 		prvTraceStoreTaskswitch(TRACE_GET_TASK_NUMBER(pxTCB));
878 
879 /* This macro will create an event to indicate that the task has been suspended */
880 #undef trcKERNEL_HOOKS_TASK_SUSPEND
881 #define trcKERNEL_HOOKS_TASK_SUSPEND(SERVICE, pxTCB) \
882 	if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
883 		if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
884 			prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \
885 	prvTraceSetTaskInstanceFinished((uint8_t)TRACE_GET_TASK_NUMBER(pxTCB));
886 
887 /* This macro will create an event to indicate that a task has called a wait/delay function */
888 #undef trcKERNEL_HOOKS_TASK_DELAY
889 #define trcKERNEL_HOOKS_TASK_DELAY(SERVICE, pxTCB, xValue) \
890 	if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
891 	{ \
892 		prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue); \
893 		prvTraceSetTaskInstanceFinished((uint8_t)TRACE_GET_TASK_NUMBER(pxTCB)); \
894 	}
895 
896 /* This macro will create an event to indicate that a task has gotten its priority changed */
897 #undef trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE
898 #define trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(SERVICE, pxTCB, uxNewPriority) \
899 	if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
900 	{ \
901 		prvTraceStoreKernelCallWithParam(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), prvTraceGetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)));\
902 		prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), (uint8_t)uxNewPriority); \
903 	}
904 
905 /* This macro will create an event to indicate that the task has been resumed */
906 #undef trcKERNEL_HOOKS_TASK_RESUME
907 #define trcKERNEL_HOOKS_TASK_RESUME(SERVICE, pxTCB) \
908 	if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
909 		if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
910 			prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
911 
912 /* This macro will create an event to indicate that the task has been resumed from ISR */
913 #undef trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR
914 #define trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR(SERVICE, pxTCB) \
915 	if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
916 		prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
917 
918 #if !defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1
919 /**
920  * @brief Dynamically enables ready events
921  *
922  * @param[in] flag Flag
923  */
924 void prvTraceSetReadyEventsEnabled(uint32_t flag);
925 
926 /**
927  * @brief Stores a Task Ready event
928  *
929  * @param[in] handle Task handle
930  */
931 void prvTraceStoreTaskReady(traceHandle handle);
932 #else
933 #define prvTraceSetReadyEventsEnabled(status) (void)status;
934 #endif
935 
936 /**
937  * @brief Stores a Low Power mode event
938  *
939  * @param[in] flag Flag
940  */
941 void prvTraceStoreLowPower(uint32_t flag);
942 
943 /**
944  * @brief Stores a Task Switch event
945  *
946  * @param[in] task_handle Task
947  */
948 void prvTraceStoreTaskswitch(traceHandle task_handle);
949 
950 #if (TRC_CFG_SCHEDULING_ONLY == 0)
951 
952 /**
953  * @brief Stores a Kernel Service call event with an Object handle parameter
954  *
955  * @param[in] eventcode Event code
956  * @param[in] objectClass Object class
957  * @param[in] objectNumber Object handle
958  */
959 void prvTraceStoreKernelCall(uint32_t eventcode, traceObjectClass objectClass, uint32_t objectNumber);
960 
961 /**
962  * @brief Stores a Kernel Service call event with only a numeric parameter
963  *
964  * @param[in] evtcode Event code
965  * @param[in] param Parameter
966  */
967 void prvTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param);
968 
969 /**
970  * @brief Stores a Kernel Service call event with an Object handle and a numeric parameter
971  *
972  * @param[in] evtcode Event code
973  * @param[in] objectClass Object class
974  * @param[in] objectNumber Object handle
975  * @param[in] param Parameter
976  */
977 void prvTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass,
978 									uint32_t objectNumber, uint32_t param);
979 #else
980 
981 #define prvTraceStoreKernelCall(eventcode, objectClass, byteParam) {}
982 #define prvTraceStoreKernelCallWithNumericParamOnly(evtcode, param) {}
983 #define prvTraceStoreKernelCallWithParam(evtcode, objectClass, objectNumber, param) {}
984 
985 #endif
986 
987 /**
988  * @brief Flags a task instance as finished
989  *
990  * @param[in] handle Task handle
991  */
992 void prvTraceSetTaskInstanceFinished(traceHandle handle);
993 
994 /**
995  * @brief Set priority
996  *
997  * @param[in] objectclass Object class
998  * @param[in] id Object handle
999  * @param[in] value Value
1000  */
1001 void prvTraceSetPriorityProperty(uint8_t objectclass, traceHandle id, uint8_t value);
1002 
1003 /**
1004  * @brief Get priority
1005  *
1006  * @param[in] objectclass Object class
1007  * @param[in] id Object handle
1008  *
1009  * @return uint8_t Value
1010  */
1011 uint8_t prvTraceGetPriorityProperty(uint8_t objectclass, traceHandle id);
1012 
1013 /**
1014  * @brief Set object state
1015  *
1016  * @param[in] objectclass Object class
1017  * @param[in] id Object handle
1018  * @param[in] value Value
1019  */
1020 void prvTraceSetObjectState(uint8_t objectclass, traceHandle id, uint8_t value);
1021 
1022 /**
1023  * @brief Mark object as used
1024  *
1025  * @param[in] objectclass Object class
1026  * @param[in] handle Object handle
1027  */
1028 void prvMarkObjectAsUsed(traceObjectClass objectclass, traceHandle handle);
1029 
1030 /**
1031  * @brief Stores the name of an object because it is being deleted
1032  *
1033  * @param[in] evtcode Event code
1034  * @param[in] handle Object handle
1035  * @param[in] objectclass Object class
1036  */
1037 void prvTraceStoreObjectNameOnCloseEvent(uint8_t evtcode, traceHandle handle,
1038 										traceObjectClass objectclass);
1039 
1040 /**
1041  * @brief Stores the property of an object because it is being deleted
1042  *
1043  * @param[in] evtcode Event code
1044  * @param[in] handle Object handle
1045  * @param[in] objectclass Object class
1046  */
1047 void prvTraceStoreObjectPropertiesOnCloseEvent(uint8_t evtcode, traceHandle handle,
1048 											 traceObjectClass objectclass);
1049 
1050 /* Internal constants for task state */
1051 #define TASK_STATE_INSTANCE_NOT_ACTIVE 0
1052 #define TASK_STATE_INSTANCE_ACTIVE 1
1053 
1054 
1055 #if (TRC_CFG_INCLUDE_ISR_TRACING == 0)
1056 
1057 #undef vTraceSetISRProperties
1058 #define vTraceSetISRProperties(handle, name, priority) (void)(handle), (void)(name), (void)(priority) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */
1059 
1060 #undef vTraceStoreISRBegin
1061 #define vTraceStoreISRBegin(x) (void)(x)
1062 
1063 #undef vTraceStoreISREnd
1064 #define vTraceStoreISREnd(x) (void)(x)
1065 
1066 #undef xTraceSetISRProperties
1067 #define xTraceSetISRProperties(name, priority) ((void)(name), (void)(priority), (traceHandle)0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */
1068 
1069 #endif /*(TRC_CFG_INCLUDE_ISR_TRACING == 0)*/
1070 
1071 /**
1072  * @brief
1073  *
1074  * Returns a pointer to the recorder data structure. Use this together with
1075  * uiTraceGetTraceBufferSize if you wish to implement an own store/upload
1076  * solution, e.g., in case a debugger connection is not available for uploading
1077  * the data.
1078  *
1079  * @return void* Buffer pointer
1080  */
1081 void* xTraceGetTraceBuffer(void);
1082 
1083 /**
1084  * @brief
1085  *
1086  * Gets the size of the recorder data structure. For use together with
1087  * xTraceGetTraceBuffer if you wish to implement an own store/upload solution,
1088  * e.g., in case a debugger connection is not available for uploading the data.
1089  *
1090  * @return uint32_t Buffer size
1091  */
1092 uint32_t uiTraceGetTraceBufferSize(void);
1093 
1094 #if (TRC_CFG_SCHEDULING_ONLY == 1)
1095 #undef TRC_CFG_INCLUDE_USER_EVENTS
1096 #define TRC_CFG_INCLUDE_USER_EVENTS 0
1097 #endif /*(TRC_CFG_SCHEDULING_ONLY == 1)*/
1098 
1099 #if ((TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)
1100 
1101 /**
1102  * @brief Register a channel and fixed format string for use with the separate User Event Buffer functions
1103  *
1104  * @param[in] channel Channel name handle
1105  * @param[in] formatStr Format string that will be used for all events on this channel
1106  *
1107  * @return traceUBChannel Channel handle
1108  */
1109 traceUBChannel xTraceRegisterUBChannel(TraceStringHandle_t channel, TraceStringHandle_t formatStr);
1110 
1111 /**
1112  * @brief Creates a User Event using the channel, previously set format string and data parameters
1113  *
1114  * @param[in] channel Channel
1115  * @param[in] ...
1116  */
1117 void vTraceUBData(traceUBChannel channel, ...);
1118 
1119 /**
1120  * @brief Creates a User Event using the channel and previously set string
1121  *
1122  * @param[in] channel Channel
1123  */
1124 void vTraceUBEvent(traceUBChannel channel);
1125 #else
1126 #define xTraceRegisterChannelFormat(eventLabel, formatStr) ((void)(eventLabel), (void)(formatStr), 0)
1127 #define vTraceUBData(label, ...) (void)(label)
1128 #endif /*(TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)*/
1129 
1130 #define NEventCodes 0x100
1131 
1132 /* Our local critical sections for the recorder */
1133 #define trcCRITICAL_SECTION_BEGIN() {TRACE_ENTER_CRITICAL_SECTION(); recorder_busy++;}
1134 #define trcCRITICAL_SECTION_END() {recorder_busy--; TRACE_EXIT_CRITICAL_SECTION();}
1135 
1136 #if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M)
1137 	#define trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY TRACE_ALLOC_CRITICAL_SECTION
1138 	#define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_BEGIN
1139 	#define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_END
1140 #else
1141 	#define trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY() {}
1142 	#define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY() recorder_busy++;
1143 	#define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--;
1144 #endif
1145 
1146 /**
1147  * @brief Object handle stack struct.
1148  *
1149  * This data-structure is used to provide a mechanism for 1-byte trace object
1150  * handles. This way, only 1 byte is necessary instead of 4 bytes (a pointer)
1151  * when storing a reference to an object. This allows for up to 255 objects of
1152  * each object class active at any given moment. There can be more "historic"
1153  * objects, that have been deleted - that number is only limited by the size of
1154  * the symbol table.
1155  *
1156  * Note that handle zero (0) is not used, it is a code for an invalid handle.
1157  *
1158  * This data structure keeps track of the FREE handles, not the handles in use.
1159  * This data structure contains one stack per object class. When a handle is
1160  * allocated to an object, the next free handle is popped from the stack. When
1161  * a handle is released (on object delete), it is pushed back on the stack.
1162  * Note that there is no initialization code that pushed the free handles
1163  * initially, that is not necessary due to the following optimization:
1164  *
1165  * The stack of handles (objectHandles) is initially all zeros. Since zero
1166  * is not a valid handle, that is a signal of additional handles needed.
1167  * If a zero is received when popping a new handle, it is replaced by the
1168  * index of the popped handle instead.
1169  */
1170 typedef struct
1171 {
1172 	uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ]; /**< For each object class, the index of the next handle to allocate */
1173 	uint16_t lowestIndexOfClass[ TRACE_NCLASSES ]; /**< The lowest index of this class (constant) */
1174 	uint16_t highestIndexOfClass[ TRACE_NCLASSES ]; /**< The highest index of this class (constant) */
1175 	uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ]; /**< The highest use count for this class (for statistics) */
1176 	traceHandle objectHandles[ TRACE_KERNEL_OBJECT_COUNT ]; /**< The free object handles - a set of stacks within this array */
1177 } objectHandleStackType;
1178 
1179 extern objectHandleStackType objectHandleStacks;
1180 
1181 /**
1182  * @brief Object property table struct
1183  *
1184  * The Object Table contains name and other properties of the objects (tasks,
1185  * queues, mutexes, etc). The below data structures defines the properties of
1186  * each object class and are used to cast the byte buffer into a cleaner format.
1187  *
1188  * The values in the object table are continuously overwritten and always
1189  * represent the current state. If a property is changed during runtime, the OLD
1190  * value should be stored in the trace buffer, not the new value (since the new
1191  * value is found in the Object Property Table).
1192  *
1193  * For close events this mechanism is the old names are stored in the symbol
1194  * table), for "priority set" (the old priority is stored in the event data)
1195  * and for "isActive", where the value decides if the task switch event type
1196  * should be "new" or "resume".
1197  */
1198 typedef struct
1199 {
1200 	/* = NCLASSES */
1201 	uint32_t NumberOfObjectClasses; /**< */
1202 	uint32_t ObjectPropertyTableSizeInBytes; /**<  */
1203 
1204 	/* This is used to calculate the index in the dynamic object table
1205 	(handle - 1 - nofStaticObjects = index)*/
1206 #if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1)
1207 	traceHandle NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)]; /** */
1208 #else
1209 	traceHandle NumberOfObjectsPerClass[4*((TRACE_NCLASSES+3)/4)]; /** */
1210 #endif
1211 	/* Allocation size rounded up to the closest multiple of 4 */
1212 	uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/4) ]; /**< */
1213 
1214 	/* Allocation size rounded up to the closest multiple of 2 */
1215 	uint8_t TotalPropertyBytesPerClass[ 4*((TRACE_NCLASSES+3)/4) ]; /**< */
1216 
1217 	/* */
1218 	uint16_t StartIndexOfClass[ 2*((TRACE_NCLASSES+1)/2) ]; /**< */
1219 
1220 	/* The actual handles issued, should be Initiated to all zeros */
1221 	uint8_t objbytes[ 4*((TRACE_OBJECT_TABLE_SIZE+3)/4) ]; /**< */
1222 } ObjectPropertyTableType;
1223 
1224 /**
1225  * @brief Symbol table structure
1226  */
1227 typedef struct
1228 {
1229 	/* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */
1230 	uint32_t symTableSize; /**< */
1231 
1232 	/* Entry 0 is reserved. Any reference to entry 0 implies NULL*/
1233 	uint32_t nextFreeSymbolIndex; /**< */
1234 
1235 	/* Size rounded up to closest multiple of 4, to avoid alignment issues*/
1236 	uint8_t symbytes[4*(((TRC_CFG_SYMBOL_TABLE_SIZE)+3)/4)]; /**< */
1237 
1238 	/* Used for lookups - Up to 64 linked lists within the symbol table
1239 	connecting all entries with the same 6 bit checksum.
1240 	This field holds the current list heads. Should be initiated to zeros */
1241 	uint16_t latestEntryOfChecksum[64]; /**< */
1242 } symbolTableType;
1243 
1244 
1245 /*******************************************************************************
1246  * The data structures of the different events, all 4 bytes long
1247  ******************************************************************************/
1248 
1249 typedef struct
1250 {
1251 	uint8_t type;
1252 	uint8_t objHandle;
1253 	uint16_t dts;	/* differential timestamp - time since last event */
1254 } TSEvent, TREvent;
1255 
1256 typedef struct
1257 {
1258 	uint8_t type;
1259 	uint8_t dummy;
1260 	uint16_t dts;	/* differential timestamp - time since last event */
1261 } LPEvent;
1262 
1263 typedef struct
1264 {
1265 	uint8_t type;
1266 	uint8_t objHandle;
1267 	uint16_t dts;	/* differential timestamp - time since last event */
1268 } KernelCall;
1269 
1270 typedef struct
1271 {
1272 	uint8_t type;
1273 	uint8_t objHandle;
1274 	uint8_t param;
1275 	uint8_t dts;	/* differential timestamp - time since last event */
1276 } KernelCallWithParamAndHandle;
1277 
1278 typedef struct
1279 {
1280 	uint8_t type;
1281 	uint8_t dts;	/* differential timestamp - time since last event */
1282 	uint16_t param;
1283 } KernelCallWithParam16;
1284 
1285 typedef struct
1286 {
1287 	uint8_t type;
1288 	uint8_t objHandle;		/* the handle of the closed object */
1289 	uint16_t symbolIndex;	/* the name of the closed object */
1290 } ObjCloseNameEvent;
1291 
1292 typedef struct
1293 {
1294 	uint8_t type;
1295 	uint8_t arg1;
1296 	uint8_t arg2;
1297 	uint8_t arg3;
1298 } ObjClosePropEvent;
1299 
1300 typedef struct
1301 {
1302 	uint8_t type;
1303 	uint8_t unused1;
1304 	uint8_t unused2;
1305 	uint8_t dts;
1306 } TaskInstanceStatusEvent;
1307 
1308 typedef struct
1309 {
1310 	uint8_t type;
1311 	uint8_t dts;
1312 	uint16_t payload;		 /* the name of the user event */
1313 } UserEvent;
1314 
1315 typedef struct
1316 {
1317 	uint8_t type;
1318 
1319 	/* 8 bits extra for storing DTS, if it does not fit in ordinary event
1320 	(this one is always MSB if used) */
1321 	uint8_t xts_8;
1322 
1323 	/* 16 bits extra for storing DTS, if it does not fit in ordinary event. */
1324 	uint16_t xts_16;
1325 } XTSEvent;
1326 
1327 typedef struct
1328 {
1329 	uint8_t type;
1330 
1331 	uint8_t xps_8;
1332 	uint16_t xps_16;
1333 } XPSEvent;
1334 
1335 typedef struct{
1336 	uint8_t type;
1337 	uint8_t dts;
1338 	uint16_t size;
1339 } MemEventSize;
1340 
1341 typedef struct{
1342 	uint8_t type;
1343 	uint8_t addr_high;
1344 	uint16_t addr_low;
1345 } MemEventAddr;
1346 
1347 /*******************************************************************************
1348  * The separate user event buffer structure. Can be enabled in trcConfig.h.
1349  ******************************************************************************/
1350 
1351 #if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)
1352 typedef struct
1353 {
1354 	TraceStringHandle_t name;
1355 	TraceStringHandle_t defaultFormat;
1356 } ChannelFormatPair;
1357 
1358 typedef struct
1359 {
1360 	uint16_t bufferID;
1361 	uint16_t version;
1362 	uint32_t wraparoundCounter;
1363 	uint32_t numberOfSlots;
1364 	uint32_t nextSlotToWrite;
1365 	uint8_t numberOfChannels;
1366 	uint8_t padding1;
1367 	uint8_t padding2;
1368 	uint8_t padding3;
1369 	ChannelFormatPair channels[(TRC_CFG_UB_CHANNELS)+1];
1370 	uint8_t channelBuffer[((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) + 3) & 0xFFFFFFFC]; /* 1 byte per slot, with padding for 4 byte alignment */
1371 	uint8_t dataBuffer[(TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) * 4]; /* 4 bytes per slot */
1372 
1373 } UserEventBuffer;
1374 #endif /* (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) */
1375 
1376 /*******************************************************************************
1377  * The main data structure, read by Tracealyzer from the RAM dump
1378  ******************************************************************************/
1379 
1380 typedef struct
1381 {
1382 	volatile uint8_t startmarker0; /* Volatile is important, see init code. */
1383 	volatile uint8_t startmarker1;
1384 	volatile uint8_t startmarker2;
1385 	volatile uint8_t startmarker3;
1386 	volatile uint8_t startmarker4;
1387 	volatile uint8_t startmarker5;
1388 	volatile uint8_t startmarker6;
1389 	volatile uint8_t startmarker7;
1390 	volatile uint8_t startmarker8;
1391 	volatile uint8_t startmarker9;
1392 	volatile uint8_t startmarker10;
1393 	volatile uint8_t startmarker11;
1394 
1395 	/* Used to determine Kernel and Endianess */
1396 	uint16_t version;
1397 
1398 	/* Currently 7 */
1399 	uint8_t minor_version;
1400 
1401 	/* This should be 0 if lower IRQ priority values implies higher priority
1402 	levels, such as on ARM Cortex M. If the opposite scheme is used, i.e.,
1403 	if higher IRQ priority values means higher priority, this should be 1. */
1404 	uint8_t irq_priority_order;
1405 
1406 	/* sizeof(RecorderDataType) - just for control */
1407 	uint32_t filesize;
1408 
1409 	/* Current number of events recorded */
1410 	uint32_t numEvents;
1411 
1412 	/* The buffer size, in number of event records */
1413 	uint32_t maxEvents;
1414 
1415 	/* The event buffer index, where to write the next event */
1416 	uint32_t nextFreeIndex;
1417 
1418 	/* 1 if the buffer is full, 0 otherwise */
1419 	uint32_t bufferIsFull;
1420 
1421 	/* The frequency of the clock/timer/counter used as time base */
1422 	uint32_t frequency;
1423 
1424 	/* The absolute timestamp of the last stored event, in the native
1425 	timebase, modulo frequency! */
1426 	uint32_t absTimeLastEvent;
1427 
1428 	/* The number of seconds in total - lasts for 136 years */
1429 	uint32_t absTimeLastEventSecond;
1430 
1431 	/* 1 if the recorder has been started, 0 if not yet started or stopped.
1432 	This is a 32 bit variable due to alignment issues. */
1433 	uint32_t recorderActive;
1434 
1435 	/* If > 0, tells the maximum time between two traced ISRs that execute
1436 	back-to-back. If the time between vTraceStoreISREnd and a directly
1437 	following vTraceISRBegin is above isrTailchainingThreshold, we assume a
1438 	return to the previous context in between the ISRs, otherwise we assume
1439 	the have executed back-to-back and don't show any fragment of the previous
1440 	context in between. */
1441 	uint32_t isrTailchainingThreshold;
1442 
1443 	/* The maximum amount of heap memory that was allocated */
1444 	uint32_t heapMemMaxUsage;
1445 
1446 	/* The amount of heap memory used */
1447 	uint32_t heapMemUsage;
1448 
1449 	/* 0xF0F0F0F0 - for control only */
1450 	int32_t debugMarker0;
1451 
1452 	/* Set to value of TRC_CFG_USE_16BIT_OBJECT_HANDLES */
1453 	uint32_t isUsing16bitHandles;
1454 
1455 	/* The Object Property Table holds information about currently active
1456 	tasks, queues, and other recorded objects. This is updated on each
1457 	create call and includes object name and other properties. */
1458 	ObjectPropertyTableType ObjectPropertyTable;
1459 
1460 	/* 0xF1F1F1F1 - for control only */
1461 	int32_t debugMarker1;
1462 
1463 	/* The Symbol Table stores strings for User Events and is also used to
1464 	store names of deleted objects, which still may be in the trace but no
1465 	longer are available. */
1466 	symbolTableType SymbolTable;
1467 
1468 	/* For inclusion of float support, and for endian detection of floats.
1469 	The value should be (float)1 or (uint32_t)0 */
1470 #if (TRC_CFG_INCLUDE_FLOAT_SUPPORT == 1)
1471 	float exampleFloatEncoding;
1472 #else
1473 	uint32_t exampleFloatEncoding;
1474 #endif
1475 	/* This is non-zero if an internal error occurred in the recorder, e.g., if
1476 	one of the Nxxx constants was too small. The systemInfo string will then
1477 	contain an error message that is displayed when attempting to view the
1478 	trace file. */
1479 	uint32_t internalErrorOccured;
1480 
1481 	/* 0xF2F2F2F2 - for control only */
1482 	int32_t debugMarker2;
1483 
1484 	/* Error messages from the recorder. */
1485 	char systemInfo[80];
1486 
1487 	/* 0xF3F3F3F3 - for control only */
1488 	int32_t debugMarker3;
1489 
1490 	/* The event data, in 4-byte records */
1491 	uint8_t eventData[ (TRC_CFG_EVENT_BUFFER_SIZE) * 4 ];
1492 
1493 #if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)
1494 	UserEventBuffer userEventBuffer;
1495 #endif
1496 
1497 	/* This should always be 0 */
1498 	uint32_t endOfSecondaryBlocks;
1499 
1500 	uint8_t endmarker0;
1501 	uint8_t endmarker1;
1502 	uint8_t endmarker2;
1503 	uint8_t endmarker3;
1504 	uint8_t endmarker4;
1505 	uint8_t endmarker5;
1506 	uint8_t endmarker6;
1507 	uint8_t endmarker7;
1508 	uint8_t endmarker8;
1509 	uint8_t endmarker9;
1510 	uint8_t endmarker10;
1511 	uint8_t endmarker11;
1512 } RecorderDataType;
1513 
1514 extern RecorderDataType* RecorderDataPtr;
1515 
1516 /* Internal functions */
1517 
1518 /**
1519  * @brief Signals a trace error
1520  *
1521  * @param[in] msg Message
1522  */
1523 void prvTraceError(const char* msg);
1524 
1525 /**
1526  * @brief
1527  *
1528  * Returns the current time based on the HWTC macros which provide a hardware
1529  * isolation layer towards the hardware timer/counter.
1530  *
1531  * The HWTC macros and prvTracePortGetTimeStamp is the main porting issue
1532  * or the trace recorder library. Typically you should not need to change
1533  * the code of prvTracePortGetTimeStamp if using the HWTC macros.
1534  *
1535  * @param[out] puiTimestamp Timestamp
1536  */
1537 void prvTracePortGetTimeStamp(uint32_t *puiTimestamp);
1538 
1539 /**
1540  * @brief Reserve an object handle
1541  *
1542  * @param[in] objectclass Object class
1543  *
1544  * @return traceHandle
1545  */
1546 traceHandle prvTraceGetObjectHandle(traceObjectClass objectclass);
1547 
1548 /**
1549  * @brief Free an object handle
1550  *
1551  * @param[in] objectclass Object class
1552  * @param[in] handle Handle
1553  */
1554 void prvTraceFreeObjectHandle(traceObjectClass objectclass,
1555 							traceHandle handle);
1556 
1557 /* Private function. Use the public functions in trcKernelPort.h */
1558 
1559 /**
1560  * @brief Set the object name
1561  *
1562  * @param[in] objectclass Object class
1563  * @param[in] handle Handle
1564  * @param[in] name Name
1565  */
1566 void prvTraceSetObjectName(traceObjectClass objectclass,
1567 							traceHandle handle,
1568 							const char* name);
1569 
1570 /* Internal macros */
1571 
1572 #define TRACE_PROPERTY_NAME_GET(objectclass, objecthandle) \
1573 	(const char*)(& RecorderDataPtr->ObjectPropertyTable.objbytes \
1574 	[uiIndexOfObject(objecthandle, objectclass)])
1575 
1576 #define TRACE_PROPERTY_OBJECT_STATE(objectclass, handle) \
1577 	RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
1578 	+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass]]
1579 
1580 #define TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle) \
1581 	RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
1582 	+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass] + 1]
1583 
1584 /* DEBUG ASSERTS */
1585 #if defined TRC_CFG_USE_TRACE_ASSERT && TRC_CFG_USE_TRACE_ASSERT != 0
1586 #define TRACE_ASSERT(eval, msg, defRetVal) \
1587 	if (!(eval)) \
1588 	{ \
1589 		prvTraceError("TRACE_ASSERT: " msg); \
1590 		return defRetVal; \
1591 	}
1592 #else
1593 #define TRACE_ASSERT(eval, msg, defRetVal)
1594 #endif
1595 
1596 typedef RecorderDataType TraceRecorderDataBuffer_t;
1597 
1598 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)*/
1599 
1600 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
1601 
1602 #ifndef TRC_EXTERNAL_BUFFERS
1603 #define TRC_EXTERNAL_BUFFERS 0
1604 #endif
1605 
1606 typedef struct TraceRecorderData
1607 {
1608 	uint32_t uiSessionCounter;
1609 	uint32_t uiRecorderEnabled;
1610 	uint32_t uiTraceSystemState;
1611 
1612 	TraceAssertBuffer_t xAssertBuffer;
1613 #if (TRC_EXTERNAL_BUFFERS == 0)
1614 	TraceHeaderBuffer_t xHeaderBuffer;
1615 	TraceEntryTableBuffer_t xEntryTableBuffer;
1616 	TraceTimestampBuffer_t xTimestampBuffer;
1617 #endif
1618 	TraceStreamPortBuffer_t xStreamPortBuffer;
1619 	TraceStaticBufferBuffer_t xStaticBufferBuffer;
1620 	TraceEventDataBuffer_t xEventDataBuffer;
1621 	TracePrintBuffer_t xPrintBuffer;
1622 	TraceErrorBuffer_t xErrorBuffer;
1623 	TraceISRInfoBuffer_t xISRInfoBuffer;
1624 	TraceKernelPortDataBuffer_t xKernelPortBuffer;
1625 	TraceTaskInfoBuffer_t xTaskInfoBuffer;
1626 	TraceStackMonitorBuffer_t xStackMonitorBuffer;
1627 	TraceDiagnosticsBuffer_t xDiagnosticsBuffer;
1628 } TraceRecorderData_t;
1629 
1630 extern TraceRecorderData_t* pxTraceRecorderData;
1631 extern uint32_t RecorderInitialized;
1632 
1633 #define TRC_RECORDER_DATA_BUFFER_SIZE (sizeof(TraceRecorderData_t))
1634 
1635 typedef struct TraceRecorderDataBuffer
1636 {
1637 	uint8_t buffer[(TRC_RECORDER_DATA_BUFFER_SIZE)];
1638 } TraceRecorderDataBuffer_t;
1639 
1640 /**
1641  * @brief Initializes the header data
1642  *
1643  * @param[in] pxBuffer Pointer to header buffer
1644  *
1645  * @retval TRC_FAIL Failure
1646  * @retval TRC_SUCCESS Success
1647  */
1648 traceResult xTraceHeaderInitialize(TraceHeaderBuffer_t* pxBuffer);
1649 
1650 /**
1651  * @brief Query if recorder is enabled
1652  *
1653  * @retval 1 Recorder enabled
1654  * @retval 0 Recorder not enabled
1655  */
1656 #define xTraceIsRecorderEnabled() (xTraceIsRecorderInitialized() & pxTraceRecorderData->uiRecorderEnabled)
1657 
1658 /**
1659  * @brief Query if recorder initialized
1660  *
1661  * @retval 1 Recorder initialized
1662  * @retval 0 Recorder not initialized
1663  */
1664 #define xTraceIsRecorderInitialized() xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_CORE)
1665 
1666 /**
1667  * @brief Flag component as initialized
1668  *
1669  * @param[in] uiComponentBit Component bit
1670  *
1671  * @retval TRC_FAIL Failure
1672  * @retval TRC_SUCCESS Success
1673  */
1674 #define xTraceSetComponentInitialized(uiComponentBit) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(RecorderInitialized |= (uiComponentBit), TRC_SUCCESS)
1675 
1676 /**
1677  * @brief Query if component is initialized
1678  *
1679  * @param[in] uiComponentBit Component bit
1680  *
1681  * @retval 1 Component initialized
1682  * @retval 0 Component not initialized
1683  */
1684 #define xTraceIsComponentInitialized(uiComponentBit) ((RecorderInitialized & (uiComponentBit)) ? 1 : 0)
1685 
1686 /**
1687  * @brief Set the trace state
1688  *
1689  * @param[in] uiState State
1690  *
1691  * @retval TRC_FAIL Failure
1692  * @retval TRC_SUCCESS Success
1693  */
1694 #define xTraceStateSet(uiState) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(pxTraceRecorderData->uiTraceSystemState = (uiState), TRC_SUCCESS)
1695 
1696 /**
1697  * @brief Query the trace state
1698  *
1699  * @param[out] puiState State
1700  *
1701  * @retval TRC_FAIL Failure
1702  * @retval TRC_SUCCESS Success
1703  */
1704 #define xTraceStateGet(puiState) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(puiState) = pxTraceRecorderData->uiTraceSystemState, TRC_SUCCESS)
1705 
1706 /**
1707  * @brief Call this function periodically
1708  *
1709  * @retval TRC_FAIL Failure
1710  * @retval TRC_SUCCESS Success
1711  */
1712 traceResult xTraceTzCtrl(void);
1713 
1714 /******************************************************************************/
1715 /*** INTERNAL STREAMING FUNCTIONS *********************************************/
1716 /******************************************************************************/
1717 
1718 /**
1719  * @brief Stores an event without parameters
1720  *
1721  * @param[in] _eventID Event id
1722  */
1723 #define prvTraceStoreEvent_None(_eventID) \
1724 	{ \
1725 		TraceEventHandle_t _xEventHandle = 0; \
1726 		if (xTraceEventBegin(_eventID, 0, &_xEventHandle) == TRC_SUCCESS) \
1727 		{ \
1728 			xTraceEventEnd(_xEventHandle); \
1729 		} \
1730 	}
1731 
1732 /**
1733  * @brief Stores an event with a handle parameter
1734  *
1735  * @param[in] _eventID Event id
1736  * @param[in] _handle Handle
1737  */
1738 #define prvTraceStoreEvent_Handle(_eventID, _handle) \
1739 	{ \
1740 		TraceEventHandle_t _xEventHandle = 0; \
1741 		if (xTraceEventBegin(_eventID, sizeof(void*), &_xEventHandle) == TRC_SUCCESS) \
1742 		{ \
1743 			xTraceEventAddPointer(_xEventHandle, (void*)(_handle)); \
1744 			xTraceEventEnd(_xEventHandle); \
1745 		} \
1746 	}
1747 
1748 /**
1749  * @brief Stores an event with one 32-bit parameter
1750  *
1751  * @param[in] _eventID Event id
1752  * @param[in] _param1 Param
1753  */
1754 #define prvTraceStoreEvent_Param(_eventID, _param1) \
1755 	{ \
1756 		TraceEventHandle_t _xEventHandle = 0; \
1757 		if (xTraceEventBegin(_eventID, sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \
1758 		{ \
1759 			xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \
1760 			xTraceEventEnd(_xEventHandle); \
1761 		} \
1762 	}
1763 
1764 /**
1765  * @brief Stores an event with a handle and one 32-bit parameter
1766  *
1767  * @param[in] _eventID Event id
1768  * @param[in] _handle Handle
1769  * @param[in] _param1 Param
1770  */
1771 #define prvTraceStoreEvent_HandleParam(_eventID, _handle, _param1) \
1772 	{ \
1773 		TraceEventHandle_t _xEventHandle = 0; \
1774 		if (xTraceEventBegin(_eventID, sizeof(void*) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \
1775 		{ \
1776 			xTraceEventAddPointer(_xEventHandle, (void*)(_handle)); \
1777 			xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \
1778 			xTraceEventEnd(_xEventHandle); \
1779 		} \
1780 	}
1781 
1782 /**
1783  * @brief Stores an event with two 32-bit parameters
1784  *
1785  * @param[in] _eventID Event id
1786  * @param[in] _param1 Param 1
1787  * @param[in] _param2 Param 2
1788  */
1789 #define prvTraceStoreEvent_ParamParam(_eventID, _param1, _param2) \
1790 	{ \
1791 		TraceEventHandle_t _xEventHandle = 0; \
1792 		if (xTraceEventBegin(_eventID, sizeof(uint32_t) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \
1793 		{ \
1794 			xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \
1795 			xTraceEventAdd32(_xEventHandle, (uint32_t)(_param2)); \
1796 			xTraceEventEnd(_xEventHandle); \
1797 		} \
1798 	}
1799 
1800 /**
1801  * @brief Stores an event with a handle and two 32-bit parameters
1802  *
1803  * @param[in] _eventID Event id
1804  * @param[in] _handle Handle
1805  * @param[in] _param1 Param 1
1806  * @param[in] _param2 Param 2
1807  */
1808 #define prvTraceStoreEvent_HandleParamParam(_eventID, _handle, _param1, _param2) \
1809 	{ \
1810 		TraceEventHandle_t _xEventHandle = 0; \
1811 		if (xTraceEventBegin(_eventID, sizeof(void*) + sizeof(uint32_t) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \
1812 		{ \
1813 			xTraceEventAddPointer(_xEventHandle, (void*)(_handle)); \
1814 			xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \
1815 			xTraceEventAdd32(_xEventHandle, (uint32_t)(_param2)); \
1816 			xTraceEventEnd(_xEventHandle); \
1817 		} \
1818 	}
1819 
1820 /**
1821  * @brief Stores an event with three 32-bit parameters
1822  *
1823  * @param[in] _eventID Event id
1824  * @param[in] _param1 Param 1
1825  * @param[in] _param2 Param 2
1826  * @param[in] _param3 Param 3
1827  */
1828 #define prvTraceStoreEvent_ParamParamParam(_eventID, _param1, _param2, _param3) \
1829 	{ \
1830 		TraceEventHandle_t _xEventHandle = 0; \
1831 		if (xTraceEventBegin(_eventID, sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \
1832 		{ \
1833 			xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \
1834 			xTraceEventAdd32(_xEventHandle, (uint32_t)(_param2)); \
1835 			xTraceEventAdd32(_xEventHandle, (uint32_t)(_param3)); \
1836 			xTraceEventEnd(_xEventHandle); \
1837 		} \
1838 	}
1839 
1840 /**
1841  * @brief Snapshot mode only. Trace stop hook.
1842  *
1843  * @param[in] x
1844  */
1845 #define vTraceSetStopHook(x) (void)(x)
1846 
1847 /**
1848  * @brief Snapshot mode only. Initialize timestamps.
1849  */
1850 #define vTraceInitTimestamps()
1851 
1852 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
1853 
1854 #if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM)
1855 /**
1856  * @brief Set the recorder data buffer
1857  *
1858  * @param[in] pxBuffer Pointer to the recorder data buffer
1859  *
1860  * @retval TRC_FAIL Failure
1861  * @retval TRC_SUCCESS Success
1862  */
1863 traceResult xTraceSetBuffer(TraceRecorderDataBuffer_t *pxBuffer);
1864 #else
1865 #define xTraceSetBuffer(p) (TRC_SUCCESS)
1866 #endif
1867 
1868 /**
1869  * @brief Retrieve the event buffer and event buffer size
1870  *
1871  * @param[out] ppvBuffer Pointer where event buffer pointer will be written
1872  * @param[out] puiSize Event buffer size
1873  *
1874  * @retval TRC_FAIL Failure
1875  * @retval TRC_SUCCESS Success
1876  */
1877 traceResult xTraceGetEventBuffer(void** ppvBuffer, TraceUnsignedBaseType_t * puiSize);
1878 
1879 #else /* when TRC_USE_TRACEALYZER_RECORDER == 0 */
1880 
1881 #define xTraceInitialize() (TRC_SUCCESS)
1882 #define xTraceEnable(x) ((void)(x), TRC_SUCCESS)
1883 #define xTraceDisable() (TRC_SUCCESS)
1884 #define xTraceStringRegister(x, y) ((void)(x), (void)y, TRC_SUCCESS) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */
1885 #define xTracePrint(chn, ...) ((void)(chn), TRC_SUCCESS)
1886 #define xTracePrintF(chn, fmt, ...) ((void)(chn), (void)(fmt), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */
1887 #define xTraceVPrintF(chn, formatStr, vl) ((void)(chn), (void)(formatStr), (void)(vl), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */
1888 #define xTraceTaskInstanceFinishedNow()
1889 #define xTraceTaskInstanceFinishedNext()
1890 #define vTraceStoreISRBegin(x) (void)(x)
1891 #define vTraceStoreISREnd(x) (void)(x)
1892 #define xTraceSetISRProperties(a, b) ((void)(a), (void)(b), (traceHandle)0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */
1893 #define xTraceRegisterChannelFormat(eventLabel, formatStr) ((void)(eventLabel), (void)(formatStr), 0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */
1894 #define vTraceUBData(label, ...) (void)(label)
1895 
1896 #define vTraceSetFilterGroup(x) (void)(x)
1897 #define vTraceSetFilterMask(x) (void)(x)
1898 
1899 #define prvTraceSetReadyEventsEnabled(status) (void)(status)
1900 
1901 #define vTraceExcludeTask(handle) (void)(handle)
1902 
1903 #define vTraceConsoleChannelPrintF(fmt, ...) (void)(fmt)
1904 
1905 #ifndef TRC_ALLOC_CUSTOM_BUFFER
1906 #define TRC_ALLOC_CUSTOM_BUFFER(bufname)
1907 #endif
1908 
1909 #define xTraceIsRecorderEnabled() (0)
1910 #define xTraceIsRecorderInitialized() (0)
1911 
1912 #define xTraceSetBuffer(p) (TRC_SUCCESS)
1913 #define xTraceGetEventBuffer(p) (TRC_FAIL)
1914 
1915 #define vTraceSetStopHook(x) (void)(x)
1916 
1917 #define TraceRecorderDataBuffer_t uint32_t
1918 
1919 #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
1920 
1921 /**
1922  * @deprecated Backwards compatibility. Use xTraceInitialize instead.
1923  */
1924 #define vTraceInitialize (void)xTraceInitialize
1925 
1926 /**
1927  * @deprecated Backwards compatibility. Use xTraceEnable instead.
1928  */
1929 #define vTraceEnable (void)xTraceEnable
1930 
1931 /**
1932  * @deprecated Backwards compatibility. Use xTraceDisable instead.
1933  */
1934 #define vTraceStop (void)xTraceDisable
1935 
1936 /**
1937  * @deprecated Backwards compatibility. Use xTraceTaskInstanceFinishedNow instead.
1938  */
1939 #define vTraceInstanceFinishedNow (void)xTraceTaskInstanceFinishedNow
1940 
1941 /**
1942  * @deprecated Backwards compatibility. Use xTraceTaskInstanceFinishedNext instead.
1943  */
1944 #define vTraceInstanceFinishedNext (void)xTraceTaskInstanceFinishedNext
1945 
1946 /**
1947  * @deprecated Backwards compatibility. Use xTracePrintF instead.
1948  */
1949 #define vTracePrintF (void)xTracePrintF
1950 
1951 /**
1952  * @deprecated Backwards compatibility. Use xTraceVPrintF instead.
1953  */
1954 #define vTraceVPrintF (void)xTraceVPrintF
1955 
1956 /**
1957  * @deprecated Backwards compatibility. Use xTracePrint instead.
1958  */
1959 #define vTracePrint (void)xTracePrint
1960 
1961 /**
1962  * @deprecated Backwards compatibility. Use xTraceSetBuffer instead.
1963  */
1964 #define vTraceSetRecorderDataBuffer(pxBuffer) xTraceSetBuffer((TraceRecorderDataBuffer_t*)(pxBuffer))
1965 
1966 #ifdef __cplusplus
1967 }
1968 #endif
1969 
1970 #endif /* TRC_RECORDER_H */
1971