1 /*******************************************************************************
\r
2 * FreeRTOS+Trace v2.3.0 Recorder Library
\r
3 * Percepio AB, www.percepio.com
\r
7 * The kernel integration hooks for FreeRTOS (v7.1.0 or later). This file should
\r
8 * be included in the end of FreeRTOSConfig.h, together with:
\r
10 * #define configUSE_TRACE_FACILITY 1
\r
13 * For IAR Embedded Workbench for ARM, you need to have a preprocessor condition
\r
14 * on the include, to except it from the assembler step which otherwise give
\r
15 * compile-time errors.
\r
18 * #include "percepio/Include/trcHooks.h"
\r
22 * This software is copyright Percepio AB. The recorder library is free for
\r
23 * use together with Percepio products. You may distribute the recorder library
\r
24 * in its original form, including modifications in trcPort.c and trcPort.h
\r
25 * given that these modification are clearly marked as your own modifications
\r
26 * and documented in the initial comment section of these source files.
\r
27 * This software is the intellectual property of Percepio AB and may not be
\r
28 * sold or in other ways commercially redistributed without explicit written
\r
29 * permission by Percepio AB.
\r
32 * The trace tool and recorder library is being delivered to you AS IS and
\r
33 * Percepio AB makes no warranty as to its use or performance. Percepio AB does
\r
34 * not and cannot warrant the performance or results you may obtain by using the
\r
35 * software or documentation. Percepio AB make no warranties, express or
\r
36 * implied, as to noninfringement of third party rights, merchantability, or
\r
37 * fitness for any particular purpose. In no event will Percepio AB, its
\r
38 * technology partners, or distributors be liable to you for any consequential,
\r
39 * incidental or special damages, including any lost profits or lost savings,
\r
40 * even if a representative of Percepio AB has been advised of the possibility
\r
41 * of such damages, or for any claim by any third party. Some jurisdictions do
\r
42 * not allow the exclusion or limitation of incidental, consequential or special
\r
43 * damages, or the exclusion of implied warranties or limitations on how long an
\r
44 * implied warranty may last, so the above limitations may not apply to you.
\r
46 * FreeRTOS+Trace is available as Free Edition and in two premium editions.
\r
47 * You may use the premium features during 30 days for evaluation.
\r
48 * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/
\r
50 * Copyright Percepio AB, 2012.
\r
52 ******************************************************************************/
\r
57 #if (configUSE_TRACE_FACILITY == 1)
\r
59 #include "trcUser.h"
\r
61 #undef INCLUDE_xTaskGetSchedulerState
\r
62 #define INCLUDE_xTaskGetSchedulerState 1
\r
64 #undef INCLUDE_xTaskGetCurrentTaskHandle
\r
65 #define INCLUDE_xTaskGetCurrentTaskHandle 1
\r
67 #if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1
\r
68 /* Called for each task that becomes ready */
\r
69 #undef traceMOVED_TASK_TO_READY_STATE
\r
70 #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
\r
71 vTraceStoreTaskReady((unsigned char)pxTCB->uxTaskNumber);
\r
74 /* Called on each OS tick. Will call uiPortGetTimestamp to make sure it is called at least once every OS tick. */
\r
75 #undef traceTASK_INCREMENT_TICK
\r
76 #define traceTASK_INCREMENT_TICK( xTickCount ) \
\r
77 if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxMissedTicks == 0) {extern uint32_t uiTraceTickCount; uiTraceTickCount++; uiTracePortGetTimeStamp(0);}
\r
79 /* Called on each task-switch */
\r
80 #undef traceTASK_SWITCHED_IN
\r
81 #define traceTASK_SWITCHED_IN() \
\r
82 vTraceStoreTaskswitch();
\r
84 /* Called on vTaskSuspend */
\r
85 #undef traceTASK_SUSPEND
\r
86 #define traceTASK_SUSPEND( pxTaskToSuspend ) \
\r
87 vTraceStoreKernelCall(TASK_SUSPEND, TRACE_CLASS_TASK, pxTaskToSuspend->uxTaskNumber); \
\r
88 vTraceSetTaskInstanceFinished((uint8_t)pxTaskToSuspend->uxTaskNumber);
\r
90 /* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */
\r
91 #undef traceTASK_DELAY
\r
92 #define traceTASK_DELAY() \
\r
93 portENTER_CRITICAL(); \
\r
94 vTraceStoreKernelCallWithNumericParamOnly(TASK_DELAY, (uint16_t)xTicksToDelay);\
\r
95 vTraceSetTaskInstanceFinished((uint8_t)pxCurrentTCB->uxTaskNumber);\
\r
96 portEXIT_CRITICAL();
\r
98 /* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */
\r
99 #undef traceTASK_DELAY_UNTIL
\r
100 #define traceTASK_DELAY_UNTIL() \
\r
101 portENTER_CRITICAL(); \
\r
102 vTraceStoreKernelCallWithNumericParamOnly(TASK_DELAY_UNTIL, (uint16_t)xTimeToWake); \
\r
103 vTraceSetTaskInstanceFinished((uint8_t)pxCurrentTCB->uxTaskNumber); \
\r
104 portEXIT_CRITICAL();
\r
106 #ifndef INCLUDE_OBJECT_DELETE
\r
107 #define INCLUDE_OBJECT_DELETE 0
\r
110 #if (INCLUDE_OBJECT_DELETE == 1)
\r
111 /* Called on vTaskDelete */
\r
112 #undef traceTASK_DELETE
\r
113 #define traceTASK_DELETE( pxTaskToDelete ) \
\r
114 trcCRITICAL_SECTION_BEGIN(); \
\r
115 vTraceStoreKernelCall(EVENTGROUP_DELETE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, pxTaskToDelete->uxTaskNumber); \
\r
116 vTraceStoreObjectNameOnCloseEvent((objectHandleType)pxTaskToDelete->uxTaskNumber, TRACE_CLASS_TASK); \
\r
117 vTraceStoreObjectPropertiesOnCloseEvent((objectHandleType)pxTaskToDelete->uxTaskNumber, TRACE_CLASS_TASK); \
\r
118 vTraceSetPriorityProperty(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber, (uint8_t)pxTaskToDelete->uxPriority); \
\r
119 vTraceSetObjectState(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber, TASK_STATE_INSTANCE_NOT_ACTIVE); \
\r
120 vTraceFreeObjectHandle(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber); \
\r
121 trcCRITICAL_SECTION_END();
\r
124 /* Called on vTaskCreate */
\r
125 #undef traceTASK_CREATE
\r
126 #define traceTASK_CREATE( pxNewTCB ) \
\r
127 if (pxNewTCB != NULL){ \
\r
128 pxNewTCB->uxTaskNumber = xTraceGetObjectHandle(TRACE_CLASS_TASK); \
\r
129 vTraceSetObjectName(TRACE_CLASS_TASK, (objectHandleType)pxNewTCB->uxTaskNumber, (char*)pxNewTCB->pcTaskName); \
\r
130 vTraceSetPriorityProperty(TRACE_CLASS_TASK, (objectHandleType)pxNewTCB->uxTaskNumber, (uint8_t)pxNewTCB->uxPriority); \
\r
131 vTraceStoreKernelCall(EVENTGROUP_CREATE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, pxNewTCB->uxTaskNumber);\
\r
134 /* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */
\r
135 #undef traceTASK_CREATE_FAILED
\r
136 #define traceTASK_CREATE_FAILED() \
\r
137 portENTER_CRITICAL();\
\r
138 vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, 0); \
\r
139 portEXIT_CRITICAL();
\r
141 /* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */
\r
142 #undef traceQUEUE_CREATE
\r
143 #define traceQUEUE_CREATE( pxNewQueue )\
\r
144 portENTER_CRITICAL(); \
\r
145 pxNewQueue->ucQueueNumber = xTraceGetObjectHandle(TraceObjectClassTable[pxNewQueue->ucQueueType]);\
\r
146 vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \
\r
147 vTraceSetObjectState(TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber, 0); \
\r
148 portEXIT_CRITICAL();
\r
150 /* Called in xQueueCreate, if the queue creation fails */
\r
151 #undef traceQUEUE_CREATE_FAILED
\r
152 #define traceQUEUE_CREATE_FAILED( queueType ) \
\r
153 portENTER_CRITICAL();\
\r
154 vTraceStoreKernelCall((uint8_t)(EVENTGROUP_FAILED_CREATE + TraceObjectClassTable[queueType]), TraceObjectClassTable[queueType], 0); \
\r
155 portEXIT_CRITICAL();
\r
157 /* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */
\r
158 #undef traceCREATE_MUTEX
\r
159 #define traceCREATE_MUTEX( pxNewQueue ) \
\r
160 portENTER_CRITICAL();\
\r
161 pxNewQueue->ucQueueNumber = xTraceGetObjectHandle(TRACE_CLASS_MUTEX); \
\r
162 vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \
\r
163 vTraceSetObjectState(TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber, 0); \
\r
164 portEXIT_CRITICAL();
\r
166 /* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */
\r
167 #undef traceCREATE_MUTEX_FAILED
\r
168 #define traceCREATE_MUTEX_FAILED() \
\r
169 portENTER_CRITICAL();\
\r
170 vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_MUTEX, TRACE_CLASS_MUTEX, 0);\
\r
171 portEXIT_CRITICAL();
\r
173 /* Called when the Mutex can not be given, since not holder */
\r
174 #undef traceGIVE_MUTEX_RECURSIVE_FAILED
\r
175 #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) \
\r
176 portENTER_CRITICAL();\
\r
177 vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TRACE_CLASS_MUTEX, TRACE_CLASS_MUTEX, pxMutex->ucQueueNumber); \
\r
178 portEXIT_CRITICAL();
\r
180 /* Called when a message is sent to a queue */
\r
181 #undef traceQUEUE_SEND
\r
182 #define traceQUEUE_SEND( pxQueue ) \
\r
183 vTraceStoreKernelCall(EVENTGROUP_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
\r
184 if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){\
\r
185 vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (uint8_t)pxQueue->ucQueueNumber, (uint8_t)0); \
\r
187 vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (uint8_t)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting + 1)); \
\r
190 /* Called when a message failed to be sent to a queue (timeout) */
\r
191 #undef traceQUEUE_SEND_FAILED
\r
192 #define traceQUEUE_SEND_FAILED( pxQueue ) \
\r
193 portENTER_CRITICAL();\
\r
194 vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
\r
195 portEXIT_CRITICAL();
\r
197 /* Called when the task is blocked due to a send operation on a full queue */
\r
198 #undef traceBLOCKING_ON_QUEUE_SEND
\r
199 #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) \
\r
200 portENTER_CRITICAL();\
\r
201 vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
\r
202 portEXIT_CRITICAL();
\r
204 /* Called when a message is received from a queue */
\r
205 #undef traceQUEUE_RECEIVE
\r
206 #define traceQUEUE_RECEIVE( pxQueue ) \
\r
207 vTraceStoreKernelCall(EVENTGROUP_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
\r
208 if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){\
\r
209 extern volatile void * volatile pxCurrentTCB; \
\r
210 vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxCurrentTCB)); /*For mutex, store the new owner rather than queue length */ \
\r
212 vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting - 1)); \
\r
215 /* Called when the task is blocked due to a receive operation on an empty queue */
\r
216 #undef traceBLOCKING_ON_QUEUE_RECEIVE
\r
217 #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \
\r
218 portENTER_CRITICAL(); \
\r
219 vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
\r
220 if (TraceObjectClassTable[pxQueue->ucQueueType] != TRACE_CLASS_MUTEX){\
\r
221 extern volatile void * volatile pxCurrentTCB; \
\r
222 vTraceSetTaskInstanceFinished((objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxCurrentTCB)); \
\r
224 portEXIT_CRITICAL();
\r
226 /* Called on xQueuePeek */
\r
227 #undef traceQUEUE_PEEK
\r
228 #define traceQUEUE_PEEK( pxQueue ) \
\r
229 vTraceStoreKernelCall(EVENTGROUP_PEEK + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);
\r
231 /* Called when a receive operation on a queue fails (timeout) */
\r
232 #undef traceQUEUE_RECEIVE_FAILED
\r
233 #define traceQUEUE_RECEIVE_FAILED( pxQueue ) \
\r
234 portENTER_CRITICAL(); \
\r
235 vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
\r
236 portEXIT_CRITICAL();
\r
238 /* Called when a message is sent from interrupt context, e.g., using xQueueSendFromISR */
\r
239 #undef traceQUEUE_SEND_FROM_ISR
\r
240 #define traceQUEUE_SEND_FROM_ISR( pxQueue ) \
\r
241 vTraceStoreKernelCall(EVENTGROUP_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
\r
242 vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting + 1));
\r
244 /* Called when a message send from interrupt context fails (since the queue was full) */
\r
245 #undef traceQUEUE_SEND_FROM_ISR_FAILED
\r
246 #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) \
\r
247 vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);
\r
249 /* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */
\r
250 #undef traceQUEUE_RECEIVE_FROM_ISR
\r
251 #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \
\r
252 vTraceStoreKernelCall(EVENTGROUP_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
\r
253 vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting - 1));
\r
255 /* Called when a message receive from interrupt context fails (since the queue was empty) */
\r
256 #undef traceQUEUE_RECEIVE_FROM_ISR_FAILED
\r
257 #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) \
\r
258 vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);
\r
260 #if (INCLUDE_OBJECT_DELETE == 1)
\r
261 /* Called on vQueueDelete */
\r
262 #undef traceQUEUE_DELETE
\r
263 #define traceQUEUE_DELETE( pxQueue ) \
\r
265 portENTER_CRITICAL();\
\r
266 vTraceStoreKernelCall(EVENTGROUP_DELETE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
\r
267 vTraceStoreObjectNameOnCloseEvent((objectHandleType)pxQueue->ucQueueNumber, TraceObjectClassTable[pxQueue->ucQueueType]); \
\r
268 vTraceStoreObjectPropertiesOnCloseEvent((objectHandleType)pxQueue->ucQueueNumber, TraceObjectClassTable[pxQueue->ucQueueType]); \
\r
269 if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){ \
\r
270 vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxQueue->pxMutexHolder)); \
\r
272 vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)uxQueueMessagesWaiting(pxQueue)); \
\r
274 vTraceFreeObjectHandle(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber); \
\r
275 portEXIT_CRITICAL();\
\r
279 /* Called in vTaskPrioritySet */
\r
280 #undef traceTASK_PRIORITY_SET
\r
281 #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \
\r
282 vTraceStoreKernelCallWithParam(TASK_PRIORITY_SET, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\
\r
283 vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority);
\r
285 /* Called in vTaskPriorityInherit, which is called by Mutex operations */
\r
286 #undef traceTASK_PRIORITY_INHERIT
\r
287 #define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \
\r
288 vTraceStoreKernelCallWithParam(TASK_PRIORITY_INHERIT, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\
\r
289 vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority );
\r
291 /* Called in vTaskPriorityDisinherit, which is called by Mutex operations */
\r
292 #undef traceTASK_PRIORITY_DISINHERIT
\r
293 #define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \
\r
294 vTraceStoreKernelCallWithParam(TASK_PRIORITY_DISINHERIT, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\
\r
295 vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority );
\r
297 /* Called in vTaskResume */
\r
298 #undef traceTASK_RESUME
\r
299 #define traceTASK_RESUME( pxTaskToResume ) \
\r
300 vTraceStoreKernelCall(TASK_RESUME, TRACE_CLASS_TASK, pxTaskToResume->uxTaskNumber);
\r
302 /* Called in vTaskResumeFromISR */
\r
303 #undef traceTASK_RESUME_FROM_ISR
\r
304 #define traceTASK_RESUME_FROM_ISR( pxTaskToResume )\
\r
305 vTraceStoreKernelCall(TASK_RESUME_FROM_ISR, TRACE_CLASS_TASK, pxTaskToResume->uxTaskNumber);
\r