1 /*******************************************************************************
\r
2 * Trace Recorder Library for Tracealyzer v3.1.2
\r
3 * Percepio AB, www.percepio.com
\r
7 * The FreeRTOS-specific parts of the trace recorder
\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
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
39 * Tabs are used for indent in this file (1 tab = 4 spaces)
\r
41 * Copyright Percepio AB, 2017.
\r
43 ******************************************************************************/
\r
45 #include "FreeRTOS.h"
\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
51 #if (defined(TRC_USE_TRACEALYZER_RECORDER) && TRC_USE_TRACEALYZER_RECORDER == 1)
\r
53 #if (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))
\r
55 The below error message is to alert you on the following issue:
\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
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
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
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
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
77 #ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
\r
78 #error Trace Recorder: This timestamping mode is not recommended with Tickless Idle.
\r
85 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
\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
92 /* We're using compatibility mode, or we're running an old kernel */
\r
93 static xTaskHandle HandleTzCtrl = NULL; /* TzCtrl task TCB */
\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
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
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
113 /* User Event Channel for giving warnings regarding NoRoomForSymbol etc. */
\r
114 traceString trcWarningChannel;
\r
116 #define TRC_PORT_MALLOC(size) pvPortMalloc(size)
\r
118 TRC_STREAM_PORT_ALLOCATE_FIELDS()
\r
120 /* Called by TzCtrl task periodically (Normally every 100 ms) */
\r
121 static void prvCheckRecorderStatus(void);
\r
123 /* The TzCtrl task - receives commands from Tracealyzer (start/stop) */
\r
124 static portTASK_FUNCTION( TzCtrl, pvParameters );
\r
126 /*******************************************************************************
\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
132 ******************************************************************************/
\r
133 void vTraceEnable(int startOption)
\r
136 extern uint32_t RecorderEnabled;
\r
137 TracealyzerCommandType msg;
\r
139 if (HandleTzCtrl != NULL)
\r
140 return; /* Seems we already initiated */
\r
142 TRC_STREAM_PORT_INIT();
\r
144 if (startOption == TRC_START_AWAIT_HOST)
\r
146 /* We keep trying to read commands until the recorder has been started */
\r
150 TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);
\r
152 if (bytes == sizeof(TracealyzerCommandType))
\r
154 if (prvIsValidCommand(&msg))
\r
156 if (msg.cmdCode == CMD_SET_ACTIVE && msg.param1 == 1)
\r
158 /* On start, init and reset the timestamping */
\r
159 TRC_PORT_SPECIFIC_INIT();
\r
162 prvProcessCommand(&msg);
\r
166 while (RecorderEnabled == 0);
\r
168 else if (startOption == TRC_START)
\r
170 /* We start streaming directly - this assumes that the interface is ready! */
\r
171 TRC_PORT_SPECIFIC_INIT();
\r
173 msg.cmdCode = CMD_SET_ACTIVE;
\r
175 prvProcessCommand(&msg);
\r
180 TRC_PORT_SPECIFIC_INIT();
\r
183 trcWarningChannel = xTraceRegisterString("Warnings from Recorder");
\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
190 xTaskCreate( TzCtrl, "TzCtrl", TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl );
\r
194 /*******************************************************************************
\r
197 * Called on trace begin.
\r
198 ******************************************************************************/
\r
199 void prvTraceOnBegin()
\r
201 TRC_STREAM_PORT_ON_TRACE_BEGIN();
\r
204 /*******************************************************************************
\r
207 * Called on trace end.
\r
208 ******************************************************************************/
\r
209 void prvTraceOnEnd()
\r
211 TRC_STREAM_PORT_ON_TRACE_END();
\r
214 /*******************************************************************************
\r
215 * vTraceSetQueueName(void* object, const char* name)
\r
217 * Parameter object: pointer to the Queue that shall be named
\r
218 * Parameter name: the name to set (const string literal)
\r
220 * Sets a name for Queue objects for display in Tracealyzer.
\r
221 ******************************************************************************/
\r
222 void vTraceSetQueueName(void* object, const char* name)
\r
224 vTraceStoreKernelObjectName(object, name);
\r
227 /*******************************************************************************
\r
228 * vTraceSetSemaphoreName(void* object, const char* name)
\r
230 * Parameter object: pointer to the Semaphore that shall be named
\r
231 * Parameter name: the name to set (const string literal)
\r
233 * Sets a name for Semaphore objects for display in Tracealyzer.
\r
234 ******************************************************************************/
\r
235 void vTraceSetSemaphoreName(void* object, const char* name)
\r
237 vTraceStoreKernelObjectName(object, name);
\r
240 /*******************************************************************************
\r
241 * vTraceSetMutexName(void* object, const char* name)
\r
243 * Parameter object: pointer to the Mutex that shall be named
\r
244 * Parameter name: the name to set (const string literal)
\r
246 * Sets a name for Semaphore objects for display in Tracealyzer.
\r
247 ******************************************************************************/
\r
248 void vTraceSetMutexName(void* object, const char* name)
\r
250 vTraceStoreKernelObjectName(object, name);
\r
253 /*******************************************************************************
\r
254 * prvGetCurrentTaskHandle
\r
256 * Function that returns the handle to the currently executing task.
\r
258 ******************************************************************************/
\r
259 void* prvTraceGetCurrentTaskHandle(void)
\r
261 return xTaskGetCurrentTaskHandle();
\r
264 /*******************************************************************************
\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
272 if (pCurrentTCB != pNewTCB)
\r
274 pCurrentTCB = pNewTCB;
\r
280 /*******************************************************************************
\r
281 * prvTraceIsSchedulerSuspended
\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
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
292 return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;
\r
296 /*******************************************************************************
\r
297 * prvCheckRecorderStatus
\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
305 if (NoRoomForSymbol > NoRoomForSymbol_last)
\r
307 vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_TABLE_SLOTS too small. Add %d slots.",
\r
310 NoRoomForSymbol_last = NoRoomForSymbol;
\r
313 if (NoRoomForObjectData > NoRoomForObjectData_last)
\r
315 vTracePrintF(trcWarningChannel, "TRC_CFG_OBJECT_DATA_SLOTS too small. Add %d slots.",
\r
316 NoRoomForObjectData);
\r
318 NoRoomForObjectData_last = NoRoomForObjectData;
\r
321 if (LongestSymbolName > LongestSymbolName_last)
\r
323 if (LongestSymbolName > TRC_CFG_SYMBOL_MAX_LENGTH)
\r
325 vTracePrintF(trcWarningChannel, "TRC_CFG_SYMBOL_MAX_LENGTH too small. Add %d chars.",
\r
326 LongestSymbolName);
\r
328 LongestSymbolName_last = LongestSymbolName;
\r
331 if (MaxBytesTruncated > MaxBytesTruncated_last)
\r
333 /* Some string event generated a too long string that was truncated.
\r
334 This may happen for the following functions:
\r
337 - vTraceStoreKernelObjectName
\r
338 - vTraceStoreUserEventChannelName
\r
339 - vTraceSetISRProperties
\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
345 vTracePrintF(trcWarningChannel, "String event too long, up to %d bytes truncated.",
\r
346 MaxBytesTruncated);
\r
348 MaxBytesTruncated_last = MaxBytesTruncated;
\r
352 /*******************************************************************************
\r
355 * Task for receiving commands from Tracealyzer and for recorder diagnostics.
\r
357 ******************************************************************************/
\r
358 static portTASK_FUNCTION( TzCtrl, pvParameters )
\r
360 TracealyzerCommandType msg;
\r
363 (void)pvParameters;
\r
369 /* Listen for new commands */
\r
371 TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);
\r
372 if (bytes == sizeof(TracealyzerCommandType))
\r
374 if (prvIsValidCommand(&msg))
\r
376 prvProcessCommand(&msg); /* Start or Stop currently... */
\r
380 /* Send periodic data */
\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
385 while (bytes != 0);
\r
387 prvCheckRecorderStatus();
\r
388 vTaskDelay(TRC_CFG_CTRL_TASK_DELAY); /* 10ms */
\r
392 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
\r
395 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
\r
397 /* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */
\r
398 int uiInEventGroupSetBitsFromISR = 0;
\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
408 TRACE_CLASS_SEMAPHORE,
\r
409 TRACE_CLASS_SEMAPHORE,
\r
413 /*******************************************************************************
\r
414 * vTraceSetQueueName(void* object, const char* name)
\r
416 * Parameter object: pointer to the Queue that shall be named
\r
417 * Parameter name: the name to set (const string literal)
\r
419 * Sets a name for Queue objects for display in Tracealyzer.
\r
420 ******************************************************************************/
\r
421 void vTraceSetQueueName(void* object, const char* name)
\r
423 prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);
\r
426 /*******************************************************************************
\r
427 * vTraceSetSemaphoreName(void* object, const char* name)
\r
429 * Parameter object: pointer to the Semaphore that shall be named
\r
430 * Parameter name: the name to set (const string literal)
\r
432 * Sets a name for Semaphore objects for display in Tracealyzer.
\r
433 ******************************************************************************/
\r
434 void vTraceSetSemaphoreName(void* object, const char* name)
\r
436 prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);
\r
439 /*******************************************************************************
\r
440 * vTraceSetMutexName(void* object, const char* name)
\r
442 * Parameter object: pointer to the Mutex that shall be named
\r
443 * Parameter name: the name to set (const string literal)
\r
445 * Sets a name for Semaphore objects for display in Tracealyzer.
\r
446 ******************************************************************************/
\r
447 void vTraceSetMutexName(void* object, const char* name)
\r
449 prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(TRC_UNUSED, object), TRACE_GET_OBJECT_NUMBER(TRC_UNUSED, object), name);
\r
452 void* prvTraceGetCurrentTaskHandle()
\r
454 return xTaskGetCurrentTaskHandle();
\r
457 #if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X)
\r
458 traceHandle prvTraceGetObjectNumber(void* handle)
\r
460 return (traceHandle) ucQueueGetQueueNumber(handle);
\r
462 #else /* For FreeRTOS v8 and later */
\r
463 traceHandle prvTraceGetObjectNumber(void* handle)
\r
465 return (traceHandle) uxQueueGetQueueNumber(handle);
\r
469 uint8_t prvTraceGetObjectType(void* handle)
\r
471 return ucQueueGetQueueType(handle);
\r
474 traceHandle prvTraceGetTaskNumber(void* handle)
\r
476 return (traceHandle)uxTaskGetTaskNumber(handle);
\r
479 /* Initialization of the object property table */
\r
480 void vTraceInitObjectPropertyTable()
\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
514 /* Initialization of the handle mechanism, see e.g, prvTraceGetObjectHandle */
\r
515 void vTraceInitObjectHandleStack()
\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
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
534 /* Returns the "Not enough handles" error message for this object class */
\r
535 const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)
\r
537 switch(objectclass)
\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
554 return "pszTraceGetErrorHandles: Invalid objectclass!";
\r
558 /* Returns the exclude state of the object */
\r
559 uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, traceHandle handle)
\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
564 switch(objectclass)
\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
580 prvTraceError("Invalid object class ID in prvIsObjectExcluded!");
\r
582 /* Must never reach */
\r
586 /*******************************************************************************
\r
587 * prvTraceIsSchedulerSuspended
\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
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
599 return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;
\r
603 #endif /* Snapshot mode */
\r
605 #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
\r