]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c
Update trace recorder code to the latest.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-Trace / trcKernelPort.c
1 /*******************************************************************************\r
2  * Trace Recorder Library for Tracealyzer v4.1.5\r
3  * Percepio AB, www.percepio.com\r
4  *\r
5  * trcKernelPort.c\r
6  *\r
7  * The FreeRTOS-specific parts of the trace recorder\r
8  *\r
9  * Terms of Use\r
10  * This file is part of the trace recorder library (RECORDER), which is the \r
11  * intellectual property of Percepio AB (PERCEPIO) and provided under a\r
12  * license as follows.\r
13  * The RECORDER may be used free of charge for the purpose of recording data\r
14  * intended for analysis in PERCEPIO products. It may not be used or modified\r
15  * for other purposes without explicit permission from PERCEPIO.\r
16  * You may distribute the RECORDER in its original source code form, assuming\r
17  * this text (terms of use, disclaimer, copyright notice) is unchanged. You are\r
18  * allowed to distribute the RECORDER with minor modifications intended for\r
19  * configuration or porting of the RECORDER, e.g., to allow using it on a \r
20  * specific processor, processor family or with a specific communication\r
21  * interface. Any such modifications should be documented directly below\r
22  * this comment block.  \r
23  *\r
24  * Disclaimer\r
25  * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty\r
26  * as to its use or performance. PERCEPIO does not and cannot warrant the \r
27  * performance or results you may obtain by using the RECORDER or documentation.\r
28  * PERCEPIO make no warranties, express or implied, as to noninfringement of\r
29  * third party rights, merchantability, or fitness for any particular purpose.\r
30  * In no event will PERCEPIO, its technology partners, or distributors be liable\r
31  * to you for any consequential, incidental or special damages, including any\r
32  * lost profits or lost savings, even if a representative of PERCEPIO has been\r
33  * advised of the possibility of such damages, or for any claim by any third\r
34  * party. Some jurisdictions do not allow the exclusion or limitation of\r
35  * incidental, consequential or special damages, or the exclusion of implied\r
36  * warranties or limitations on how long an implied warranty may last, so the\r
37  * above limitations may not apply to you.\r
38  *\r
39  * Tabs are used for indent in this file (1 tab = 4 spaces)\r
40  *\r
41  * Copyright Percepio AB, 2018.\r
42  * www.percepio.com\r
43  ******************************************************************************/\r
44 \r
45 #include "FreeRTOS.h"\r
46 \r
47 #if (!defined(TRC_USE_TRACEALYZER_RECORDER) && configUSE_TRACE_FACILITY == 1)\r
48 #error Trace Recorder: You need to include trcRecorder.h at the end of your FreeRTOSConfig.h!\r
49 #endif\r
50 \r
51 #if (defined(TRC_USE_TRACEALYZER_RECORDER) && TRC_USE_TRACEALYZER_RECORDER == 1)\r
52 \r
53 #ifndef TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS\r
54  /* TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS is missing in trcConfig.h. */\r
55 #error "TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS must be defined in trcConfig.h."\r
56 #endif\r
57 \r
58 #ifndef TRC_CFG_INCLUDE_TIMER_EVENTS\r
59  /* TRC_CFG_INCLUDE_TIMER_EVENTS is missing in trcConfig.h. */\r
60 #error "TRC_CFG_INCLUDE_TIMER_EVENTS must be defined in trcConfig.h."\r
61 #endif\r
62 \r
63 #ifndef TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS\r
64  /* TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS is missing in trcConfig.h. */\r
65 #error "TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS must be defined in trcConfig.h."\r
66 #endif\r
67 \r
68 #ifndef TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS\r
69  /* 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. */\r
70 #error "TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be defined in trcConfig.h."\r
71 #endif\r
72 \r
73 #if (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))\r
74         /*      \r
75                 The below error message is to alert you on the following issue:\r
76                 \r
77                 The hardware port selected in trcConfig.h uses the operating system timer for the \r
78                 timestamping, i.e., the periodic interrupt timer that drives the OS tick interrupt.\r
79                                 \r
80                 When using "tickless idle" mode, the recorder needs an independent time source in\r
81                 order to correctly record the durations of the idle times. Otherwise, the trace may appear\r
82                 to have a different length than in reality, and the reported CPU load is also affected.\r
83                 \r
84                 You may override this warning by defining the TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING\r
85                 macro in your trcConfig.h file. But then the time scale may be incorrect during\r
86                 tickless idle periods.\r
87                 \r
88                 To get this correct, override the default timestamping by setting TRC_CFG_HARDWARE_PORT\r
89                 in trcConfig.h to TRC_HARDWARE_PORT_APPLICATION_DEFINED and define the HWTC macros\r
90                 accordingly, using a free running counter or an independent periodic interrupt timer.\r
91                 See trcHardwarePort.h for details.\r
92                                 \r
93                 For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the \r
94                 DWT cycle counter for timestamping in these cases.              \r
95         */\r
96         \r
97         #ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING\r
98         #error Trace Recorder: This timestamping mode is not recommended with Tickless Idle.\r
99         #endif\r
100 #endif /* (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)) */\r
101         \r
102 #include "task.h"\r
103 #include "queue.h"\r
104 \r
105 #if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)\r
106 /* If the project does not include the FreeRTOS timers, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */\r
107 #include "timers.h"\r
108 #endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */\r
109 \r
110 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)\r
111 /* If the project does not include the FreeRTOS event groups, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */\r
112 #include "event_groups.h"\r
113 #endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */\r
114 \r
115 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)\r
116 /* If the project does not include the FreeRTOS stream buffers, TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be set to 0 */\r
117 #include "stream_buffer.h"\r
118 #endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */\r
119 \r
120 uint32_t prvTraceGetQueueNumber(void* handle);\r
121 \r
122 #if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X)\r
123 \r
124 extern unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue );\r
125 extern void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber );\r
126 extern unsigned char ucQueueGetQueueType( xQueueHandle pxQueue );\r
127 \r
128 uint32_t prvTraceGetQueueNumber(void* handle)\r
129 {\r
130         return (uint32_t)ucQueueGetQueueNumber(handle);\r
131 }\r
132 #else \r
133 uint32_t prvTraceGetQueueNumber(void* handle)\r
134 {\r
135         return (uint32_t)uxQueueGetQueueNumber(handle);\r
136 }\r
137 #endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X) */\r
138 \r
139 uint8_t prvTraceGetQueueType(void* handle)\r
140 {\r
141         // This is either declared in header file in FreeRTOS 8 and later, or as extern above\r
142         return ucQueueGetQueueType(handle);\r
143 }\r
144 \r
145 /* Tasks */\r
146 uint16_t prvTraceGetTaskNumberLow16(void* handle)\r
147 {\r
148         return TRACE_GET_LOW16(uxTaskGetTaskNumber(handle));\r
149 }\r
150 \r
151 uint16_t prvTraceGetTaskNumberHigh16(void* handle)\r
152 {\r
153         return TRACE_GET_HIGH16(uxTaskGetTaskNumber(handle));\r
154 }\r
155 \r
156 void prvTraceSetTaskNumberLow16(void* handle, uint16_t value)\r
157 {\r
158         vTaskSetTaskNumber(handle, TRACE_SET_LOW16(uxTaskGetTaskNumber(handle), value));\r
159 }\r
160 \r
161 void prvTraceSetTaskNumberHigh16(void* handle, uint16_t value)\r
162 {\r
163         vTaskSetTaskNumber(handle, TRACE_SET_HIGH16(uxTaskGetTaskNumber(handle), value));\r
164 }\r
165 \r
166 uint16_t prvTraceGetQueueNumberLow16(void* handle)\r
167 {\r
168         return TRACE_GET_LOW16(prvTraceGetQueueNumber(handle));\r
169 }\r
170 \r
171 uint16_t prvTraceGetQueueNumberHigh16(void* handle)\r
172 {\r
173         return TRACE_GET_HIGH16(prvTraceGetQueueNumber(handle));\r
174 }\r
175 \r
176 void prvTraceSetQueueNumberLow16(void* handle, uint16_t value)\r
177 {\r
178         vQueueSetQueueNumber(handle, TRACE_SET_LOW16(prvTraceGetQueueNumber(handle), value));\r
179 }\r
180 \r
181 void prvTraceSetQueueNumberHigh16(void* handle, uint16_t value)\r
182 {\r
183         vQueueSetQueueNumber(handle, TRACE_SET_HIGH16(prvTraceGetQueueNumber(handle), value));\r
184 }\r
185 \r
186 #if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)\r
187 \r
188 uint16_t prvTraceGetTimerNumberLow16(void* handle)\r
189 {\r
190         return TRACE_GET_LOW16(uxTimerGetTimerNumber(handle));\r
191 }\r
192 \r
193 uint16_t prvTraceGetTimerNumberHigh16(void* handle)\r
194 {\r
195         return TRACE_GET_HIGH16(uxTimerGetTimerNumber(handle));\r
196 }\r
197 \r
198 void prvTraceSetTimerNumberLow16(void* handle, uint16_t value)\r
199 {\r
200         vTimerSetTimerNumber(handle, TRACE_SET_LOW16(uxTimerGetTimerNumber(handle), value));\r
201 }\r
202 \r
203 void prvTraceSetTimerNumberHigh16(void* handle, uint16_t value)\r
204 {\r
205         vTimerSetTimerNumber(handle, TRACE_SET_HIGH16(uxTimerGetTimerNumber(handle), value));\r
206 }\r
207 #endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */\r
208 \r
209 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)\r
210 \r
211 uint16_t prvTraceGetEventGroupNumberLow16(void* handle)\r
212 {\r
213         return TRACE_GET_LOW16(uxEventGroupGetNumber(handle));\r
214 }\r
215 \r
216 uint16_t prvTraceGetEventGroupNumberHigh16(void* handle)\r
217 {\r
218         return TRACE_GET_HIGH16(uxEventGroupGetNumber(handle));\r
219 }\r
220 \r
221 void prvTraceSetEventGroupNumberLow16(void* handle, uint16_t value)\r
222 {\r
223         vEventGroupSetNumber(handle, TRACE_SET_LOW16(uxEventGroupGetNumber(handle), value));\r
224 }\r
225 \r
226 void prvTraceSetEventGroupNumberHigh16(void* handle, uint16_t value)\r
227 {\r
228         vEventGroupSetNumber(handle, TRACE_SET_HIGH16(uxEventGroupGetNumber(handle), value));\r
229 }\r
230 #endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */\r
231 \r
232 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)\r
233 \r
234 uint16_t prvTraceGetStreamBufferNumberLow16(void* handle)\r
235 {\r
236         return TRACE_GET_LOW16(uxStreamBufferGetStreamBufferNumber(handle));\r
237 }\r
238 \r
239 uint16_t prvTraceGetStreamBufferNumberHigh16(void* handle)\r
240 {\r
241         return TRACE_GET_HIGH16(uxStreamBufferGetStreamBufferNumber(handle));\r
242 }\r
243 \r
244 void prvTraceSetStreamBufferNumberLow16(void* handle, uint16_t value)\r
245 {\r
246         vStreamBufferSetStreamBufferNumber(handle, TRACE_SET_LOW16(uxStreamBufferGetStreamBufferNumber(handle), value));\r
247 }\r
248 \r
249 void prvTraceSetStreamBufferNumberHigh16(void* handle, uint16_t value)\r
250 {\r
251         vStreamBufferSetStreamBufferNumber(handle, TRACE_SET_HIGH16(uxStreamBufferGetStreamBufferNumber(handle), value));\r
252 }\r
253 #endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */\r
254 \r
255 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)\r
256         \r
257 static void* pCurrentTCB = NULL;\r
258 #if (defined(configENABLE_BACKWARD_COMPATIBILITY) && configENABLE_BACKWARD_COMPATIBILITY == 0)\r
259 /* We're explicitly not using compatibility mode */\r
260 static TaskHandle_t HandleTzCtrl = NULL;       /* TzCtrl task TCB */\r
261 #else\r
262 /* We're using compatibility mode, or we're running an old kernel */\r
263 static xTaskHandle HandleTzCtrl = NULL;       /* TzCtrl task TCB */\r
264 #endif\r
265 \r
266 #if defined(configSUPPORT_STATIC_ALLOCATION)\r
267 #if (configSUPPORT_STATIC_ALLOCATION == 1)\r
268 static StackType_t stackTzCtrl[TRC_CFG_CTRL_TASK_STACK_SIZE];\r
269 static StaticTask_t tcbTzCtrl;\r
270 #endif\r
271 #endif\r
272 \r
273 /* Monitored by TzCtrl task, that give warnings as User Events */\r
274 extern volatile uint32_t NoRoomForSymbol;\r
275 extern volatile uint32_t NoRoomForObjectData;\r
276 extern volatile uint32_t LongestSymbolName;\r
277 extern volatile uint32_t MaxBytesTruncated;\r
278 \r
279 /* Keeps track of previous values, to only react on changes. */\r
280 static uint32_t NoRoomForSymbol_last = 0;\r
281 static uint32_t NoRoomForObjectData_last = 0;\r
282 static uint32_t LongestSymbolName_last = 0;\r
283 static uint32_t MaxBytesTruncated_last = 0;\r
284 \r
285 /* User Event Channel for giving warnings regarding NoRoomForSymbol etc. */\r
286 traceString trcWarningChannel;\r
287 \r
288 #define TRC_PORT_MALLOC(size) pvPortMalloc(size)\r
289 \r
290 TRC_STREAM_PORT_ALLOCATE_FIELDS()\r
291 \r
292 /* Called by TzCtrl task periodically (Normally every 100 ms) */\r
293 static void prvCheckRecorderStatus(void);\r
294 \r
295 extern void prvTraceWarning(int errCode);\r
296 \r
297 /* The TzCtrl task - receives commands from Tracealyzer (start/stop) */\r
298 static portTASK_FUNCTION( TzCtrl, pvParameters );\r
299 \r
300 /*******************************************************************************\r
301  * vTraceEnable\r
302  *\r
303  * Function that enables the tracing and creates the control task. It will halt\r
304  * execution until a Start command has been received if haltUntilStart is true.\r
305  *\r
306  ******************************************************************************/\r
307 void vTraceEnable(int startOption)\r
308 {\r
309         int32_t bytes = 0;\r
310         int32_t status;\r
311         extern uint32_t RecorderEnabled;\r
312         TracealyzerCommandType msg;\r
313 \r
314         /* Only do this first time...*/\r
315         if (HandleTzCtrl == NULL)\r
316         {\r
317                 TRC_STREAM_PORT_INIT();\r
318                 \r
319                 /* Note: Requires that TRC_CFG_INCLUDE_USER_EVENTS is 1. */\r
320                 trcWarningChannel = xTraceRegisterString("Warnings from Recorder");\r
321 \r
322                 /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */\r
323                 #if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)\r
324                 HandleTzCtrl = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);\r
325                 #else\r
326                 xTaskCreate( TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl );\r
327                 #endif\r
328 \r
329                 if (HandleTzCtrl == NULL)\r
330                 {\r
331                         prvTraceError(PSF_ERROR_TZCTRLTASK_NOT_CREATED);\r
332                 }\r
333         }\r
334 \r
335         if (startOption == TRC_START_AWAIT_HOST)\r
336         {\r
337                 /* We keep trying to read commands until the recorder has been started */\r
338                 do\r
339                 {\r
340                         bytes = 0;\r
341                         \r
342                         status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes);\r
343                         \r
344                         if (status != 0)\r
345                         {\r
346                                 prvTraceWarning(PSF_WARNING_STREAM_PORT_READ);\r
347                         }\r
348 \r
349                         if ((status == 0) && (bytes == sizeof(TracealyzerCommandType)))\r
350                         {\r
351                                 if (prvIsValidCommand(&msg))\r
352                                 {\r
353                                         if (msg.cmdCode == CMD_SET_ACTIVE && msg.param1 == 1)\r
354                                         {\r
355                                                 /* On start, init and reset the timestamping */\r
356                                                 TRC_PORT_SPECIFIC_INIT();\r
357                                         }\r
358                                         \r
359                                         prvProcessCommand(&msg);\r
360                                 }\r
361                         }\r
362                 }\r
363                 while (RecorderEnabled == 0);\r
364         }\r
365         else if (startOption == TRC_START)\r
366         {\r
367                 /* We start streaming directly - this assumes that the interface is ready! */\r
368                 TRC_PORT_SPECIFIC_INIT();\r
369                 \r
370                 msg.cmdCode = CMD_SET_ACTIVE;\r
371                 msg.param1 = 1;\r
372                 prvProcessCommand(&msg);\r
373         }\r
374         else\r
375         {\r
376                 /* On TRC_INIT */\r
377                 TRC_PORT_SPECIFIC_INIT();\r
378         }\r
379 }\r
380 \r
381 #if (TRC_CFG_SCHEDULING_ONLY == 0)\r
382 /*******************************************************************************\r
383  * vTraceSetQueueName(void* object, const char* name)\r
384  *\r
385  * Parameter object: pointer to the Queue that shall be named\r
386  * Parameter name: the name to set (const string literal)\r
387  *\r
388  * Sets a name for Queue objects for display in Tracealyzer.\r
389  ******************************************************************************/\r
390 void vTraceSetQueueName(void* object, const char* name)\r
391 {\r
392         vTraceStoreKernelObjectName(object, name);\r
393 }\r
394 \r
395 /*******************************************************************************\r
396  * vTraceSetSemaphoreName(void* object, const char* name)\r
397  *\r
398  * Parameter object: pointer to the Semaphore that shall be named\r
399  * Parameter name: the name to set (const string literal)\r
400  *\r
401  * Sets a name for Semaphore objects for display in Tracealyzer.\r
402  ******************************************************************************/\r
403 void vTraceSetSemaphoreName(void* object, const char* name)\r
404 {\r
405         vTraceStoreKernelObjectName(object, name);\r
406 }\r
407 \r
408 /*******************************************************************************\r
409  * vTraceSetMutexName(void* object, const char* name)\r
410  *\r
411  * Parameter object: pointer to the Mutex that shall be named\r
412  * Parameter name: the name to set (const string literal)\r
413  *\r
414  * Sets a name for Mutex objects for display in Tracealyzer.\r
415  ******************************************************************************/\r
416 void vTraceSetMutexName(void* object, const char* name)\r
417 {\r
418         vTraceStoreKernelObjectName(object, name);\r
419 }\r
420 \r
421 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)\r
422 /*******************************************************************************\r
423 * vTraceSetEventGroupName(void* object, const char* name)\r
424 *\r
425 * Parameter object: pointer to the vTraceSetEventGroupName that shall be named\r
426 * Parameter name: the name to set (const string literal)\r
427 *\r
428 * Sets a name for EventGroup objects for display in Tracealyzer.\r
429 ******************************************************************************/\r
430 void vTraceSetEventGroupName(void* object, const char* name)\r
431 {\r
432         vTraceStoreKernelObjectName(object, name);\r
433 }\r
434 #endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */\r
435 \r
436 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)\r
437 /*******************************************************************************\r
438 * vTraceSetStreamBufferName(void* object, const char* name)\r
439 *\r
440 * Parameter object: pointer to the StreamBuffer that shall be named\r
441 * Parameter name: the name to set (const string literal)\r
442 *\r
443 * Sets a name for StreamBuffer objects for display in Tracealyzer.\r
444 ******************************************************************************/\r
445 void vTraceSetStreamBufferName(void* object, const char* name)\r
446 {\r
447         vTraceStoreKernelObjectName(object, name);\r
448 }\r
449 \r
450 /*******************************************************************************\r
451 * vTraceSetMessageBufferName(void* object, const char* name)\r
452 *\r
453 * Parameter object: pointer to the MessageBuffer that shall be named\r
454 * Parameter name: the name to set (const string literal)\r
455 *\r
456 * Sets a name for MessageBuffer objects for display in Tracealyzer.\r
457 ******************************************************************************/\r
458 void vTraceSetMessageBufferName(void* object, const char* name)\r
459 {\r
460         vTraceStoreKernelObjectName(object, name);\r
461 }\r
462 #endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */\r
463 \r
464 #endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */\r
465 \r
466 /*******************************************************************************\r
467  * prvGetCurrentTaskHandle\r
468  *\r
469  * Function that returns the handle to the currently executing task.\r
470  *\r
471  ******************************************************************************/\r
472 void* prvTraceGetCurrentTaskHandle(void)\r
473 {\r
474         return xTaskGetCurrentTaskHandle();\r
475 }\r
476 \r
477 /*******************************************************************************\r
478  * prvIsNewTCB\r
479  *\r
480  * Tells if this task is already executing, or if there has been a task-switch.\r
481  * Assumed to be called within a trace hook in kernel context.\r
482  ******************************************************************************/\r
483 uint32_t prvIsNewTCB(void* pNewTCB)\r
484 {\r
485         if (pCurrentTCB != pNewTCB)\r
486         {\r
487                 pCurrentTCB = pNewTCB;\r
488                 return 1;\r
489         }\r
490         return 0;\r
491 }\r
492 \r
493 /*******************************************************************************\r
494  * prvTraceIsSchedulerSuspended\r
495  *\r
496  * Returns true if the RTOS scheduler currently is disabled, thus preventing any\r
497  * task-switches from occurring. Only called from vTraceStoreISREnd.\r
498  ******************************************************************************/\r
499 unsigned char prvTraceIsSchedulerSuspended(void)\r
500 {\r
501     /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs, \r
502         INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in\r
503         FreeRTOSConfig.h for this function to be available. */\r
504 \r
505         return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;\r
506 }\r
507 \r
508 \r
509 /*******************************************************************************\r
510  * prvCheckRecorderStatus\r
511  *\r
512  * Called by TzCtrl task periodically (every 100 ms - seems reasonable).\r
513  * Checks a number of diagnostic variables and give warnings as user events,\r
514  * in most cases including a suggested solution.\r
515  ******************************************************************************/\r
516 static void prvCheckRecorderStatus(void)\r
517 {\r
518         if (NoRoomForSymbol > NoRoomForSymbol_last)\r
519         {\r
520                 if (NoRoomForSymbol > 0)\r
521                 {\r
522                         prvTraceWarning(PSF_WARNING_SYMBOL_TABLE_SLOTS);\r
523                 }\r
524                 NoRoomForSymbol_last = NoRoomForSymbol;\r
525         }\r
526 \r
527         if (NoRoomForObjectData > NoRoomForObjectData_last)\r
528         {\r
529                 if (NoRoomForObjectData > 0)\r
530                 {\r
531                         prvTraceWarning(PSF_WARNING_OBJECT_DATA_SLOTS);\r
532                 }\r
533                 NoRoomForObjectData_last = NoRoomForObjectData;\r
534         }\r
535 \r
536         if (LongestSymbolName > LongestSymbolName_last)\r
537         {\r
538                 if (LongestSymbolName > (TRC_CFG_SYMBOL_MAX_LENGTH))\r
539                 {\r
540                         prvTraceWarning(PSF_WARNING_SYMBOL_MAX_LENGTH);\r
541                 }\r
542                 LongestSymbolName_last = LongestSymbolName;\r
543         }\r
544 \r
545         if (MaxBytesTruncated > MaxBytesTruncated_last)\r
546         {\r
547                 if (MaxBytesTruncated > 0)\r
548                 {\r
549                         prvTraceWarning(PSF_WARNING_STRING_TOO_LONG);\r
550                 }\r
551                 MaxBytesTruncated_last = MaxBytesTruncated;\r
552         }\r
553 }\r
554 \r
555 /*******************************************************************************\r
556  * TzCtrl\r
557  *\r
558  * Task for sending the trace data from the internal buffer to the stream \r
559  * interface (assuming TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) and for\r
560  * receiving commands from Tracealyzer. Also does some diagnostics.\r
561  ******************************************************************************/\r
562 static portTASK_FUNCTION( TzCtrl, pvParameters )\r
563 {\r
564         TracealyzerCommandType msg;\r
565         int32_t bytes = 0;\r
566         int32_t status = 0;\r
567         (void)pvParameters;\r
568 \r
569         while (1)\r
570         {\r
571                 do\r
572                 {\r
573                         /* Listen for new commands */\r
574                         bytes = 0;\r
575                         status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes);\r
576 \r
577                         if (status != 0)\r
578                         {\r
579                                 prvTraceWarning(PSF_WARNING_STREAM_PORT_READ);\r
580                         }\r
581 \r
582                         if ((status == 0) && (bytes == sizeof(TracealyzerCommandType)))\r
583                         {\r
584                                 if (prvIsValidCommand(&msg))\r
585                                 {\r
586                                         prvProcessCommand(&msg); /* Start or Stop currently... */\r
587                                 }\r
588                         }\r
589 \r
590 /* If the internal buffer is disabled, the COMMIT macro instead sends the data directly \r
591    from the "event functions" (using TRC_STREAM_PORT_WRITE_DATA). */                    \r
592 #if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)\r
593                         /* If there is a buffer page, this sends it to the streaming interface using TRC_STREAM_PORT_WRITE_DATA. */\r
594                         bytes = prvPagedEventBufferTransfer();\r
595 #endif                  \r
596                         \r
597                 /* If there was data sent or received (bytes != 0), loop around and repeat, if there is more data to send or receive.\r
598                 Otherwise, step out of this loop and sleep for a while. */              \r
599                 \r
600                 } while (bytes != 0);\r
601 \r
602                 prvCheckRecorderStatus();\r
603 \r
604                 vTaskDelay(TRC_CFG_CTRL_TASK_DELAY);\r
605         }\r
606 }\r
607 \r
608 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/\r
609 \r
610 \r
611 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)\r
612 \r
613 /* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */\r
614 int uiInEventGroupSetBitsFromISR = 0;\r
615 \r
616 /******************************************************************************\r
617  * TraceQueueClassTable\r
618  * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).\r
619  * Has one entry for each QueueType, gives TRACE_CLASS ID.\r
620  ******************************************************************************/\r
621 traceObjectClass TraceQueueClassTable[5] = {\r
622         TRACE_CLASS_QUEUE,\r
623         TRACE_CLASS_MUTEX,\r
624         TRACE_CLASS_SEMAPHORE,\r
625         TRACE_CLASS_SEMAPHORE,\r
626         TRACE_CLASS_MUTEX\r
627 };\r
628 \r
629 #if (TRC_CFG_SCHEDULING_ONLY == 0)\r
630 /*******************************************************************************\r
631  * vTraceSetQueueName(void* object, const char* name)\r
632  *\r
633  * Parameter object: pointer to the Queue that shall be named\r
634  * Parameter name: the name to set (const string literal)\r
635  *\r
636  * Sets a name for Queue objects for display in Tracealyzer.\r
637  ******************************************************************************/\r
638 void vTraceSetQueueName(void* object, const char* name)\r
639 {\r
640         prvTraceSetObjectName(TRACE_CLASS_QUEUE, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);\r
641 }\r
642 \r
643 /*******************************************************************************\r
644  * vTraceSetSemaphoreName(void* object, const char* name)\r
645  *\r
646  * Parameter object: pointer to the Semaphore that shall be named\r
647  * Parameter name: the name to set (const string literal)\r
648  *\r
649  * Sets a name for Semaphore objects for display in Tracealyzer.\r
650  ******************************************************************************/\r
651 void vTraceSetSemaphoreName(void* object, const char* name)\r
652 {\r
653         prvTraceSetObjectName(TRACE_CLASS_SEMAPHORE, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);\r
654 }\r
655 \r
656 /*******************************************************************************\r
657  * vTraceSetMutexName(void* object, const char* name)\r
658  *\r
659  * Parameter object: pointer to the Mutex that shall be named\r
660  * Parameter name: the name to set (const string literal)\r
661  *\r
662  * Sets a name for Semaphore objects for display in Tracealyzer.\r
663  ******************************************************************************/\r
664 void vTraceSetMutexName(void* object, const char* name)\r
665 {\r
666         prvTraceSetObjectName(TRACE_CLASS_MUTEX, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);\r
667 }\r
668 \r
669 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)\r
670 /*******************************************************************************\r
671 * vTraceSetEventGroupName(void* object, const char* name)\r
672 *\r
673 * Parameter object: pointer to the EventGroup that shall be named\r
674 * Parameter name: the name to set (const string literal)\r
675 *\r
676 * Sets a name for EventGroup objects for display in Tracealyzer.\r
677 ******************************************************************************/\r
678 void vTraceSetEventGroupName(void* object, const char* name)\r
679 {\r
680         prvTraceSetObjectName(TRACE_CLASS_EVENTGROUP, TRACE_GET_OBJECT_NUMBER(EVENTGROUP, object), name);\r
681 }\r
682 #endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */\r
683 \r
684 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)\r
685 /*******************************************************************************\r
686 * vTraceSetStreamBufferName(void* object, const char* name)\r
687 *\r
688 * Parameter object: pointer to the StreamBuffer that shall be named\r
689 * Parameter name: the name to set (const string literal)\r
690 *\r
691 * Sets a name for StreamBuffer objects for display in Tracealyzer.\r
692 ******************************************************************************/\r
693 void vTraceSetStreamBufferName(void* object, const char* name)\r
694 {\r
695         prvTraceSetObjectName(TRACE_CLASS_STREAMBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, object), name);\r
696 }\r
697 \r
698 /*******************************************************************************\r
699 * vTraceSetMessageBufferName(void* object, const char* name)\r
700 *\r
701 * Parameter object: pointer to the MessageBuffer that shall be named\r
702 * Parameter name: the name to set (const string literal)\r
703 *\r
704 * Sets a name for MessageBuffer objects for display in Tracealyzer.\r
705 ******************************************************************************/\r
706 void vTraceSetMessageBufferName(void* object, const char* name)\r
707 {\r
708         prvTraceSetObjectName(TRACE_CLASS_MESSAGEBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, object), name);\r
709 }\r
710 #endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */\r
711 \r
712 #endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */\r
713 \r
714 void* prvTraceGetCurrentTaskHandle()\r
715 {\r
716         return xTaskGetCurrentTaskHandle();\r
717 }\r
718 \r
719 /* Initialization of the object property table */\r
720 void vTraceInitObjectPropertyTable()\r
721 {\r
722         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectClasses = TRACE_NCLASSES;\r
723         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[0] = TRC_CFG_NQUEUE;\r
724         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[1] = TRC_CFG_NSEMAPHORE;\r
725         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = TRC_CFG_NMUTEX;\r
726         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = TRC_CFG_NTASK;\r
727         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = TRC_CFG_NISR;\r
728         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = TRC_CFG_NTIMER;\r
729         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = TRC_CFG_NEVENTGROUP;\r
730         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[7] = TRC_CFG_NSTREAMBUFFER;\r
731         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[8] = TRC_CFG_NMESSAGEBUFFER;\r
732         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = TRC_CFG_NAME_LEN_QUEUE;\r
733         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = TRC_CFG_NAME_LEN_SEMAPHORE;\r
734         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = TRC_CFG_NAME_LEN_MUTEX;\r
735         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = TRC_CFG_NAME_LEN_TASK;\r
736         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = TRC_CFG_NAME_LEN_ISR;\r
737         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = TRC_CFG_NAME_LEN_TIMER;\r
738         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = TRC_CFG_NAME_LEN_EVENTGROUP;\r
739         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[7] = TRC_CFG_NAME_LEN_STREAMBUFFER;\r
740         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[8] = TRC_CFG_NAME_LEN_MESSAGEBUFFER;\r
741         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;\r
742         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;\r
743         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;\r
744         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[3] = PropertyTableSizeTask;\r
745         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;\r
746         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[5] = PropertyTableSizeTimer;\r
747         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[6] = PropertyTableSizeEventGroup;\r
748         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[7] = PropertyTableSizeStreamBuffer;\r
749         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[8] = PropertyTableSizeMessageBuffer;\r
750         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;\r
751         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;\r
752         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;\r
753         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[3] = StartIndexTask;\r
754         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;\r
755         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[5] = StartIndexTimer;\r
756         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[6] = StartIndexEventGroup;\r
757         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[7] = StartIndexStreamBuffer;\r
758         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[8] = StartIndexMessageBuffer;\r
759         RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;\r
760 }\r
761 \r
762 /* Initialization of the handle mechanism, see e.g, prvTraceGetObjectHandle */\r
763 void vTraceInitObjectHandleStack()\r
764 {\r
765         objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0;\r
766         objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = (TRC_CFG_NQUEUE);\r
767         objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE);\r
768         objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX);\r
769         objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK);\r
770         objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR);\r
771         objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER);\r
772         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);\r
773         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);\r
774 \r
775         objectHandleStacks.highestIndexOfClass[0] = (TRC_CFG_NQUEUE) - 1;\r
776         objectHandleStacks.highestIndexOfClass[1] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) - 1;\r
777         objectHandleStacks.highestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) - 1;\r
778         objectHandleStacks.highestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) - 1;\r
779         objectHandleStacks.highestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) - 1;\r
780         objectHandleStacks.highestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) - 1;\r
781         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;\r
782         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;\r
783         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;\r
784 }\r
785 \r
786 /* Returns the "Not enough handles" error message for this object class */\r
787 const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)\r
788 {\r
789         switch(objectclass)\r
790         {\r
791         case TRACE_CLASS_TASK:\r
792                 return "Not enough TASK handles - increase TRC_CFG_NTASK in trcSnapshotConfig.h";\r
793         case TRACE_CLASS_ISR:\r
794                 return "Not enough ISR handles - increase TRC_CFG_NISR in trcSnapshotConfig.h";\r
795         case TRACE_CLASS_SEMAPHORE:\r
796                 return "Not enough SEMAPHORE handles - increase TRC_CFG_NSEMAPHORE in trcSnapshotConfig.h";\r
797         case TRACE_CLASS_MUTEX:\r
798                 return "Not enough MUTEX handles - increase TRC_CFG_NMUTEX in trcSnapshotConfig.h";\r
799         case TRACE_CLASS_QUEUE:\r
800                 return "Not enough QUEUE handles - increase TRC_CFG_NQUEUE in trcSnapshotConfig.h";\r
801         case TRACE_CLASS_TIMER:\r
802                 return "Not enough TIMER handles - increase TRC_CFG_NTIMER in trcSnapshotConfig.h";\r
803         case TRACE_CLASS_EVENTGROUP:\r
804                 return "Not enough EVENTGROUP handles - increase TRC_CFG_NEVENTGROUP in trcSnapshotConfig.h";\r
805         case TRACE_CLASS_STREAMBUFFER:\r
806                 return "Not enough STREAMBUFFER handles - increase TRC_CFG_NSTREAMBUFFER in trcSnapshotConfig.h";\r
807         case TRACE_CLASS_MESSAGEBUFFER:\r
808                 return "Not enough MESSAGEBUFFER handles - increase TRC_CFG_NMESSAGEBUFFER in trcSnapshotConfig.h";\r
809         default:\r
810                 return "pszTraceGetErrorHandles: Invalid objectclass!";\r
811         }\r
812 }\r
813 \r
814 /*******************************************************************************\r
815  * prvTraceIsSchedulerSuspended\r
816  *\r
817  * Returns true if the RTOS scheduler currently is disabled, thus preventing any\r
818  * task-switches from occurring. Only called from vTraceStoreISREnd.\r
819  ******************************************************************************/\r
820 #if (TRC_CFG_INCLUDE_ISR_TRACING == 1)\r
821 unsigned char prvTraceIsSchedulerSuspended(void)\r
822 {\r
823     /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs, \r
824         INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in\r
825         FreeRTOSConfig.h for this function to be available. */\r
826 \r
827         return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;\r
828 }\r
829 #endif\r
830 \r
831 #endif /* Snapshot mode */\r
832 \r
833 #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/\r