]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernel.c
78334daa35efe8037ca340d8d173e81c978faa75
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-Trace / trcKernel.c
1 /*******************************************************************************\r
2  * Tracealyzer v2.5.0 Recorder Library\r
3  * Percepio AB, www.percepio.com\r
4  *\r
5  * trcKernel.c\r
6  *\r
7  * Functions used by trcKernelHooks.h.\r
8  *\r
9  * Terms of Use\r
10  * This software is copyright Percepio AB. The recorder library is free for\r
11  * use together with Percepio products. You may distribute the recorder library\r
12  * in its original form, including modifications in trcHardwarePort.c/.h\r
13  * given that these modification are clearly marked as your own modifications\r
14  * and documented in the initial comment section of these source files.\r
15  * This software is the intellectual property of Percepio AB and may not be\r
16  * sold or in other ways commercially redistributed without explicit written\r
17  * permission by Percepio AB.\r
18  *\r
19  * Disclaimer\r
20  * The trace tool and recorder library is being delivered to you AS IS and\r
21  * Percepio AB makes no warranty as to its use or performance. Percepio AB does\r
22  * not and cannot warrant the performance or results you may obtain by using the\r
23  * software or documentation. Percepio AB make no warranties, express or\r
24  * implied, as to noninfringement of third party rights, merchantability, or\r
25  * fitness for any particular purpose. In no event will Percepio AB, its\r
26  * technology partners, or distributors be liable to you for any consequential,\r
27  * incidental or special damages, including any lost profits or lost savings,\r
28  * even if a representative of Percepio AB has been advised of the possibility\r
29  * of such damages, or for any claim by any third party. Some jurisdictions do\r
30  * not allow the exclusion or limitation of incidental, consequential or special\r
31  * damages, or the exclusion of implied warranties or limitations on how long an\r
32  * implied warranty may last, so the above limitations may not apply to you.\r
33  *\r
34  * Copyright Percepio AB, 2013.\r
35  * www.percepio.com\r
36  ******************************************************************************/\r
37 \r
38 #include "trcKernel.h"\r
39 \r
40 #if (USE_TRACEALYZER_RECORDER == 1)\r
41 \r
42 #include <stdint.h>\r
43 \r
44 /* Internal variables */\r
45 uint8_t nISRactive = 0;\r
46 objectHandleType handle_of_last_logged_task = 0;\r
47 uint8_t inExcludedTask = 0;\r
48 \r
49 static uint32_t prvTraceGetParam(uint32_t, uint32_t);\r
50 \r
51 #if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1\r
52 /*******************************************************************************\r
53  * vTraceStoreTaskReady\r
54  *\r
55  * This function stores a ready state for the task handle sent in as parameter.\r
56  ******************************************************************************/\r
57 void vTraceStoreTaskReady(objectHandleType handle)\r
58 {\r
59     uint16_t dts3;\r
60     TREvent* tr;\r
61         \r
62         TRACE_ASSERT(handle > 0 && handle <= NTask, "vTraceStoreTaskReady: Invalid value for handle", );\r
63 \r
64     if (recorder_busy)\r
65     {\r
66       /***********************************************************************\r
67       * This should never occur, as the tick- and kernel call ISR is on lowest\r
68       * interrupt priority and always are disabled during the critical sections\r
69       * of the recorder.\r
70       ***********************************************************************/\r
71 \r
72       vTraceError("Recorder busy - high priority ISR using syscall? (1)");\r
73       return;\r
74     }\r
75 \r
76     if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
77         {\r
78                 if (!TRACE_GET_TASK_FLAG_ISEXCLUDED(handle))\r
79                 {\r
80                         dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
81                         if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
82                         {\r
83                                 tr = (TREvent*)xTraceNextFreeEventBufferSlot();\r
84 \r
85                                 if (tr != NULL)\r
86                                 {\r
87                                         tr->type = DIV_TASK_READY;\r
88                                         tr->dts = dts3;\r
89                                         tr->objHandle = handle;\r
90 \r
91                                         prvTraceUpdateCounters();\r
92                                 }\r
93                         }\r
94                 }\r
95         }\r
96 }\r
97 #endif\r
98 \r
99 /*******************************************************************************\r
100  * vTraceStoreLowPower\r
101  *\r
102  * This function stores a low power state.\r
103  ******************************************************************************/\r
104 void vTraceStoreLowPower(uint32_t flag)\r
105 {\r
106     uint16_t dts;\r
107     LPEvent* lp;\r
108         \r
109         TRACE_ASSERT(flag <= 1, "vTraceStoreLowPower: Invalid flag value", );\r
110 \r
111     if (recorder_busy)\r
112     {\r
113                 /***********************************************************************\r
114                 * This should never occur, as the tick- and kernel call ISR is on lowest\r
115                 * interrupt priority and always are disabled during the critical sections\r
116                 * of the recorder.\r
117                 ***********************************************************************/\r
118           \r
119                 vTraceError("Recorder busy - high priority ISR using syscall? (1)");\r
120                 return;\r
121     }\r
122 \r
123     if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
124         {\r
125                 dts = (uint16_t)prvTraceGetDTS(0xFFFF);\r
126                 if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
127                 {\r
128                         lp = (LPEvent*)xTraceNextFreeEventBufferSlot();\r
129                         if (lp != NULL)\r
130                         {\r
131                                 lp->type = LOW_POWER_BEGIN + flag; /* BEGIN or END depending on flag */\r
132                                 lp->dts = dts;\r
133 \r
134                                 prvTraceUpdateCounters();\r
135                         }\r
136                 }\r
137         }\r
138 }\r
139 \r
140 /*******************************************************************************\r
141  * vTraceStoreKernelCall\r
142  *\r
143  * This is the main integration point for storing kernel calls, and\r
144  * is called by the hooks in trcKernelHooks.h (see trcKernelPort.h for event codes).\r
145  ******************************************************************************/\r
146 void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber)\r
147 {\r
148     KernelCall * kse;\r
149     uint16_t dts1;\r
150         \r
151     TRACE_ASSERT(ecode < 0xFF, "vTraceStoreKernelCall: ecode >= 0xFF", );\r
152     TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCall: objectClass >= TRACE_NCLASSES", );\r
153     TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCall: Invalid value for objectNumber", );\r
154 \r
155     if (recorder_busy)\r
156     {\r
157         /*************************************************************************\r
158         * This may occur if a high-priority ISR is illegally using a system call,\r
159         * or creates a user event.\r
160         * Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls\r
161         * or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).\r
162         *************************************************************************/\r
163 \r
164         vTraceError("Recorder busy - high priority ISR using syscall? (2)");\r
165         return;\r
166     }\r
167 \r
168     if (handle_of_last_logged_task == 0)\r
169     {\r
170         return;\r
171     }\r
172 \r
173     if (RecorderDataPtr->recorderActive)\r
174     {\r
175 \r
176         /* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */\r
177         if (nISRactive || !inExcludedTask)\r
178         {\r
179             /* Check if the referenced object or the event code is excluded */\r
180             if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))\r
181             {\r
182                 trcCRITICAL_SECTION_BEGIN();\r
183                 dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
184 \r
185                 if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
186                 {\r
187                     kse = (KernelCall*) xTraceNextFreeEventBufferSlot();\r
188                     if (kse != NULL)\r
189                     {\r
190                         kse->dts = dts1;\r
191                         kse->type = (uint8_t)ecode;\r
192                         kse->objHandle = (uint8_t)objectNumber;\r
193                         prvTraceUpdateCounters();\r
194                     }\r
195                 }\r
196                 trcCRITICAL_SECTION_END();\r
197             }\r
198         }\r
199     }\r
200 }\r
201 \r
202 /*******************************************************************************\r
203  * vTraceStoreKernelCallWithParam\r
204  *\r
205  * Used for storing kernel calls with a handle and a numeric parameter. This is\r
206  * only used for traceTASK_PRIORITY_SET at the moment.\r
207  ******************************************************************************/\r
208 void vTraceStoreKernelCallWithParam(uint32_t evtcode,\r
209                                     traceObjectClass objectClass,\r
210                                     uint32_t objectNumber,\r
211                                     uint8_t param)\r
212 {\r
213     KernelCallWithParamAndHandle * kse;\r
214     uint8_t dts2;\r
215 \r
216         TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCall: evtcode >= 0xFF", );\r
217         TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCallWithParam: objectClass >= TRACE_NCLASSES", );\r
218         TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCallWithParam: Invalid value for objectNumber", );\r
219 \r
220     if (RecorderDataPtr->recorderActive && handle_of_last_logged_task &&\r
221         (! inExcludedTask || nISRactive))\r
222     {\r
223         if (recorder_busy)\r
224         {\r
225             /*************************************************************************\r
226             * This may occur if a high-priority ISR is illegally using a system call,\r
227             * or creates a user event.\r
228             * Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls\r
229                 * or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).\r
230             *************************************************************************/\r
231 \r
232             vTraceError("Recorder busy - high priority ISR using syscall? (3)");\r
233             return;\r
234         }\r
235 \r
236         /* Check if the referenced object or the event code is excluded */\r
237         if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))\r
238         {\r
239             trcCRITICAL_SECTION_BEGIN();\r
240             dts2 = (uint8_t)prvTraceGetDTS(0xFF);\r
241 \r
242             if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
243             {\r
244                 kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot();\r
245                 if (kse != NULL)\r
246                 {\r
247                     kse->dts = dts2;\r
248                     kse->type = (uint8_t)evtcode;\r
249                     kse->objHandle = (uint8_t)objectNumber;\r
250                     kse->param = param;\r
251                     prvTraceUpdateCounters();\r
252                 }\r
253             }\r
254             trcCRITICAL_SECTION_END();\r
255         }\r
256     }\r
257 }\r
258 \r
259 /*******************************************************************************\r
260  * prvTraceGetParam\r
261  *\r
262  * Used for storing extra bytes for kernel calls with numeric parameters.\r
263  ******************************************************************************/\r
264 static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)\r
265 {\r
266         XPSEvent* xps;\r
267         \r
268         TRACE_ASSERT(param_max == 0xFF || param_max == 0xFFFF, "prvTraceGetParam: Invalid value for param_max", param);\r
269         \r
270         if (param <= param_max)\r
271         {\r
272                 return param;\r
273         }\r
274         else\r
275         {\r
276                 xps = (XPSEvent*) xTraceNextFreeEventBufferSlot();\r
277                 if (xps != NULL)\r
278                 {\r
279                         xps->type = DIV_XPS;\r
280                         xps->xps_8 = (param & (0xFF00 & ~param_max)) >> 8;\r
281                         xps->xps_16 = (param & (0xFFFF0000 & ~param_max)) >> 16;\r
282                         prvTraceUpdateCounters();\r
283                 }\r
284 \r
285                 return param & param_max;\r
286         }\r
287 }\r
288 \r
289 /*******************************************************************************\r
290  * vTraceStoreKernelCallWithNumericParamOnly\r
291  *\r
292  * Used for storing kernel calls with numeric parameters only. This is\r
293  * only used for traceTASK_DELAY and traceDELAY_UNTIL at the moment.\r
294  ******************************************************************************/\r
295 void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)\r
296 {\r
297     KernelCallWithParam16 * kse;\r
298     uint8_t dts6;\r
299         uint16_t restParam = 0;\r
300 \r
301         TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCallWithNumericParamOnly: Invalid value for evtcode", );\r
302         \r
303     if (RecorderDataPtr->recorderActive && handle_of_last_logged_task\r
304         && (! inExcludedTask || nISRactive))\r
305     {\r
306         /* Check if the event code is excluded */\r
307         if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))\r
308         {\r
309             if (recorder_busy)\r
310             {\r
311                 /*************************************************************************\r
312                 * This may occur if a high-priority ISR is illegally using a system call,\r
313                 * or creates a user event.\r
314                 * Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls\r
315                 * or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).\r
316                 *************************************************************************/\r
317 \r
318                 vTraceError("Recorder busy - high priority ISR using syscall? (4)");\r
319                 return;\r
320             }\r
321 \r
322             trcCRITICAL_SECTION_BEGIN();\r
323             dts6 = (uint8_t)prvTraceGetDTS(0xFF);\r
324 \r
325             if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
326             {\r
327                                 restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);\r
328 \r
329                                 if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
330                                 {\r
331                                         kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot();\r
332                                         if (kse != NULL)\r
333                                         {\r
334                                                 kse->dts = dts6;\r
335                                                 kse->type = (uint8_t)evtcode;\r
336                                                 kse->param = restParam;\r
337                                                 prvTraceUpdateCounters();\r
338                                         }\r
339                                 }\r
340             }\r
341             trcCRITICAL_SECTION_END();\r
342         }\r
343     }\r
344 }\r
345 \r
346 /*******************************************************************************\r
347  * vTraceStoreTaskswitch\r
348  * Called by the scheduler from the SWITCHED_OUT hook, and by uiTraceStart.\r
349  * At this point interrupts are assumed to be disabled!\r
350  ******************************************************************************/\r
351 void vTraceStoreTaskswitch(objectHandleType task_handle)\r
352 {\r
353     uint16_t dts3;\r
354     TSEvent* ts;\r
355     int8_t skipEvent = 0;\r
356 \r
357         TRACE_ASSERT(task_handle <= NTask, "vTraceStoreTaskswitch: Invalid value for task_handle", );\r
358         \r
359     /***************************************************************************\r
360     This is used to detect if a high-priority ISRs is illegally using the\r
361     recorder ISR trace functions (vTraceStoreISRBegin and ...End) while the\r
362     recorder is busy with a task-level event or lower priority ISR event.\r
363 \r
364     If this is detected, it triggers a call to vTraceError with the error\r
365     "Illegal call to vTraceStoreISRBegin/End". If you get this error, it means\r
366     that the macro trcCRITICAL_SECTION_BEGIN does not disable this ISR, as required.\r
367 \r
368     Note: Setting recorder_busy is normally handled in our macros\r
369     trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this\r
370     function since critical sections should not be used in the context switch\r
371     event...)\r
372     ***************************************************************************/\r
373     recorder_busy++;\r
374 \r
375     /* Skip the event if the task has been excluded, using vTraceExcludeTask */\r
376     if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle))\r
377     {\r
378         skipEvent = 1;\r
379         inExcludedTask = 1;\r
380     }\r
381     else\r
382         {\r
383         inExcludedTask = 0;\r
384         }\r
385 \r
386         /* Skip the event if the same task is scheduled */\r
387         if (task_handle == handle_of_last_logged_task)\r
388         {\r
389                 skipEvent = 1;\r
390         }\r
391 \r
392 \r
393     if (!RecorderDataPtr->recorderActive)\r
394     {\r
395         skipEvent = 1;\r
396     }\r
397 \r
398     /* If this event should be logged, log it! */\r
399     if (skipEvent == 0)\r
400     {\r
401         dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
402 \r
403         if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
404         {\r
405             handle_of_last_logged_task = task_handle;\r
406             ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
407 \r
408             if (ts != NULL)\r
409             {\r
410                 if (uiTraceGetObjectState(TRACE_CLASS_TASK,\r
411                     handle_of_last_logged_task) == TASK_STATE_INSTANCE_ACTIVE)\r
412                 {\r
413                     ts->type = TS_TASK_RESUME;\r
414                 }\r
415                 else\r
416                 {\r
417                     ts->type = TS_TASK_BEGIN;\r
418                 }\r
419 \r
420                 ts->dts = dts3;\r
421                 ts->objHandle = handle_of_last_logged_task;\r
422 \r
423                 vTraceSetObjectState(TRACE_CLASS_TASK,\r
424                                      handle_of_last_logged_task,\r
425                                      TASK_STATE_INSTANCE_ACTIVE);\r
426 \r
427                 prvTraceUpdateCounters();\r
428             }\r
429         }\r
430     }\r
431 \r
432     /* See comment on recorder_busy++ above. */\r
433     recorder_busy--;\r
434 }\r
435 \r
436 /*******************************************************************************\r
437  * vTraceStoreNameCloseEvent\r
438  *\r
439  * Updates the symbol table with the name of this object from the dynamic\r
440  * objects table and stores a "close" event, holding the mapping between handle\r
441  * and name (a symbol table handle). The stored name-handle mapping is thus the\r
442  * "old" one, valid up until this point.\r
443  ******************************************************************************/\r
444 #if (INCLUDE_OBJECT_DELETE == 1)\r
445 void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,\r
446                                        traceObjectClass objectclass)\r
447 {\r
448     ObjCloseNameEvent * ce;\r
449     const char * name;\r
450     traceLabel idx;\r
451 \r
452         TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceStoreObjectNameOnCloseEvent: objectclass >= TRACE_NCLASSES", );\r
453         TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceStoreObjectNameOnCloseEvent: Invalid value for handle", );\r
454 \r
455     if (RecorderDataPtr->recorderActive)\r
456         {\r
457                 name = TRACE_PROPERTY_NAME_GET(objectclass, handle);\r
458 \r
459                 idx = prvTraceOpenSymbol(name, 0);\r
460 \r
461                 // Interrupt disable not necessary, already done in trcHooks.h macro\r
462                 ce = (ObjCloseNameEvent*) xTraceNextFreeEventBufferSlot();\r
463                 if (ce != NULL)\r
464                 {\r
465                         ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass;\r
466                         ce->objHandle = handle;\r
467                         ce->symbolIndex = idx;\r
468                         prvTraceUpdateCounters();\r
469                 }\r
470         }\r
471 }\r
472 \r
473 void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,\r
474                                              traceObjectClass objectclass)\r
475 {\r
476     ObjClosePropEvent * pe;\r
477         \r
478     TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceStoreObjectPropertiesOnCloseEvent: objectclass >= TRACE_NCLASSES", );\r
479     TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceStoreObjectPropertiesOnCloseEvent: Invalid value for handle", );\r
480 \r
481     if (RecorderDataPtr->recorderActive)\r
482         {\r
483                 // Interrupt disable not necessary, already done in trcHooks.h macro\r
484                 pe = (ObjClosePropEvent*) xTraceNextFreeEventBufferSlot();\r
485                 if (pe != NULL)\r
486                 {\r
487                         if (objectclass == TRACE_CLASS_TASK)\r
488                         {\r
489                                 pe->arg1 = TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle);\r
490                                 pe->arg2 = 0; // Legacy - IFE info removed.\r
491                                 pe->arg3 = 0; // Legacy - IFE info removed.\r
492                         }else{\r
493                                 pe->arg1 = TRACE_PROPERTY_OBJECT_STATE(objectclass, handle);\r
494                         }\r
495                         pe->type = EVENTGROUP_OBJCLOSE_PROP + objectclass;\r
496                         prvTraceUpdateCounters();\r
497                 }\r
498         }\r
499 }\r
500 #endif\r
501 \r
502 void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value)\r
503 {\r
504         TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceSetPriorityProperty: objectclass >= TRACE_NCLASSES", );\r
505         TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceSetPriorityProperty: Invalid value for id", );\r
506 \r
507     TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id) = value;\r
508 }\r
509 \r
510 uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id)\r
511 {\r
512         TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetPriorityProperty: objectclass >= TRACE_NCLASSES", 0);\r
513         TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetPriorityProperty: Invalid value for id", 0);\r
514 \r
515     return TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id);\r
516 }\r
517 \r
518 void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value)\r
519 {\r
520         TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceSetObjectState: objectclass >= TRACE_NCLASSES", );\r
521         TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceSetObjectState: Invalid value for id", );\r
522         \r
523     TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value;\r
524 }\r
525 \r
526 uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id)\r
527 {\r
528         TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetObjectState: objectclass >= TRACE_NCLASSES", 0);\r
529         TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetObjectState: Invalid value for id", 0);\r
530         \r
531     return TRACE_PROPERTY_OBJECT_STATE(objectclass, id);\r
532 }\r
533 \r
534 void vTraceSetTaskInstanceFinished(objectHandleType handle)\r
535 {\r
536         TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_TASK], "vTraceSetTaskInstanceFinished: Invalid value for handle", );\r
537         \r
538 #if (USE_IMPLICIT_IFE_RULES == 1)\r
539     TRACE_PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle) = 0;    \r
540 #endif\r
541 }\r
542 \r
543 #endif