]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/ThirdParty/TraceRecorderSrc/trcKernel.c
Split the LPC18xx FreeRTOS+UDP drivers between those that use the LPCOpen library...
[freertos] / FreeRTOS-Plus / Demo / FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC / ThirdParty / TraceRecorderSrc / trcKernel.c
1 /*******************************************************************************\r
2  * FreeRTOS+Trace v2.3.0 Recorder Library\r
3  * Percepio AB, www.percepio.com\r
4  *\r
5  * trcKernel.c\r
6  *\r
7  * Functions for integration of the trace recorder library in the FreeRTOS \r
8  * kernel (requires FreeRTOS v7.1.0 or later).\r
9  * \r
10  * Terms of Use\r
11  * This software is copyright Percepio AB. The recorder library is free for\r
12  * use together with Percepio products. You may distribute the recorder library\r
13  * in its original form, including modifications in trcPort.c and trcPort.h\r
14  * given that these modification are clearly marked as your own modifications\r
15  * and documented in the initial comment section of these source files. \r
16  * This software is the intellectual property of Percepio AB and may not be \r
17  * sold or in other ways commercially redistributed without explicit written \r
18  * permission by Percepio AB.\r
19  *\r
20  * Disclaimer \r
21  * The trace tool and recorder library is being delivered to you AS IS and \r
22  * Percepio AB makes no warranty as to its use or performance. Percepio AB does \r
23  * not and cannot warrant the performance or results you may obtain by using the \r
24  * software or documentation. Percepio AB make no warranties, express or \r
25  * implied, as to noninfringement of third party rights, merchantability, or \r
26  * fitness for any particular purpose. In no event will Percepio AB, its \r
27  * technology partners, or distributors be liable to you for any consequential, \r
28  * incidental or special damages, including any lost profits or lost savings, \r
29  * even if a representative of Percepio AB has been advised of the possibility \r
30  * of such damages, or for any claim by any third party. Some jurisdictions do \r
31  * not allow the exclusion or limitation of incidental, consequential or special \r
32  * damages, or the exclusion of implied warranties or limitations on how long an \r
33  * implied warranty may last, so the above limitations may not apply to you.\r
34  *\r
35  * FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
36  * You may use the premium features during 30 days for evaluation.\r
37  * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
38  *\r
39  * Copyright Percepio AB, 2012.\r
40  * www.percepio.com\r
41  ******************************************************************************/\r
42 \r
43 #include "trcUser.h"\r
44 #include "task.h"\r
45 \r
46 #if (configUSE_TRACE_FACILITY == 1)\r
47 \r
48 \r
49 \r
50 /******************************************************************************\r
51  * TraceObjectClassTable\r
52  * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).\r
53  * This was added since we want to map both types of Mutex and both types of \r
54  * Semaphores on common classes for all Mutexes and all Semaphores respectively. \r
55  * \r
56  * FreeRTOS Queue types\r
57  * #define queueQUEUE_TYPE_BASE                  ( 0U ) => TRACE_CLASS_QUEUE\r
58  * #define queueQUEUE_TYPE_MUTEX                 ( 1U ) => TRACE_CLASS_MUTEX\r
59  * #define queueQUEUE_TYPE_COUNTING_SEMAPHORE    ( 2U ) => TRACE_CLASS_SEMAPHORE\r
60  * #define queueQUEUE_TYPE_BINARY_SEMAPHORE      ( 3U ) => TRACE_CLASS_SEMAPHORE\r
61  * #define queueQUEUE_TYPE_RECURSIVE_MUTEX       ( 4U ) => TRACE_CLASS_MUTEX \r
62  ******************************************************************************/\r
63 traceObjectClass TraceObjectClassTable[5]        =  {TRACE_CLASS_QUEUE,     \r
64                                                      TRACE_CLASS_MUTEX,      \r
65                                                      TRACE_CLASS_SEMAPHORE,  \r
66                                                      TRACE_CLASS_SEMAPHORE,\r
67                                                      TRACE_CLASS_MUTEX };\r
68 \r
69 /* This is defined in FreeRTOS! */\r
70 extern volatile void * volatile pxCurrentTCB; \r
71 \r
72 /* Internal variables */\r
73 uint8_t nISRactive = 0;\r
74 objectHandleType handle_of_last_logged_task = 0;\r
75 uint8_t inExcludedTask = 0;\r
76 \r
77 static uint8_t prvTraceIsObjectExcluded(traceObjectClass, uint32_t);\r
78 \r
79 /*******************************************************************************\r
80  * prvTraceIsObjectExcluded\r
81  *\r
82  * Private function that accepts an object class and an object number and uses\r
83  * that to determine if the object has been flagged as excluded.\r
84  ******************************************************************************/\r
85 static uint8_t prvTraceIsObjectExcluded(traceObjectClass objectClass, uint32_t objectNumber)\r
86 {\r
87     switch(objectClass)\r
88     {\r
89     case TRACE_CLASS_QUEUE:\r
90         return GET_QUEUE_FLAG_ISEXCLUDED(objectNumber);\r
91         break;\r
92     case TRACE_CLASS_SEMAPHORE:\r
93         return GET_SEMAPHORE_FLAG_ISEXCLUDED(objectNumber);\r
94         break;\r
95     case TRACE_CLASS_MUTEX:\r
96         return GET_MUTEX_FLAG_ISEXCLUDED(objectNumber);\r
97         break;\r
98     case TRACE_CLASS_TASK:\r
99         return GET_TASK_FLAG_ISEXCLUDED(objectNumber);\r
100         break;\r
101     }\r
102     return 0;\r
103 }\r
104 \r
105 #if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1\r
106 /*******************************************************************************\r
107  * vTraceStoreTaskReady\r
108  *\r
109  * This function stores a ready state for the task handle sent in as parameter.\r
110  ******************************************************************************/\r
111 void vTraceStoreTaskReady(objectHandleType handle)\r
112 {\r
113     uint16_t dts3;\r
114     TREvent* tr;\r
115 \r
116     if (!GET_TASK_FLAG_ISEXCLUDED(handle))\r
117     {\r
118         dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
119         if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
120         {\r
121             tr = (TREvent*)xTraceNextFreeEventBufferSlot();\r
122 \r
123             if (tr != NULL)\r
124             {\r
125                 tr->type = TR_TASK_READY;\r
126                 tr->dts = dts3;\r
127                 tr->objHandle = handle;\r
128 \r
129                 prvTraceUpdateCounters();    \r
130             }\r
131         }\r
132     }\r
133 }\r
134 #endif\r
135 \r
136 /*******************************************************************************\r
137  * vTraceStoreKernelCall\r
138  *\r
139  * This is the main integration point for storing FreeRTOS kernel calls, and\r
140  * is called by the hooks in FreeRTOS.h (see trcKernel.h for event codes).\r
141  ******************************************************************************/\r
142 void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber)\r
143 {\r
144     KernelCall * kse;\r
145     uint16_t dts1;\r
146 \r
147     if (handle_of_last_logged_task == 0)\r
148     {\r
149         return;\r
150     }\r
151     \r
152     if (RecorderDataPtr->recorderActive)\r
153     {\r
154         \r
155         /* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */\r
156         if (nISRactive || !inExcludedTask)\r
157         {\r
158             /* Make sure ISRs never change the IFE flags of tasks */\r
159             if (!nISRactive)\r
160             {\r
161                 /* This checks if this is the first kernel call after a call to\r
162                 vTraceTaskInstanceIsFinished. In that case, calls to this kernel service \r
163                 with this specific kernel object become the "instance finish event"\r
164                 (IFE) of the calling task.*/\r
165                 if (GET_TASK_FLAG_MARKIFE(handle_of_last_logged_task))\r
166                 {\r
167                     /* Reset the flag - this has been handled now */\r
168                     CLEAR_TASK_FLAG_MARKIFE(handle_of_last_logged_task);\r
169 \r
170                     /* Store the kernel service tagged as instance finished event */\r
171                     PROPERTY_TASK_IFE_SERVICECODE(handle_of_last_logged_task) = \r
172                       (uint8_t)ecode;                \r
173 \r
174                     /* Store the handle of the specific kernel object */\r
175                     PROPERTY_TASK_IFE_OBJHANDLE(handle_of_last_logged_task) =\r
176                       (objectHandleType)objectNumber;    \r
177                 }\r
178             }\r
179             \r
180             /* Check if the referenced object or the event code is excluded */\r
181             if (!prvTraceIsObjectExcluded(objectClass, objectNumber) && !GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))\r
182             {\r
183                 trcCRITICAL_SECTION_BEGIN();\r
184                 dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
185 \r
186                 if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
187                 {           \r
188                     kse = (KernelCall*) xTraceNextFreeEventBufferSlot();\r
189                     if (kse != NULL)\r
190                     {\r
191                         kse->dts = dts1;\r
192                         kse->type = (uint8_t)ecode;\r
193                         kse->objHandle = (uint8_t)objectNumber;\r
194                         prvTraceUpdateCounters();\r
195                     }\r
196                 }\r
197                 trcCRITICAL_SECTION_END();\r
198             }\r
199         }\r
200     }\r
201 }\r
202 \r
203 /*******************************************************************************\r
204  * vTraceStoreKernelCallWithParam\r
205  *\r
206  * Used for storing kernel calls with a handle and a numeric parameter. This is\r
207  * only used for traceTASK_PRIORITY_SET at the moment.\r
208  ******************************************************************************/\r
209 void vTraceStoreKernelCallWithParam(uint32_t evtcode,\r
210                                     traceObjectClass objectClass,\r
211                                     uint32_t objectNumber,\r
212                                     uint8_t param)\r
213 {\r
214     KernelCallWithParamAndHandle * kse;\r
215     uint8_t dts2;\r
216 \r
217     if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && \r
218         (! inExcludedTask || nISRactive))\r
219     {\r
220         /* Check if the referenced object or the event code is excluded */\r
221         if (!prvTraceIsObjectExcluded(objectClass, objectNumber) && !GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))\r
222         {\r
223             trcCRITICAL_SECTION_BEGIN();\r
224             dts2 = (uint8_t)prvTraceGetDTS(0xFF);\r
225 \r
226             if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
227             {                \r
228                 kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot();\r
229                 if (kse != NULL)\r
230                 {\r
231                     kse->dts = dts2;\r
232                     kse->type = (uint8_t)evtcode;\r
233                     kse->objHandle = (uint8_t)objectNumber;\r
234                     kse->param = param;\r
235                     prvTraceUpdateCounters();    \r
236                 }\r
237             }\r
238             trcCRITICAL_SECTION_END();\r
239         }\r
240     }\r
241 }\r
242 \r
243 \r
244 /*******************************************************************************\r
245  * vTraceStoreKernelCallWithNumericParamOnly\r
246  *\r
247  * Used for storing kernel calls with numeric parameters only. This is\r
248  * only used for traceTASK_DELAY and traceDELAY_UNTIL at the moment.\r
249  ******************************************************************************/\r
250 void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint16_t param)\r
251 {\r
252     KernelCallWithParam16 * kse;\r
253     uint8_t dts6;\r
254 \r
255     if (RecorderDataPtr->recorderActive && handle_of_last_logged_task \r
256         && (! inExcludedTask || nISRactive))\r
257     {\r
258         /* Check if the event code is excluded */\r
259         if (!GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))\r
260         {\r
261             trcCRITICAL_SECTION_BEGIN();\r
262             dts6 = (uint8_t)prvTraceGetDTS(0xFF);\r
263 \r
264             if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
265             {                \r
266                 kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot();\r
267                 if (kse != NULL)\r
268                 {\r
269                     kse->dts = dts6;\r
270                     kse->type = (uint8_t)evtcode;\r
271                     kse->param = param;\r
272                     prvTraceUpdateCounters();    \r
273                 }\r
274             }\r
275             trcCRITICAL_SECTION_END();\r
276         }\r
277     }\r
278 }\r
279 \r
280 objectHandleType handle_of_running_task = 0;\r
281 \r
282 /*******************************************************************************\r
283  * vTraceStoreTaskswitch\r
284  * Called by the scheduler from the SWITCHED_OUT hook, and by uiTraceStart.\r
285  * At this point interrupts are assumed to be disabled!\r
286  ******************************************************************************/\r
287 void vTraceStoreTaskswitch(void)\r
288 {\r
289     uint16_t dts3;\r
290     TSEvent* ts;        \r
291     int8_t skipEvent = 0;\r
292     uint32_t schedulerState = 0;\r
293     \r
294     /*************************************************************************** \r
295     This is used to detect if a high-priority ISRs is illegally using the \r
296     recorder ISR trace functions (vTraceStoreISRBegin and ...End) while the \r
297     recorder is busy with a task-level event or lower priority ISR event.\r
298     \r
299     If this is detected, it triggers a call to vTraceError with the error \r
300     "Illegal call to vTraceStoreISRBegin/End". If you get this error, it means\r
301     that the macro taskENTER_CRITICAL does not disable this ISR, as required.\r
302     You can solve this by adjusting the value of the FreeRTOS constant\r
303     configMAX_SYSCALL_INTERRUPT_PRIORITY, which is defined in FreeRTOSConfig.h\r
304 \r
305     Note: Setting recorder_busy is normally handled in our macros\r
306     trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this \r
307     function since critical sections should not be used in the context switch \r
308     event...)    \r
309     ***************************************************************************/\r
310     recorder_busy++; \r
311     \r
312     schedulerState = xTaskGetSchedulerState();\r
313 \r
314     if (schedulerState == 0)\r
315     {\r
316         /* This occurs on the very first taskswitch event, generated by \r
317         vTraceStart and uiTraceStart if the scheduler is not yet started.\r
318         This creates a dummy "(startup)" task entry internally in the\r
319         recorder */\r
320         if (handle_of_running_task == 0)\r
321         {\r
322             handle_of_running_task = xTraceGetObjectHandle(TRACE_CLASS_TASK);\r
323 \r
324             vTraceSetObjectName(TRACE_CLASS_TASK, \r
325                 handle_of_running_task,\r
326                 "(startup)");\r
327 \r
328             vTraceSetPriorityProperty(TRACE_CLASS_TASK,\r
329                 handle_of_running_task,\r
330                 0);\r
331         }        \r
332     }\r
333     else\r
334     {    \r
335         handle_of_running_task = \r
336         (objectHandleType)uxTaskGetTaskNumber(xTaskGetCurrentTaskHandle());\r
337     }\r
338     \r
339     /* Skip the event if the task has been excluded, using vTraceExcludeTask */\r
340     if (GET_TASK_FLAG_ISEXCLUDED(handle_of_running_task))\r
341     {    \r
342         skipEvent = 1;\r
343         inExcludedTask = 1;            \r
344     }\r
345     else\r
346         inExcludedTask = 0;\r
347         \r
348 \r
349     /* Skip the event if the same task is scheduled */\r
350     if (handle_of_running_task == handle_of_last_logged_task)\r
351     {\r
352         skipEvent = 1;\r
353     }\r
354   \r
355     if (! RecorderDataPtr->recorderActive)\r
356     {\r
357         skipEvent = 1;\r
358     }\r
359 \r
360     /* If this event should be logged, log it! */\r
361     if (skipEvent == 0)    \r
362     {    \r
363         dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
364         \r
365         if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
366         {\r
367             handle_of_last_logged_task = handle_of_running_task;            \r
368             ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
369 \r
370             if (ts != NULL)\r
371             {\r
372                 if (uiTraceGetObjectState(TRACE_CLASS_TASK,\r
373                     handle_of_last_logged_task) == TASK_STATE_INSTANCE_ACTIVE)\r
374                 {\r
375                     ts->type = TS_TASK_RESUME;\r
376                 }\r
377                 else\r
378                 {\r
379                     ts->type = TS_TASK_BEGIN;\r
380                 }\r
381 \r
382                 ts->dts = dts3;\r
383                 ts->objHandle = handle_of_last_logged_task;\r
384 \r
385                 vTraceSetObjectState(TRACE_CLASS_TASK, \r
386                                      handle_of_last_logged_task, \r
387                                      TASK_STATE_INSTANCE_ACTIVE);\r
388 \r
389                 prvTraceUpdateCounters();    \r
390             }\r
391         }\r
392     }    \r
393 \r
394     /* See comment on recorder_busy++ above. */\r
395     recorder_busy--; \r
396 }\r
397 \r
398 /*******************************************************************************\r
399  * vTraceStoreNameCloseEvent\r
400  *\r
401  * Updates the symbol table with the name of this object from the dynamic\r
402  * objects table and stores a "close" event, holding the mapping between handle\r
403  * and name (a symbol table handle). The stored name-handle mapping is thus the\r
404  * "old" one, valid up until this point.\r
405  ******************************************************************************/\r
406 #if (INCLUDE_OBJECT_DELETE == 1)\r
407 void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle, \r
408                                        traceObjectClass objectclass)\r
409 {    \r
410     ObjCloseNameEvent * ce;\r
411     const char * name;\r
412     traceLabel idx;\r
413 \r
414     name = PROPERTY_NAME_GET(objectclass, handle);\r
415 \r
416     idx = prvTraceOpenSymbol(name, 0);\r
417     \r
418     // Interrupt disable not necessary, already done in trcHooks.h macro\r
419     ce = (ObjCloseNameEvent*) xTraceNextFreeEventBufferSlot(); \r
420     if (ce != NULL)\r
421     {\r
422         ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass;\r
423         ce->objHandle = handle;\r
424         ce->symbolIndex = idx;\r
425         prvTraceUpdateCounters();\r
426     }\r
427     \r
428 }\r
429 \r
430 void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle, \r
431                                              traceObjectClass objectclass)\r
432 {\r
433     ObjClosePropEvent * pe;\r
434 \r
435     if (objectclass == TRACE_CLASS_ISR)\r
436     {        \r
437         /* ISR handles should not be closed - never called for ISR */\r
438         return;\r
439     }\r
440 \r
441     // Interrupt disable not necessary, already done in trcHooks.h macro\r
442     pe = (ObjClosePropEvent*) xTraceNextFreeEventBufferSlot();\r
443     if (pe != NULL)\r
444     {\r
445         if (objectclass == TRACE_CLASS_TASK)\r
446         {\r
447             pe->arg1 = PROPERTY_ACTOR_PRIORITY(objectclass, handle);\r
448             pe->arg2 = PROPERTY_TASK_IFE_SERVICECODE(handle);\r
449             pe->arg3 = PROPERTY_TASK_IFE_OBJHANDLE(handle);\r
450             PROPERTY_TASK_IFE_SERVICECODE(handle) = 0;\r
451             PROPERTY_TASK_IFE_OBJHANDLE(handle) = 0;\r
452         }else{\r
453             pe->arg1 = PROPERTY_OBJECT_STATE(objectclass, handle);\r
454         }\r
455         pe->type = EVENTGROUP_OBJCLOSE_PROP + objectclass;    \r
456         prvTraceUpdateCounters();\r
457     }\r
458 }\r
459 #endif\r
460 \r
461 void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value)\r
462 {\r
463     PROPERTY_ACTOR_PRIORITY(objectclass, id) = value;\r
464 }\r
465 \r
466 uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id)\r
467 {\r
468     return PROPERTY_ACTOR_PRIORITY(objectclass, id);\r
469 }\r
470 \r
471 void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value)\r
472 {\r
473     PROPERTY_OBJECT_STATE(objectclass, id) = value;\r
474 }\r
475 \r
476 void vTraceSetTaskInstanceFinished(objectHandleType handle)\r
477 {\r
478 #if (USE_IMPLICIT_IFE_RULES == 1)\r
479     if (PROPERTY_TASK_IFE_SERVICECODE(handle) == 0)\r
480     {\r
481         PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle) = 0;\r
482     }\r
483 #endif\r
484 }\r
485 \r
486 uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id)\r
487 {\r
488     return PROPERTY_OBJECT_STATE(objectclass, id);\r
489 }\r
490 \r
491 #endif\r