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 * The FreeRTOS specific parts of the trace recorder
9 */
10
11 #include <FreeRTOS.h>
12 #include <trcRecorder.h>
13
14 #if (!defined(TRC_USE_TRACEALYZER_RECORDER) && configUSE_TRACE_FACILITY == 1)
15
16 #error Trace Recorder: You need to include trcRecorder.h at the end of your FreeRTOSConfig.h!
17
18 #endif
19
20 #if (defined(TRC_USE_TRACEALYZER_RECORDER) && TRC_USE_TRACEALYZER_RECORDER == 1)
21
22 #ifndef TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS
23
24 /* TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS is missing in trcConfig.h. */
25 #error "TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS must be defined in trcConfig.h."
26
27 #endif
28
29 #ifndef TRC_CFG_INCLUDE_TIMER_EVENTS
30
31 /* TRC_CFG_INCLUDE_TIMER_EVENTS is missing in trcConfig.h. */
32 #error "TRC_CFG_INCLUDE_TIMER_EVENTS must be defined in trcConfig.h."
33
34 #endif
35
36 #ifndef TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS
37
38 /* TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS is missing in trcConfig.h. */
39 #error "TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS must be defined in trcConfig.h."
40
41 #endif
42
43 #ifndef TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS
44
45 /* TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS is missing in trcConfig.h. Define this as 1 if using FreeRTOS v10 or later and like to trace stream buffer or message buffer events, otherwise 0. */
46 #error "TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be defined in trcConfig.h."
47
48 #endif
49
50 #if (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))
51 /*
52 The below error message is to alert you on the following issue:
53
54 The hardware port selected in trcConfig.h uses the operating system timer for the
55 timestamping, i.e., the periodic interrupt timer that drives the OS tick interrupt.
56
57 When using "tickless idle" mode, the recorder needs an independent time source in
58 order to correctly record the durations of the idle times. Otherwise, the trace may appear
59 to have a different length than in reality, and the reported CPU load is also affected.
60
61 You may override this warning by defining the TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
62 macro in your trcConfig.h file. But then the time scale may be incorrect during
63 tickless idle periods.
64
65 To get this correct, override the default timestamping by setting TRC_CFG_HARDWARE_PORT
66 in trcConfig.h to TRC_HARDWARE_PORT_APPLICATION_DEFINED and define the HWTC macros
67 accordingly, using a free running counter or an independent periodic interrupt timer.
68 See trcHardwarePort.h for details.
69
70 For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the
71 DWT cycle counter for timestamping in these cases.
72 */
73
74 #ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
75 #error Trace Recorder: This timestamping mode is not recommended with Tickless Idle.
76 #endif
77
78 #endif
79
80 #include <task.h>
81 #include <queue.h>
82
83 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) || (defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0))
84
85 #if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
86
87 #if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0)
88
89 static StackType_t stackTzCtrl[TRC_CFG_CTRL_TASK_STACK_SIZE];
90 static StaticTask_t tcbTzCtrl;
91
92 #else
93
94 #error "configSUPPORT_STATIC_ALLOCATION not supported before FreeRTOS v9"
95
96 #endif
97
98 #endif
99
100 /* The TzCtrl task - receives commands from Tracealyzer (start/stop) */
101 static portTASK_FUNCTION(TzCtrl, pvParameters);
102
103 #endif
104
105 #if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X)
106
107 /* If the project does not include the FreeRTOS timers, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */
108 #include <timers.h>
109
110 #endif
111
112 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X)
113
114 /* If the project does not include the FreeRTOS event groups, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */
115 #include <event_groups.h>
116
117 #endif
118
119 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
120
121 /* If the project does not include the FreeRTOS stream buffers, TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be set to 0 */
122 #include <stream_buffer.h>
123
124 #endif
125
126 #if (TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND != TRC_ACKNOWLEDGED) && (TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_10_3_0 || TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_10_3_1) && (configUSE_QUEUE_SETS == 1)
127
128 #error "When using FreeRTOS v10.3.0 or v10.3.1, please make sure that the trace point in prvNotifyQueueSetContainer() in queue.c is renamed from traceQUEUE_SEND to traceQUEUE_SET_SEND in order to tell them apart from other traceQUEUE_SEND trace points. Then set TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND in trcConfig.h to TRC_ACKNOWLEDGED to get rid of this error."
129
130 #endif
131
132 #if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)
133
xTraceKernelPortGetUnusedStack(void * pvTask,TraceUnsignedBaseType_t * puxUnusedStack)134 traceResult xTraceKernelPortGetUnusedStack(void* pvTask, TraceUnsignedBaseType_t* puxUnusedStack)
135 {
136 *puxUnusedStack = uxTaskGetStackHighWaterMark(pvTask);
137
138 return TRC_SUCCESS;
139 }
140
141 #endif
142
xTraceKernelPortDelay(uint32_t uiTicks)143 traceResult xTraceKernelPortDelay(uint32_t uiTicks)
144 {
145 vTaskDelay(uiTicks);
146
147 return TRC_SUCCESS;
148 }
149
xTraceKernelPortIsSchedulerSuspended(void)150 unsigned char xTraceKernelPortIsSchedulerSuspended(void)
151 {
152 /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,
153 INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in
154 FreeRTOSConfig.h for this function to be available. */
155
156 return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;
157 }
158
159 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
160
161 typedef struct TraceKernelPortData
162 {
163 TraceHeapHandle_t xSystemHeapHandle;
164 TraceKernelPortTaskHandle_t xTzCtrlHandle;
165 } TraceKernelPortData_t;
166
167 static TraceKernelPortData_t* pxKernelPortData;
168
169 #define TRC_PORT_MALLOC(size) pvPortMalloc(size)
170
xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t * pxBuffer)171 traceResult xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t* pxBuffer)
172 {
173 TRC_ASSERT_EQUAL_SIZE(TraceKernelPortDataBuffer_t, TraceKernelPortData_t);
174
175 if (pxBuffer == 0)
176 {
177 return TRC_FAIL;
178 }
179
180 pxKernelPortData = (TraceKernelPortData_t*)pxBuffer;
181
182 pxKernelPortData->xSystemHeapHandle = 0;
183 pxKernelPortData->xTzCtrlHandle = 0;
184
185 return TRC_SUCCESS;
186 }
187
xTraceKernelPortEnable(void)188 traceResult xTraceKernelPortEnable(void)
189 {
190 if (pxKernelPortData->xSystemHeapHandle == 0)
191 {
192 xTraceHeapCreate("System Heap", 0, 0, configTOTAL_HEAP_SIZE, &pxKernelPortData->xSystemHeapHandle);
193 }
194
195 if (pxKernelPortData->xTzCtrlHandle == 0)
196 {
197 /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */
198 #if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
199 pxKernelPortData->xTzCtrlHandle = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);
200 #else
201 xTaskCreate(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, &pxKernelPortData->xTzCtrlHandle);
202 #endif
203
204 if (pxKernelPortData->xTzCtrlHandle == 0)
205 {
206 xTraceError(TRC_ERROR_TZCTRLTASK_NOT_CREATED);
207
208 return TRC_FAIL;
209 }
210 }
211
212 return TRC_SUCCESS;
213 }
214
portTASK_FUNCTION(TzCtrl,pvParameters)215 static portTASK_FUNCTION(TzCtrl, pvParameters)
216 {
217 (void)pvParameters;
218
219 while (1)
220 {
221 xTraceTzCtrl();
222
223 vTaskDelay(TRC_CFG_CTRL_TASK_DELAY);
224 }
225 }
226
227 #if (TRC_CFG_SCHEDULING_ONLY == 0)
228
vTraceSetQueueName(void * pvQueue,const char * szName)229 void vTraceSetQueueName(void* pvQueue, const char* szName)
230 {
231 xTraceObjectSetNameWithoutHandle(pvQueue, szName);
232 }
233
vTraceSetSemaphoreName(void * pvSemaphore,const char * szName)234 void vTraceSetSemaphoreName(void* pvSemaphore, const char* szName)
235 {
236 xTraceObjectSetNameWithoutHandle(pvSemaphore, szName);
237 }
238
vTraceSetMutexName(void * pvMutex,const char * szName)239 void vTraceSetMutexName(void* pvMutex, const char* szName)
240 {
241 xTraceObjectSetNameWithoutHandle(pvMutex, szName);
242 }
243
244 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X)
245
vTraceSetEventGroupName(void * pvEventGroup,const char * szName)246 void vTraceSetEventGroupName(void* pvEventGroup, const char* szName)
247 {
248 xTraceObjectSetNameWithoutHandle(pvEventGroup, szName);
249 }
250
251 #endif
252
253 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
254
vTraceSetStreamBufferName(void * pvStreamBuffer,const char * szName)255 void vTraceSetStreamBufferName(void* pvStreamBuffer, const char* szName)
256 {
257 xTraceObjectSetNameWithoutHandle(pvStreamBuffer, szName);
258 }
259
vTraceSetMessageBufferName(void * pvMessageBuffer,const char * szName)260 void vTraceSetMessageBufferName(void* pvMessageBuffer, const char* szName)
261 {
262 xTraceObjectSetNameWithoutHandle(pvMessageBuffer, szName);
263 }
264
265 #endif
266
267 #endif
268
xTraceKernelPortGetSystemHeapHandle(void)269 TraceHeapHandle_t xTraceKernelPortGetSystemHeapHandle(void)
270 {
271 return pxKernelPortData->xSystemHeapHandle;
272 }
273
274 #endif
275
276 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
277
278 uint32_t prvTraceGetQueueNumber(void* handle);
279
280 #if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X_X)
281
282 extern unsigned char ucQueueGetQueueNumber(xQueueHandle pxQueue);
283 extern void vQueueSetQueueNumber(xQueueHandle pxQueue, unsigned char ucQueueNumber);
284 extern unsigned char ucQueueGetQueueType(xQueueHandle pxQueue);
285
prvTraceGetQueueNumber(void * handle)286 uint32_t prvTraceGetQueueNumber(void* handle)
287 {
288 return (uint32_t)ucQueueGetQueueNumber(handle);
289 }
290
291 #else
292
prvTraceGetQueueNumber(void * handle)293 uint32_t prvTraceGetQueueNumber(void* handle)
294 {
295 return (uint32_t)uxQueueGetQueueNumber(handle);
296 }
297
298 #endif
299
prvTraceGetQueueType(void * pvQueue)300 uint8_t prvTraceGetQueueType(void* pvQueue)
301 {
302 // This is either declared in header file in FreeRTOS 8 and later, or as extern above
303 return ucQueueGetQueueType(pvQueue);
304 }
305
306 /* Tasks */
prvTraceGetTaskNumberLow16(void * pvTask)307 uint16_t prvTraceGetTaskNumberLow16(void* pvTask)
308 {
309 return TRACE_GET_LOW16(uxTaskGetTaskNumber(pvTask));
310 }
311
prvTraceGetTaskNumberHigh16(void * pvTask)312 uint16_t prvTraceGetTaskNumberHigh16(void* pvTask)
313 {
314 return TRACE_GET_HIGH16(uxTaskGetTaskNumber(pvTask));
315 }
316
prvTraceSetTaskNumberLow16(void * pvTask,uint16_t uiValue)317 void prvTraceSetTaskNumberLow16(void* pvTask, uint16_t uiValue)
318 {
319 vTaskSetTaskNumber(pvTask, TRACE_SET_LOW16(uxTaskGetTaskNumber(pvTask), uiValue));
320 }
321
prvTraceSetTaskNumberHigh16(void * pvTask,uint16_t uiValue)322 void prvTraceSetTaskNumberHigh16(void* pvTask, uint16_t uiValue)
323 {
324 vTaskSetTaskNumber(pvTask, TRACE_SET_HIGH16(uxTaskGetTaskNumber(pvTask), uiValue));
325 }
326
prvTraceGetQueueNumberLow16(void * pvQueue)327 uint16_t prvTraceGetQueueNumberLow16(void* pvQueue)
328 {
329 return TRACE_GET_LOW16(prvTraceGetQueueNumber(pvQueue));
330 }
331
prvTraceGetQueueNumberHigh16(void * pvQueue)332 uint16_t prvTraceGetQueueNumberHigh16(void* pvQueue)
333 {
334 return TRACE_GET_HIGH16(prvTraceGetQueueNumber(pvQueue));
335 }
336
prvTraceSetQueueNumberLow16(void * pvQueue,uint16_t uiValue)337 void prvTraceSetQueueNumberLow16(void* pvQueue, uint16_t uiValue)
338 {
339 vQueueSetQueueNumber(pvQueue, TRACE_SET_LOW16(prvTraceGetQueueNumber(pvQueue), uiValue));
340 }
341
prvTraceSetQueueNumberHigh16(void * pvQueue,uint16_t uiValue)342 void prvTraceSetQueueNumberHigh16(void* pvQueue, uint16_t uiValue)
343 {
344 vQueueSetQueueNumber(pvQueue, TRACE_SET_HIGH16(prvTraceGetQueueNumber(pvQueue), uiValue));
345 }
346
347 #if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
348
prvTraceGetTimerNumberLow16(void * pvTimer)349 uint16_t prvTraceGetTimerNumberLow16(void* pvTimer)
350 {
351 return TRACE_GET_LOW16(uxTimerGetTimerNumber(pvTimer));
352 }
353
prvTraceGetTimerNumberHigh16(void * pvTimer)354 uint16_t prvTraceGetTimerNumberHigh16(void* pvTimer)
355 {
356 return TRACE_GET_HIGH16(uxTimerGetTimerNumber(pvTimer));
357 }
358
prvTraceSetTimerNumberLow16(void * pvTimer,uint16_t uiValue)359 void prvTraceSetTimerNumberLow16(void* pvTimer, uint16_t uiValue)
360 {
361 vTimerSetTimerNumber(pvTimer, TRACE_SET_LOW16(uxTimerGetTimerNumber(pvTimer), uiValue));
362 }
363
prvTraceSetTimerNumberHigh16(void * pvTimer,uint16_t uiValue)364 void prvTraceSetTimerNumberHigh16(void* pvTimer, uint16_t uiValue)
365 {
366 vTimerSetTimerNumber(pvTimer, TRACE_SET_HIGH16(uxTimerGetTimerNumber(pvTimer), uiValue));
367 }
368
369 #endif
370
371 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
372
prvTraceGetEventGroupNumberLow16(void * pvEventGroup)373 uint16_t prvTraceGetEventGroupNumberLow16(void* pvEventGroup)
374 {
375 return TRACE_GET_LOW16(uxEventGroupGetNumber(pvEventGroup));
376 }
377
prvTraceGetEventGroupNumberHigh16(void * pvEventGroup)378 uint16_t prvTraceGetEventGroupNumberHigh16(void* pvEventGroup)
379 {
380 return TRACE_GET_HIGH16(uxEventGroupGetNumber(pvEventGroup));
381 }
382
prvTraceSetEventGroupNumberLow16(void * pvEventGroup,uint16_t uiValue)383 void prvTraceSetEventGroupNumberLow16(void* pvEventGroup, uint16_t uiValue)
384 {
385 vEventGroupSetNumber(pvEventGroup, TRACE_SET_LOW16(uxEventGroupGetNumber(pvEventGroup), uiValue));
386 }
387
prvTraceSetEventGroupNumberHigh16(void * pvEventGroup,uint16_t uiValue)388 void prvTraceSetEventGroupNumberHigh16(void* pvEventGroup, uint16_t uiValue)
389 {
390 vEventGroupSetNumber(pvEventGroup, TRACE_SET_HIGH16(uxEventGroupGetNumber(pvEventGroup), uiValue));
391 }
392
393 #endif
394
395 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
396
prvTraceGetStreamBufferNumberLow16(void * pvStreamBuffer)397 uint16_t prvTraceGetStreamBufferNumberLow16(void* pvStreamBuffer)
398 {
399 return TRACE_GET_LOW16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer));
400 }
401
prvTraceGetStreamBufferNumberHigh16(void * pvStreamBuffer)402 uint16_t prvTraceGetStreamBufferNumberHigh16(void* pvStreamBuffer)
403 {
404 return TRACE_GET_HIGH16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer));
405 }
406
prvTraceSetStreamBufferNumberLow16(void * pvStreamBuffer,uint16_t uiValue)407 void prvTraceSetStreamBufferNumberLow16(void* pvStreamBuffer, uint16_t uiValue)
408 {
409 vStreamBufferSetStreamBufferNumber(pvStreamBuffer, TRACE_SET_LOW16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer), uiValue));
410 }
411
prvTraceSetStreamBufferNumberHigh16(void * pvStreamBuffer,uint16_t uiValue)412 void prvTraceSetStreamBufferNumberHigh16(void* pvStreamBuffer, uint16_t uiValue)
413 {
414 vStreamBufferSetStreamBufferNumber(pvStreamBuffer, TRACE_SET_HIGH16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer), uiValue));
415 }
416
417 #endif
418
419 static TraceKernelPortTaskHandle_t xTzCtrlHandle = 0; /* TzCtrl task TCB */
420
421 /* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */
422 int uiInEventGroupSetBitsFromISR = 0;
423
424 /**
425 * @internal Class reference table
426 */
427 traceObjectClass TraceQueueClassTable[5] = {
428 TRACE_CLASS_QUEUE,
429 TRACE_CLASS_MUTEX,
430 TRACE_CLASS_SEMAPHORE,
431 TRACE_CLASS_SEMAPHORE,
432 TRACE_CLASS_MUTEX
433 };
434
435 #if (TRC_CFG_SCHEDULING_ONLY == 0)
436
vTraceSetQueueName(void * pvQueue,const char * szName)437 void vTraceSetQueueName(void* pvQueue, const char* szName)
438 {
439 prvTraceSetObjectName(TRACE_CLASS_QUEUE, TRACE_GET_OBJECT_NUMBER(QUEUE, pvQueue), szName);
440 }
441
vTraceSetSemaphoreName(void * pvSemaphore,const char * szName)442 void vTraceSetSemaphoreName(void* pvSemaphore, const char* szName)
443 {
444 prvTraceSetObjectName(TRACE_CLASS_SEMAPHORE, TRACE_GET_OBJECT_NUMBER(QUEUE, pvSemaphore), szName);
445 }
446
vTraceSetMutexName(void * pvMutex,const char * szName)447 void vTraceSetMutexName(void* pvMutex, const char* szName)
448 {
449 prvTraceSetObjectName(TRACE_CLASS_MUTEX, TRACE_GET_OBJECT_NUMBER(QUEUE, pvMutex), szName);
450 }
451
452 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X)
453
vTraceSetEventGroupName(void * pvEventGroup,const char * szName)454 void vTraceSetEventGroupName(void* pvEventGroup, const char* szName)
455 {
456 prvTraceSetObjectName(TRACE_CLASS_EVENTGROUP, TRACE_GET_OBJECT_NUMBER(EVENTGROUP, pvEventGroup), szName);
457 }
458
459 #endif
460
461 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
462
vTraceSetStreamBufferName(void * pvStreamBuffer,const char * szName)463 void vTraceSetStreamBufferName(void* pvStreamBuffer, const char* szName)
464 {
465 prvTraceSetObjectName(TRACE_CLASS_STREAMBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, pvStreamBuffer), szName);
466 }
467
vTraceSetMessageBufferName(void * pvStreamBuffer,const char * szName)468 void vTraceSetMessageBufferName(void* pvStreamBuffer, const char* szName)
469 {
470 prvTraceSetObjectName(TRACE_CLASS_MESSAGEBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, pvStreamBuffer), szName);
471 }
472
473 #endif
474
475 #endif
476
prvTraceGetCurrentTaskHandle()477 void* prvTraceGetCurrentTaskHandle()
478 {
479 return xTaskGetCurrentTaskHandle();
480 }
481
xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t * pxBuffer)482 traceResult xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t* pxBuffer)
483 {
484 (void)pxBuffer;
485
486 return TRC_SUCCESS;
487 }
488
xTraceKernelPortEnable(void)489 traceResult xTraceKernelPortEnable(void)
490 {
491 #if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)
492
493 if (xTzCtrlHandle == 0)
494 {
495 #if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
496
497 xTzCtrlHandle = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);
498
499 #else
500
501 xTaskCreate(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, &xTzCtrlHandle);
502
503 #endif
504 }
505
506 #else
507
508 (void)xTzCtrlHandle;
509
510 #endif
511
512 return TRC_SUCCESS;
513 }
514
515 #if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)
516
portTASK_FUNCTION(TzCtrl,pvParameters)517 static portTASK_FUNCTION(TzCtrl, pvParameters)
518 {
519 (void)pvParameters;
520
521 while (1)
522 {
523 if (xTraceIsRecorderEnabled())
524 {
525 prvReportStackUsage();
526 }
527
528 vTaskDelay(TRC_CFG_CTRL_TASK_DELAY);
529 }
530 }
531
532 #endif
533
xTraceKernelPortInitObjectPropertyTable()534 traceResult xTraceKernelPortInitObjectPropertyTable()
535 {
536 RecorderDataPtr->ObjectPropertyTable.NumberOfObjectClasses = TRACE_NCLASSES;
537 RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[0] = TRC_CFG_NQUEUE;
538 RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[1] = TRC_CFG_NSEMAPHORE;
539 RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = TRC_CFG_NMUTEX;
540 RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = TRC_CFG_NTASK;
541 RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = TRC_CFG_NISR;
542 RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = TRC_CFG_NTIMER;
543 RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = TRC_CFG_NEVENTGROUP;
544 RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[7] = TRC_CFG_NSTREAMBUFFER;
545 RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[8] = TRC_CFG_NMESSAGEBUFFER;
546 RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = TRC_CFG_NAME_LEN_QUEUE;
547 RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = TRC_CFG_NAME_LEN_SEMAPHORE;
548 RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = TRC_CFG_NAME_LEN_MUTEX;
549 RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = TRC_CFG_NAME_LEN_TASK;
550 RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = TRC_CFG_NAME_LEN_ISR;
551 RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = TRC_CFG_NAME_LEN_TIMER;
552 RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = TRC_CFG_NAME_LEN_EVENTGROUP;
553 RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[7] = TRC_CFG_NAME_LEN_STREAMBUFFER;
554 RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[8] = TRC_CFG_NAME_LEN_MESSAGEBUFFER;
555 RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;
556 RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;
557 RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;
558 RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[3] = PropertyTableSizeTask;
559 RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;
560 RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[5] = PropertyTableSizeTimer;
561 RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[6] = PropertyTableSizeEventGroup;
562 RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[7] = PropertyTableSizeStreamBuffer;
563 RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[8] = PropertyTableSizeMessageBuffer;
564 RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;
565 RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;
566 RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;
567 RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[3] = StartIndexTask;
568 RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;
569 RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[5] = StartIndexTimer;
570 RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[6] = StartIndexEventGroup;
571 RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[7] = StartIndexStreamBuffer;
572 RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[8] = StartIndexMessageBuffer;
573 RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;
574
575 return TRC_SUCCESS;
576 }
577
xTraceKernelPortInitObjectHandleStack()578 traceResult xTraceKernelPortInitObjectHandleStack()
579 {
580 uint32_t i = 0;
581
582 objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0;
583 objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = (TRC_CFG_NQUEUE);
584 objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE);
585 objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX);
586 objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK);
587 objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR);
588 objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER);
589 objectHandleStacks.indexOfNextAvailableHandle[7] = objectHandleStacks.lowestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP);
590 objectHandleStacks.indexOfNextAvailableHandle[8] = objectHandleStacks.lowestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER);
591
592 objectHandleStacks.highestIndexOfClass[0] = (TRC_CFG_NQUEUE) - 1;
593 objectHandleStacks.highestIndexOfClass[1] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) - 1;
594 objectHandleStacks.highestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) - 1;
595 objectHandleStacks.highestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) - 1;
596 objectHandleStacks.highestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) - 1;
597 objectHandleStacks.highestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) - 1;
598 objectHandleStacks.highestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) - 1;
599 objectHandleStacks.highestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) - 1;
600 objectHandleStacks.highestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) + (TRC_CFG_NMESSAGEBUFFER) - 1;
601
602 for (i = 0; i < TRACE_NCLASSES; i++)
603 {
604 objectHandleStacks.handleCountWaterMarksOfClass[i] = 0;
605 }
606
607 for (i = 0; i < TRACE_KERNEL_OBJECT_COUNT; i++)
608 {
609 objectHandleStacks.objectHandles[i] = 0;
610 }
611
612 return TRC_SUCCESS;
613 }
614
pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)615 const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)
616 {
617 switch(objectclass)
618 {
619 case TRACE_CLASS_TASK:
620 return "Not enough TASK handles - increase TRC_CFG_NTASK in trcSnapshotConfig.h";
621 case TRACE_CLASS_ISR:
622 return "Not enough ISR handles - increase TRC_CFG_NISR in trcSnapshotConfig.h";
623 case TRACE_CLASS_SEMAPHORE:
624 return "Not enough SEMAPHORE handles - increase TRC_CFG_NSEMAPHORE in trcSnapshotConfig.h";
625 case TRACE_CLASS_MUTEX:
626 return "Not enough MUTEX handles - increase TRC_CFG_NMUTEX in trcSnapshotConfig.h";
627 case TRACE_CLASS_QUEUE:
628 return "Not enough QUEUE handles - increase TRC_CFG_NQUEUE in trcSnapshotConfig.h";
629 case TRACE_CLASS_TIMER:
630 return "Not enough TIMER handles - increase TRC_CFG_NTIMER in trcSnapshotConfig.h";
631 case TRACE_CLASS_EVENTGROUP:
632 return "Not enough EVENTGROUP handles - increase TRC_CFG_NEVENTGROUP in trcSnapshotConfig.h";
633 case TRACE_CLASS_STREAMBUFFER:
634 return "Not enough STREAMBUFFER handles - increase TRC_CFG_NSTREAMBUFFER in trcSnapshotConfig.h";
635 case TRACE_CLASS_MESSAGEBUFFER:
636 return "Not enough MESSAGEBUFFER handles - increase TRC_CFG_NMESSAGEBUFFER in trcSnapshotConfig.h";
637 default:
638 return "pszTraceGetErrorHandles: Invalid objectclass!";
639 }
640 }
641
642 #endif
643
644 #endif
645