]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c
96e568a1a231fe406ba5be81fd035fe60bab2d8d
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-Trace / trcKernelPort.c
1 /*******************************************************************************\r
2  * Trace Recorder Library for Tracealyzer v3.1.2\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, 2017.\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 #if (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))\r
54         /*\r
55                 The below error message is to alert you on the following issue:\r
56 \r
57                 The hardware port selected in trcConfig.h uses the operating system timer for the\r
58                 timestamping, i.e., the periodic interrupt timer that drives the OS tick interrupt.\r
59 \r
60                 When using tickless idle, the recorder needs an independent time source in order to\r
61                 correctly record the durations of the idle times. Otherwise, the trace may appear\r
62                 to have a different length than in reality, and the reported CPU load is also affected.\r
63 \r
64                 You may override this warning by defining the TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING\r
65                 macro in your trcConfig.h file. But then the time scale may be incorrect during\r
66                 tickless idle periods.\r
67 \r
68                 To get this correct, override the default timestamping by setting TRC_CFG_HARDWARE_PORT\r
69                 in trcConfig.h to TRC_HARDWARE_PORT_APPLICATION_DEFINED and define the HWTC macros\r
70                 accordingly, using a free running counter or an independent periodic interrupt timer.\r
71                 See trcHardwarePort.h for details.\r
72 \r
73                 For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the\r
74                 DWT cycle counter for timestamping in these cases.\r
75         */\r
76 \r
77         #ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING\r
78         #error Trace Recorder: This timestamping mode is not recommended with Tickless Idle.\r
79         #endif\r
80 #endif\r
81 \r
82 #include "task.h"\r
83 #include "queue.h"\r
84 \r
85 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)\r
86 \r
87 static void* pCurrentTCB = NULL;\r
88 #if (defined(configENABLE_BACKWARD_COMPATIBILITY) && configENABLE_BACKWARD_COMPATIBILITY == 0)\r
89 /* We're explicitly not using compatibility mode */\r
90 static TaskHandle_t HandleTzCtrl = NULL;       /* TzCtrl task TCB */\r
91 #else\r
92 /* We're using compatibility mode, or we're running an old kernel */\r
93 static xTaskHandle HandleTzCtrl = NULL;       /* TzCtrl task TCB */\r
94 #endif\r
95 \r
96 #if (configSUPPORT_STATIC_ALLOCATION == 1)\r
97 static StackType_t stackTzCtrl[TRC_CFG_CTRL_TASK_STACK_SIZE];\r
98 static StaticTask_t tcbTzCtrl;\r
99 #endif\r
100 \r
101 /* Monitored by TzCtrl task, that give warnings as User Events */\r
102 extern volatile uint32_t NoRoomForSymbol;\r
103 extern volatile uint32_t NoRoomForObjectData;\r
104 extern volatile uint32_t LongestSymbolName;\r
105 extern volatile uint32_t MaxBytesTruncated;\r
106 \r
107 /* Keeps track of previous values, to only react on changes. */\r
108 static uint32_t NoRoomForSymbol_last = 0;\r
109 static uint32_t NoRoomForObjectData_last = 0;\r
110 static uint32_t LongestSymbolName_last = 0;\r
111 static uint32_t MaxBytesTruncated_last = 0;\r
112 \r
113 /* User Event Channel for giving warnings regarding NoRoomForSymbol etc. */\r
114 traceString trcWarningChannel;\r
115 \r
116 #define TRC_PORT_MALLOC(size) pvPortMalloc(size)\r
117 \r
118 TRC_STREAM_PORT_ALLOCATE_FIELDS()\r
119 \r
120 /* Called by TzCtrl task periodically (Normally every 100 ms) */\r
121 static void prvCheckRecorderStatus(void);\r
122 \r
123 /* The TzCtrl task - receives commands from Tracealyzer (start/stop) */\r
124 static portTASK_FUNCTION( TzCtrl, pvParameters );\r
125 \r
126 /*******************************************************************************\r
127  * vTraceEnable\r
128  *\r
129  * Function that enables the tracing and creates the control task. It will halt\r
130  * execution until a Start command has been received if haltUntilStart is true.\r
131  *\r
132  ******************************************************************************/\r
133 void vTraceEnable(int startOption)\r
134 {\r
135         int bytes = 0;\r
136         extern uint32_t RecorderEnabled;\r
137         TracealyzerCommandType msg;\r
138 \r
139         if (HandleTzCtrl != NULL)\r
140                 return; /* Seems we already initiated */\r
141 \r
142         TRC_STREAM_PORT_INIT();\r
143 \r
144         if (startOption == TRC_START_AWAIT_HOST)\r
145         {\r
146                 /* We keep trying to read commands until the recorder has been started */\r
147                 do\r
148                 {\r
149                         bytes = 0;\r
150                         TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);\r
151 \r
152                         if (bytes == sizeof(TracealyzerCommandType))\r
153                         {\r
154                                 if (prvIsValidCommand(&msg))\r
155                                 {\r
156                                         if (msg.cmdCode == CMD_SET_ACTIVE && msg.param1 == 1)\r
157                                         {\r
158                                                 /* On start, init and reset the timestamping */\r
159                                                 TRC_PORT_SPECIFIC_INIT();\r
160                                         }\r
161 \r
162                                         prvProcessCommand(&msg);\r
163                                 }\r
164                         }\r
165                 }\r
166                 while (RecorderEnabled == 0);\r
167         }\r
168         else if (startOption == TRC_START)\r
169         {\r
170                 /* We start streaming directly - this assumes that the interface is ready! */\r
171                 TRC_PORT_SPECIFIC_INIT();\r
172 \r
173                 msg.cmdCode = CMD_SET_ACTIVE;\r
174                 msg.param1 = 1;\r
175                 prvProcessCommand(&msg);\r
176         }\r
177         else\r
178         {\r
179                 /* On TRC_INIT */\r
180                 TRC_PORT_SPECIFIC_INIT();\r
181         }\r
182 \r
183         trcWarningChannel = xTraceRegisterString("Warnings from Recorder");\r
184 \r
185         /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */\r
186 #if (configSUPPORT_STATIC_ALLOCATION == 1)\r
187         HandleTzCtrl = xTaskCreateStatic(TzCtrl, "TzCtrl", TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);\r
188         (void)HandleTzCtrl;\r
189 #else\r
190         xTaskCreate( TzCtrl, "TzCtrl", TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl );\r
191 #endif\r
192 }\r
193 \r
194 /*******************************************************************************\r
195  * prvTraceOnBegin\r
196  *\r
197  * Called on trace begin.\r
198  ******************************************************************************/\r
199 void prvTraceOnBegin()\r
200 {\r
201         TRC_STREAM_PORT_ON_TRACE_BEGIN();\r
202 }\r
203 \r
204 /*******************************************************************************\r
205  * prvTraceOnEnd\r
206  *\r
207  * Called on trace end.\r
208  ******************************************************************************/\r
209 void prvTraceOnEnd()\r
210 {\r
211         TRC_STREAM_PORT_ON_TRACE_END();\r
212 }\r
213 \r
214 /*******************************************************************************\r
215  * vTraceSetQueueName(void* object, const char* name)\r
216  *\r
217  * Parameter object: pointer to the Queue that shall be named\r
218  * Parameter name: the name to set (const string literal)\r
219  *\r
220  * Sets a name for Queue objects for display in Tracealyzer.\r
221  ******************************************************************************/\r
222 void vTraceSetQueueName(void* object, const char* name)\r
223 {\r
224         vTraceStoreKernelObjectName(object, name);\r
225 }\r
226 \r
227 /*******************************************************************************\r
228  * vTraceSetSemaphoreName(void* object, const char* name)\r
229  *\r
230  * Parameter object: pointer to the Semaphore that shall be named\r
231  * Parameter name: the name to set (const string literal)\r
232  *\r
233  * Sets a name for Semaphore objects for display in Tracealyzer.\r
234  ******************************************************************************/\r
235 void vTraceSetSemaphoreName(void* object, const char* name)\r
236 {\r
237         vTraceStoreKernelObjectName(object, name);\r
238 }\r
239 \r
240 /*******************************************************************************\r
241  * vTraceSetMutexName(void* object, const char* name)\r
242  *\r
243  * Parameter object: pointer to the Mutex that shall be named\r
244  * Parameter name: the name to set (const string literal)\r
245  *\r
246  * Sets a name for Semaphore objects for display in Tracealyzer.\r
247  ******************************************************************************/\r
248 void vTraceSetMutexName(void* object, const char* name)\r
249 {\r
250         vTraceStoreKernelObjectName(object, name);\r
251 }\r
252 \r
253 /*******************************************************************************\r
254  * prvGetCurrentTaskHandle\r
255  *\r
256  * Function that returns the handle to the currently executing task.\r
257  *\r
258  ******************************************************************************/\r
259 void* prvTraceGetCurrentTaskHandle(void)\r
260 {\r
261         return xTaskGetCurrentTaskHandle();\r
262 }\r
263 \r
264 /*******************************************************************************\r
265  * prvIsNewTCB\r
266  *\r
267  * Tells if this task is already executing, or if there has been a task-switch.\r
268  * Assumed to be called within a trace hook in kernel context.\r
269  ******************************************************************************/\r
270 uint32_t prvIsNewTCB(void* pNewTCB)\r
271 {\r
272         if (pCurrentTCB != pNewTCB)\r
273         {\r
274                 pCurrentTCB = pNewTCB;\r
275                 return 1;\r
276         }\r
277         return 0;\r
278 }\r
279 \r
280 /*******************************************************************************\r
281  * prvTraceIsSchedulerSuspended\r
282  *\r
283  * Returns true if the RTOS scheduler currently is disabled, thus preventing any\r
284  * task-switches from occurring. Only called from vTraceStoreISREnd.\r
285  ******************************************************************************/\r
286 unsigned char prvTraceIsSchedulerSuspended()\r
287 {\r
288     /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,\r
289         INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in\r
290         FreeRTOSConfig.h for this function to be available. */\r
291 \r
292         return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;\r
293 }\r
294 \r
295 \r
296 /*******************************************************************************\r
297  * prvCheckRecorderStatus\r
298  *\r
299  * Called by TzCtrl task periodically (every 100 ms - seems reasonable).\r
300  * Checks a number of diagnostic variables and give warnings as user events,\r
301  * in most cases including a suggested solution.\r
302  ******************************************************************************/\r
303 static void prvCheckRecorderStatus(void)\r
304 {\r
305         if (NoRoomForSymbol > NoRoomForSymbol_last)\r
306         {\r
307                 vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_TABLE_SLOTS too small. Add %d slots.",\r
308                         NoRoomForSymbol);\r
309 \r
310                 NoRoomForSymbol_last = NoRoomForSymbol;\r
311         }\r
312 \r
313         if (NoRoomForObjectData > NoRoomForObjectData_last)\r
314         {\r
315                 vTracePrintF(trcWarningChannel, "TRC_CFG_OBJECT_DATA_SLOTS too small. Add %d slots.",\r
316                         NoRoomForObjectData);\r
317 \r
318                 NoRoomForObjectData_last = NoRoomForObjectData;\r
319         }\r
320 \r
321         if (LongestSymbolName > LongestSymbolName_last)\r
322         {\r
323                 if (LongestSymbolName > TRC_CFG_SYMBOL_MAX_LENGTH)\r
324                 {\r
325                         vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_MAX_LENGTH too small. Add %d chars.",\r
326                                 LongestSymbolName);\r
327                 }\r
328                 LongestSymbolName_last = LongestSymbolName;\r
329         }\r
330 \r
331         if (MaxBytesTruncated > MaxBytesTruncated_last)\r
332         {\r
333                 /* Some string event generated a too long string that was truncated.\r
334                 This may happen for the following functions:\r
335                 - vTracePrintF\r
336                 - vTracePrintF\r
337                 - vTraceStoreKernelObjectName\r
338                 - vTraceStoreUserEventChannelName\r
339                 - vTraceSetISRProperties\r
340 \r
341                 A PSF event may store maximum 60 bytes payload, including data arguments\r
342                 and string characters. For User Events, also the User Event Channel ptr\r
343                 must be squeezed in, if a channel is specified. */\r
344 \r
345                 vTracePrintF(trcWarningChannel, "String event too long, up to %d bytes truncated.",\r
346                         MaxBytesTruncated);\r
347 \r
348                 MaxBytesTruncated_last = MaxBytesTruncated;\r
349         }\r
350 }\r
351 \r
352 /*******************************************************************************\r
353  * TzCtrl\r
354  *\r
355  * Task for receiving commands from Tracealyzer and for recorder diagnostics.\r
356  *\r
357  ******************************************************************************/\r
358 static portTASK_FUNCTION( TzCtrl, pvParameters )\r
359 {\r
360         TracealyzerCommandType msg;\r
361         int bytes = 0;\r
362 \r
363         (void)pvParameters;\r
364 \r
365         while (1)\r
366         {\r
367                 do\r
368                 {\r
369                         /* Listen for new commands */\r
370                         bytes = 0;\r
371                         TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);\r
372                         if (bytes == sizeof(TracealyzerCommandType))\r
373                         {\r
374                                 if (prvIsValidCommand(&msg))\r
375                                 {\r
376                                         prvProcessCommand(&msg); /* Start or Stop currently... */\r
377                                 }\r
378                         }\r
379 \r
380                         /* Send periodic data */\r
381                         bytes = 0;\r
382                         TRC_STREAM_PORT_PERIODIC_SEND_DATA(&bytes);\r
383                         /* If there was data sent (bytes != 0), immediately loop around and do all this again. Otherwise, step out of this loop and sleep for a while. */\r
384                 }\r
385                 while (bytes != 0);\r
386 \r
387                 prvCheckRecorderStatus();\r
388                 vTaskDelay(TRC_CFG_CTRL_TASK_DELAY);    /* 10ms */\r
389         }\r
390 }\r
391 \r
392 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/\r
393 \r
394 \r
395 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)\r
396 \r
397 /* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */\r
398 int uiInEventGroupSetBitsFromISR = 0;\r
399 \r
400 /******************************************************************************\r
401  * TraceObjectClassTable\r
402  * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).\r
403  * Has one entry for each QueueType, gives TRACE_CLASS ID.\r
404  ******************************************************************************/\r
405 traceObjectClass TraceObjectClassTable[5] = {\r
406         TRACE_CLASS_QUEUE,\r
407         TRACE_CLASS_MUTEX,\r
408         TRACE_CLASS_SEMAPHORE,\r
409         TRACE_CLASS_SEMAPHORE,\r
410         TRACE_CLASS_MUTEX\r
411 };\r
412 \r
413 /*******************************************************************************\r
414  * vTraceSetQueueName(void* object, const char* name)\r
415  *\r
416  * Parameter object: pointer to the Queue that shall be named\r
417  * Parameter name: the name to set (const string literal)\r
418  *\r
419  * Sets a name for Queue objects for display in Tracealyzer.\r
420  ******************************************************************************/\r
421 void vTraceSetQueueName(void* object, const char* name)\r
422 {\r
423         prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);\r
424 }\r
425 \r
426 /*******************************************************************************\r
427  * vTraceSetSemaphoreName(void* object, const char* name)\r
428  *\r
429  * Parameter object: pointer to the Semaphore that shall be named\r
430  * Parameter name: the name to set (const string literal)\r
431  *\r
432  * Sets a name for Semaphore objects for display in Tracealyzer.\r
433  ******************************************************************************/\r
434 void vTraceSetSemaphoreName(void* object, const char* name)\r
435 {\r
436         prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);\r
437 }\r
438 \r
439 /*******************************************************************************\r
440  * vTraceSetMutexName(void* object, const char* name)\r
441  *\r
442  * Parameter object: pointer to the Mutex that shall be named\r
443  * Parameter name: the name to set (const string literal)\r
444  *\r
445  * Sets a name for Semaphore objects for display in Tracealyzer.\r
446  ******************************************************************************/\r
447 void vTraceSetMutexName(void* object, const char* name)\r
448 {\r
449         prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);\r
450 }\r
451 \r
452 void* prvTraceGetCurrentTaskHandle()\r
453 {\r
454         return xTaskGetCurrentTaskHandle();\r
455 }\r
456 \r
457 #if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X)\r
458 traceHandle prvTraceGetObjectNumber(void* handle)\r
459 {\r
460         return (traceHandle) ucQueueGetQueueNumber(handle);\r
461 }\r
462 #else /* For FreeRTOS v8 and later */\r
463 traceHandle prvTraceGetObjectNumber(void* handle)\r
464 {\r
465         return (traceHandle) uxQueueGetQueueNumber(handle);\r
466 }\r
467 #endif\r
468 \r
469 uint8_t prvTraceGetObjectType(void* handle)\r
470 {\r
471         return ucQueueGetQueueType(handle);\r
472 }\r
473 \r
474 traceHandle prvTraceGetTaskNumber(void* handle)\r
475 {\r
476         return (traceHandle)uxTaskGetTaskNumber(handle);\r
477 }\r
478 \r
479 /* Initialization of the object property table */\r
480 void vTraceInitObjectPropertyTable()\r
481 {\r
482         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectClasses = TRACE_NCLASSES;\r
483         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[0] = TRC_CFG_NQUEUE;\r
484         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[1] = TRC_CFG_NSEMAPHORE;\r
485         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = TRC_CFG_NMUTEX;\r
486         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = TRC_CFG_NTASK;\r
487         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = TRC_CFG_NISR;\r
488         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = TRC_CFG_NTIMER;\r
489         RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = TRC_CFG_NEVENTGROUP;\r
490         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = TRC_CFG_NAME_LEN_QUEUE;\r
491         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = TRC_CFG_NAME_LEN_SEMAPHORE;\r
492         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = TRC_CFG_NAME_LEN_MUTEX;\r
493         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = TRC_CFG_NAME_LEN_TASK;\r
494         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = TRC_CFG_NAME_LEN_ISR;\r
495         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = TRC_CFG_NAME_LEN_TIMER;\r
496         RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = TRC_CFG_NAME_LEN_EVENTGROUP;\r
497         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;\r
498         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;\r
499         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;\r
500         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[3] = PropertyTableSizeTask;\r
501         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;\r
502         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[5] = PropertyTableSizeTimer;\r
503         RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[6] = PropertyTableSizeEventGroup;\r
504         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;\r
505         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;\r
506         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;\r
507         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[3] = StartIndexTask;\r
508         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;\r
509         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[5] = StartIndexTimer;\r
510         RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[6] = StartIndexEventGroup;\r
511         RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;\r
512 }\r
513 \r
514 /* Initialization of the handle mechanism, see e.g, prvTraceGetObjectHandle */\r
515 void vTraceInitObjectHandleStack()\r
516 {\r
517         objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0;\r
518         objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = TRC_CFG_NQUEUE;\r
519         objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE;\r
520         objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX;\r
521         objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK;\r
522         objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR;\r
523         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
524 \r
525         objectHandleStacks.highestIndexOfClass[0] = TRC_CFG_NQUEUE - 1;\r
526         objectHandleStacks.highestIndexOfClass[1] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE - 1;\r
527         objectHandleStacks.highestIndexOfClass[2] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX - 1;\r
528         objectHandleStacks.highestIndexOfClass[3] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK - 1;\r
529         objectHandleStacks.highestIndexOfClass[4] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR - 1;\r
530         objectHandleStacks.highestIndexOfClass[5] = TRC_CFG_NQUEUE + TRC_CFG_NSEMAPHORE + TRC_CFG_NMUTEX + TRC_CFG_NTASK + TRC_CFG_NISR + TRC_CFG_NTIMER - 1;\r
531         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
532 }\r
533 \r
534 /* Returns the "Not enough handles" error message for this object class */\r
535 const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)\r
536 {\r
537         switch(objectclass)\r
538         {\r
539         case TRACE_CLASS_TASK:\r
540                 return "Not enough TASK handles - increase TRC_CFG_NTASK in trcSnapshotConfig.h";\r
541         case TRACE_CLASS_ISR:\r
542                 return "Not enough ISR handles - increase TRC_CFG_NISR in trcSnapshotConfig.h";\r
543         case TRACE_CLASS_SEMAPHORE:\r
544                 return "Not enough SEMAPHORE handles - increase TRC_CFG_NSEMAPHORE in trcSnapshotConfig.h";\r
545         case TRACE_CLASS_MUTEX:\r
546                 return "Not enough MUTEX handles - increase TRC_CFG_NMUTEX in trcSnapshotConfig.h";\r
547         case TRACE_CLASS_QUEUE:\r
548                 return "Not enough QUEUE handles - increase TRC_CFG_NQUEUE in trcSnapshotConfig.h";\r
549         case TRACE_CLASS_TIMER:\r
550                 return "Not enough TIMER handles - increase TRC_CFG_NTIMER in trcSnapshotConfig.h";\r
551         case TRACE_CLASS_EVENTGROUP:\r
552                 return "Not enough EVENTGROUP handles - increase TRC_CFG_NEVENTGROUP in trcSnapshotConfig.h";\r
553         default:\r
554                 return "pszTraceGetErrorHandles: Invalid objectclass!";\r
555         }\r
556 }\r
557 \r
558 /* Returns the exclude state of the object */\r
559 uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, traceHandle handle)\r
560 {\r
561         TRACE_ASSERT(objectclass < TRACE_NCLASSES, "prvIsObjectExcluded: objectclass >= TRACE_NCLASSES", 1);\r
562         TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "prvIsObjectExcluded: Invalid value for handle", 1);\r
563 \r
564         switch(objectclass)\r
565         {\r
566         case TRACE_CLASS_TASK:\r
567                 return (uint8_t) TRACE_GET_TASK_FLAG_ISEXCLUDED(handle);\r
568         case TRACE_CLASS_SEMAPHORE:\r
569                 return (uint8_t) TRACE_GET_SEMAPHORE_FLAG_ISEXCLUDED(handle);\r
570         case TRACE_CLASS_MUTEX:\r
571                 return (uint8_t) TRACE_GET_MUTEX_FLAG_ISEXCLUDED(handle);\r
572         case TRACE_CLASS_QUEUE:\r
573                 return (uint8_t) TRACE_GET_QUEUE_FLAG_ISEXCLUDED(handle);\r
574         case TRACE_CLASS_TIMER:\r
575                 return (uint8_t) TRACE_GET_TIMER_FLAG_ISEXCLUDED(handle);\r
576         case TRACE_CLASS_EVENTGROUP:\r
577                 return (uint8_t) TRACE_GET_EVENTGROUP_FLAG_ISEXCLUDED(handle);\r
578         }\r
579 \r
580         prvTraceError("Invalid object class ID in prvIsObjectExcluded!");\r
581 \r
582         /* Must never reach */\r
583         return 1;\r
584 }\r
585 \r
586 /*******************************************************************************\r
587  * prvTraceIsSchedulerSuspended\r
588  *\r
589  * Returns true if the RTOS scheduler currently is disabled, thus preventing any\r
590  * task-switches from occurring. Only called from vTraceStoreISREnd.\r
591  ******************************************************************************/\r
592 #if (TRC_CFG_INCLUDE_ISR_TRACING == 1)\r
593 unsigned char prvTraceIsSchedulerSuspended()\r
594 {\r
595     /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,\r
596         INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in\r
597         FreeRTOSConfig.h for this function to be available. */\r
598 \r
599         return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;\r
600 }\r
601 #endif\r
602 \r
603 #endif /* Snapshot mode */\r
604 \r
605 #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/\r