You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
680 lines
23 KiB
C
680 lines
23 KiB
C
/*******************************************************************************
|
|
* Tracealyzer v2.7.7 Recorder Library
|
|
* Percepio AB, www.percepio.com
|
|
*
|
|
* trcKernel.c
|
|
*
|
|
* Functions used by trcKernelHooks.h for storing various kernel events.
|
|
*
|
|
* Terms of Use
|
|
* This software is copyright Percepio AB. The recorder library is free for
|
|
* use together with Percepio products. You may distribute the recorder library
|
|
* in its original form, including modifications in trcHardwarePort.c/.h
|
|
* given that these modification are clearly marked as your own modifications
|
|
* and documented in the initial comment section of these source files.
|
|
* This software is the intellectual property of Percepio AB and may not be
|
|
* sold or in other ways commercially redistributed without explicit written
|
|
* permission by Percepio AB.
|
|
*
|
|
* Disclaimer
|
|
* The trace tool and recorder library is being delivered to you AS IS and
|
|
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
|
|
* not and cannot warrant the performance or results you may obtain by using the
|
|
* software or documentation. Percepio AB make no warranties, express or
|
|
* implied, as to noninfringement of third party rights, merchantability, or
|
|
* fitness for any particular purpose. In no event will Percepio AB, its
|
|
* technology partners, or distributors be liable to you for any consequential,
|
|
* incidental or special damages, including any lost profits or lost savings,
|
|
* even if a representative of Percepio AB has been advised of the possibility
|
|
* of such damages, or for any claim by any third party. Some jurisdictions do
|
|
* not allow the exclusion or limitation of incidental, consequential or special
|
|
* damages, or the exclusion of implied warranties or limitations on how long an
|
|
* implied warranty may last, so the above limitations may not apply to you.
|
|
*
|
|
* Tabs are used for indent in this file (1 tab = 4 spaces)
|
|
*
|
|
* Copyright Percepio AB, 2012-2015.
|
|
* www.percepio.com
|
|
******************************************************************************/
|
|
|
|
#include "trcKernel.h"
|
|
|
|
#if (USE_TRACEALYZER_RECORDER == 1)
|
|
|
|
#include <stdint.h>
|
|
|
|
/* Internal variables */
|
|
int8_t nISRactive = 0;
|
|
objectHandleType handle_of_last_logged_task = 0;
|
|
uint8_t inExcludedTask = 0;
|
|
|
|
#if (INCLUDE_MEMMANG_EVENTS == 1)
|
|
/* Current heap usage. Always updated. */
|
|
static uint32_t heapMemUsage = 0;
|
|
#endif
|
|
|
|
#if (TRACE_SCHEDULING_ONLY == 0)
|
|
static uint32_t prvTraceGetParam(uint32_t, uint32_t);
|
|
#endif
|
|
|
|
#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1
|
|
|
|
static int readyEventsEnabled = 1;
|
|
|
|
void vTraceSetReadyEventsEnabled(int status)
|
|
{
|
|
readyEventsEnabled = status;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* vTraceStoreTaskReady
|
|
*
|
|
* This function stores a ready state for the task handle sent in as parameter.
|
|
******************************************************************************/
|
|
void vTraceStoreTaskReady(objectHandleType handle)
|
|
{
|
|
uint16_t dts3;
|
|
TREvent* tr;
|
|
uint8_t hnd8;
|
|
|
|
TRACE_SR_ALLOC_CRITICAL_SECTION();
|
|
|
|
if (handle == 0)
|
|
{
|
|
/* On FreeRTOS v7.3.0, this occurs when creating tasks due to a bad
|
|
placement of the trace macro. In that case, the events are ignored. */
|
|
return;
|
|
}
|
|
|
|
if (! readyEventsEnabled)
|
|
{
|
|
/* When creating tasks, ready events are also created. If creating
|
|
a "hidden" (not traced) task, we must therefore disable recording
|
|
of ready events to avoid an undesired ready event... */
|
|
return;
|
|
}
|
|
|
|
TRACE_ASSERT(handle <= NTask, "vTraceStoreTaskReady: Invalid value for handle", );
|
|
|
|
if (recorder_busy)
|
|
{
|
|
/***********************************************************************
|
|
* This should never occur, as the tick- and kernel call ISR is on lowest
|
|
* interrupt priority and always are disabled during the critical sections
|
|
* of the recorder.
|
|
***********************************************************************/
|
|
|
|
vTraceError("Recorder busy - high priority ISR using syscall? (1)");
|
|
return;
|
|
}
|
|
|
|
trcCRITICAL_SECTION_BEGIN();
|
|
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
|
|
{
|
|
if (!TRACE_GET_TASK_FLAG_ISEXCLUDED(handle))
|
|
{
|
|
dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
|
|
hnd8 = prvTraceGet8BitHandle(handle);
|
|
tr = (TREvent*)xTraceNextFreeEventBufferSlot();
|
|
if (tr != NULL)
|
|
{
|
|
tr->type = DIV_TASK_READY;
|
|
tr->dts = dts3;
|
|
tr->objHandle = hnd8;
|
|
prvTraceUpdateCounters();
|
|
}
|
|
}
|
|
}
|
|
trcCRITICAL_SECTION_END();
|
|
}
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* vTraceStoreLowPower
|
|
*
|
|
* This function stores a low power state.
|
|
******************************************************************************/
|
|
void vTraceStoreLowPower(uint32_t flag)
|
|
{
|
|
uint16_t dts;
|
|
LPEvent* lp;
|
|
TRACE_SR_ALLOC_CRITICAL_SECTION();
|
|
|
|
TRACE_ASSERT(flag <= 1, "vTraceStoreLowPower: Invalid flag value", );
|
|
|
|
if (recorder_busy)
|
|
{
|
|
/***********************************************************************
|
|
* This should never occur, as the tick- and kernel call ISR is on lowest
|
|
* interrupt priority and always are disabled during the critical sections
|
|
* of the recorder.
|
|
***********************************************************************/
|
|
|
|
vTraceError("Recorder busy - high priority ISR using syscall? (1)");
|
|
return;
|
|
}
|
|
|
|
trcCRITICAL_SECTION_BEGIN();
|
|
if (RecorderDataPtr->recorderActive)
|
|
{
|
|
dts = (uint16_t)prvTraceGetDTS(0xFFFF);
|
|
lp = (LPEvent*)xTraceNextFreeEventBufferSlot();
|
|
if (lp != NULL)
|
|
{
|
|
lp->type = LOW_POWER_BEGIN + ( uint8_t ) flag; /* BEGIN or END depending on flag */
|
|
lp->dts = dts;
|
|
prvTraceUpdateCounters();
|
|
}
|
|
}
|
|
trcCRITICAL_SECTION_END();
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* vTraceStoreMemMangEvent
|
|
*
|
|
* This function stores malloc and free events. Each call requires two records,
|
|
* for size and address respectively. The event code parameter (ecode) is applied
|
|
* to the first record (size) and the following address record gets event
|
|
* code "ecode + 1", so make sure this is respected in the event code table.
|
|
* Note: On "free" calls, the signed_size parameter should be negative.
|
|
******************************************************************************/
|
|
#if (INCLUDE_MEMMANG_EVENTS == 1)
|
|
void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_size)
|
|
{
|
|
#if (TRACE_SCHEDULING_ONLY == 0)
|
|
uint8_t dts1;
|
|
MemEventSize * ms;
|
|
MemEventAddr * ma;
|
|
uint16_t size_low;
|
|
uint16_t addr_low;
|
|
uint8_t addr_high;
|
|
uint32_t size;
|
|
TRACE_SR_ALLOC_CRITICAL_SECTION();
|
|
|
|
if (RecorderDataPtr == NULL) // This happens in vTraceInitTraceData, if using dynamic allocation...
|
|
return;
|
|
|
|
if (signed_size < 0)
|
|
size = (uint32_t)(- signed_size);
|
|
else
|
|
size = (uint32_t)(signed_size);
|
|
|
|
trcCRITICAL_SECTION_BEGIN();
|
|
|
|
heapMemUsage += signed_size;
|
|
|
|
if (RecorderDataPtr->recorderActive)
|
|
{
|
|
/* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */
|
|
if (nISRactive || !inExcludedTask)
|
|
{
|
|
dts1 = (uint8_t)prvTraceGetDTS(0xFF);
|
|
size_low = (uint16_t)prvTraceGetParam(0xFFFF, size);
|
|
ms = (MemEventSize *)xTraceNextFreeEventBufferSlot();
|
|
|
|
if (ms != NULL)
|
|
{
|
|
ms->dts = dts1;
|
|
ms->type = NULL_EVENT; /* Updated when all events are written */
|
|
ms->size = size_low;
|
|
prvTraceUpdateCounters();
|
|
|
|
/* Storing a second record with address (signals "failed" if null) */
|
|
#if (HEAP_SIZE_BELOW_16M)
|
|
/* If the heap address range is within 16 MB, i.e., the upper 8 bits
|
|
of addresses are constant, this optimization avoids storing an extra
|
|
event record by ignoring the upper 8 bit of the address */
|
|
addr_low = address & 0xFFFF;
|
|
addr_high = (address >> 16) & 0xFF;
|
|
#else
|
|
/* The whole 32 bit address is stored using a second event record
|
|
for the upper 16 bit */
|
|
addr_low = (uint16_t)prvTraceGetParam(0xFFFF, address);
|
|
addr_high = 0;
|
|
#endif
|
|
|
|
ma = (MemEventAddr *) xTraceNextFreeEventBufferSlot();
|
|
if (ma != NULL)
|
|
{
|
|
ma->addr_low = addr_low;
|
|
ma->addr_high = addr_high;
|
|
ma->type = ( ( uint8_t) ecode ) + 1; /* Note this! */
|
|
ms->type = (uint8_t)ecode;
|
|
prvTraceUpdateCounters();
|
|
RecorderDataPtr->heapMemUsage = heapMemUsage;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
trcCRITICAL_SECTION_END();
|
|
#endif /* TRACE_SCHEDULING_ONLY */
|
|
}
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* vTraceStoreKernelCall
|
|
*
|
|
* This is the main integration point for storing kernel calls, and
|
|
* is called by the hooks in trcKernelHooks.h (see trcKernelPort.h for event codes).
|
|
******************************************************************************/
|
|
void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber)
|
|
{
|
|
#if (TRACE_SCHEDULING_ONLY == 0)
|
|
KernelCall * kse;
|
|
uint16_t dts1;
|
|
uint8_t hnd8;
|
|
TRACE_SR_ALLOC_CRITICAL_SECTION();
|
|
|
|
TRACE_ASSERT(ecode < 0xFF, "vTraceStoreKernelCall: ecode >= 0xFF", );
|
|
TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCall: objectClass >= TRACE_NCLASSES", );
|
|
TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCall: Invalid value for objectNumber", );
|
|
|
|
if (recorder_busy)
|
|
{
|
|
/*************************************************************************
|
|
* This may occur if a high-priority ISR is illegally using a system call,
|
|
* or creates a user event.
|
|
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
|
|
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
|
|
*************************************************************************/
|
|
|
|
vTraceError("Recorder busy - high priority ISR using syscall? (2)");
|
|
return;
|
|
}
|
|
|
|
if (handle_of_last_logged_task == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
trcCRITICAL_SECTION_BEGIN();
|
|
if (RecorderDataPtr->recorderActive)
|
|
{
|
|
/* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */
|
|
if (nISRactive || !inExcludedTask)
|
|
{
|
|
/* Check if the referenced object or the event code is excluded */
|
|
if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))
|
|
{
|
|
dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);
|
|
hnd8 = prvTraceGet8BitHandle(objectNumber);
|
|
kse = (KernelCall*) xTraceNextFreeEventBufferSlot();
|
|
if (kse != NULL)
|
|
{
|
|
kse->dts = dts1;
|
|
kse->type = (uint8_t)ecode;
|
|
kse->objHandle = hnd8;
|
|
prvTraceUpdateCounters();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
trcCRITICAL_SECTION_END();
|
|
#endif /* TRACE_SCHEDULING_ONLY */
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* vTraceStoreKernelCallWithParam
|
|
*
|
|
* Used for storing kernel calls with a handle and a numeric parameter. If the
|
|
* numeric parameter does not fit in one byte, and extra XPS event is inserted
|
|
* before the kernel call event containing the three upper bytes.
|
|
******************************************************************************/
|
|
void vTraceStoreKernelCallWithParam(uint32_t evtcode,
|
|
traceObjectClass objectClass,
|
|
uint32_t objectNumber,
|
|
uint32_t param)
|
|
{
|
|
#if (TRACE_SCHEDULING_ONLY == 0)
|
|
KernelCallWithParamAndHandle * kse;
|
|
uint8_t dts2;
|
|
uint8_t hnd8;
|
|
uint8_t p8;
|
|
TRACE_SR_ALLOC_CRITICAL_SECTION();
|
|
|
|
TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCall: evtcode >= 0xFF", );
|
|
TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCallWithParam: objectClass >= TRACE_NCLASSES", );
|
|
TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCallWithParam: Invalid value for objectNumber", );
|
|
|
|
if (recorder_busy)
|
|
{
|
|
/*************************************************************************
|
|
* This may occur if a high-priority ISR is illegally using a system call,
|
|
* or creates a user event.
|
|
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
|
|
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
|
|
*************************************************************************/
|
|
|
|
vTraceError("Recorder busy - high priority ISR using syscall? (3)");
|
|
return;
|
|
}
|
|
|
|
trcCRITICAL_SECTION_BEGIN();
|
|
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && (! inExcludedTask || nISRactive))
|
|
{
|
|
/* Check if the referenced object or the event code is excluded */
|
|
if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) &&
|
|
!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
|
|
{
|
|
dts2 = (uint8_t)prvTraceGetDTS(0xFF);
|
|
p8 = (uint8_t) prvTraceGetParam(0xFF, param);
|
|
hnd8 = prvTraceGet8BitHandle((objectHandleType)objectNumber);
|
|
kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot();
|
|
if (kse != NULL)
|
|
{
|
|
kse->dts = dts2;
|
|
kse->type = (uint8_t)evtcode;
|
|
kse->objHandle = hnd8;
|
|
kse->param = p8;
|
|
prvTraceUpdateCounters();
|
|
}
|
|
}
|
|
}
|
|
trcCRITICAL_SECTION_END();
|
|
#endif /* TRACE_SCHEDULING_ONLY */
|
|
}
|
|
|
|
#if (TRACE_SCHEDULING_ONLY == 0)
|
|
|
|
/*******************************************************************************
|
|
* prvTraceGetParam
|
|
*
|
|
* Used for storing extra bytes for kernel calls with numeric parameters.
|
|
*
|
|
* May only be called within a critical section!
|
|
******************************************************************************/
|
|
static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)
|
|
{
|
|
XPSEvent* xps;
|
|
|
|
TRACE_ASSERT(param_max == 0xFF || param_max == 0xFFFF,
|
|
"prvTraceGetParam: Invalid value for param_max", param);
|
|
|
|
if (param <= param_max)
|
|
{
|
|
return param;
|
|
}
|
|
else
|
|
{
|
|
xps = (XPSEvent*) xTraceNextFreeEventBufferSlot();
|
|
if (xps != NULL)
|
|
{
|
|
xps->type = DIV_XPS;
|
|
xps->xps_8 = (param & (0xFF00 & ~param_max)) >> 8;
|
|
xps->xps_16 = (param & (0xFFFF0000 & ~param_max)) >> 16;
|
|
prvTraceUpdateCounters();
|
|
}
|
|
|
|
return param & param_max;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* vTraceStoreKernelCallWithNumericParamOnly
|
|
*
|
|
* Used for storing kernel calls with numeric parameters only. This is
|
|
* only used for traceTASK_DELAY and traceDELAY_UNTIL at the moment.
|
|
******************************************************************************/
|
|
void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
|
|
{
|
|
#if (TRACE_SCHEDULING_ONLY == 0)
|
|
KernelCallWithParam16 * kse;
|
|
uint8_t dts6;
|
|
uint16_t restParam;
|
|
TRACE_SR_ALLOC_CRITICAL_SECTION();
|
|
|
|
restParam = 0;
|
|
|
|
TRACE_ASSERT(evtcode < 0xFF,
|
|
"vTraceStoreKernelCallWithNumericParamOnly: Invalid value for evtcode", );
|
|
|
|
if (recorder_busy)
|
|
{
|
|
/*************************************************************************
|
|
* This may occur if a high-priority ISR is illegally using a system call,
|
|
* or creates a user event.
|
|
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
|
|
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
|
|
*************************************************************************/
|
|
|
|
vTraceError("Recorder busy - high priority ISR using syscall? (4)");
|
|
return;
|
|
}
|
|
|
|
trcCRITICAL_SECTION_BEGIN();
|
|
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task
|
|
&& (! inExcludedTask || nISRactive))
|
|
{
|
|
/* Check if the event code is excluded */
|
|
if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
|
|
{
|
|
dts6 = (uint8_t)prvTraceGetDTS(0xFF);
|
|
restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);
|
|
kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot();
|
|
if (kse != NULL)
|
|
{
|
|
kse->dts = dts6;
|
|
kse->type = (uint8_t)evtcode;
|
|
kse->param = restParam;
|
|
prvTraceUpdateCounters();
|
|
}
|
|
}
|
|
}
|
|
trcCRITICAL_SECTION_END();
|
|
#endif /* TRACE_SCHEDULING_ONLY */
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* vTraceStoreTaskswitch
|
|
* Called by the scheduler from the SWITCHED_OUT hook, and by uiTraceStart.
|
|
* At this point interrupts are assumed to be disabled!
|
|
******************************************************************************/
|
|
void vTraceStoreTaskswitch(objectHandleType task_handle)
|
|
{
|
|
uint16_t dts3;
|
|
TSEvent* ts;
|
|
int8_t skipEvent;
|
|
uint8_t hnd8;
|
|
TRACE_SR_ALLOC_CRITICAL_SECTION();
|
|
|
|
skipEvent = 0;
|
|
|
|
TRACE_ASSERT(task_handle <= NTask,
|
|
"vTraceStoreTaskswitch: Invalid value for task_handle", );
|
|
|
|
/***************************************************************************
|
|
This is used to detect if a high-priority ISRs is illegally using the
|
|
recorder ISR trace functions (vTraceStoreISRBegin and ...End) while the
|
|
recorder is busy with a task-level event or lower priority ISR event.
|
|
|
|
If this is detected, it triggers a call to vTraceError with the error
|
|
"Illegal call to vTraceStoreISRBegin/End". If you get this error, it means
|
|
that the macro trcCRITICAL_SECTION_BEGIN does not disable this ISR, as required.
|
|
|
|
Note: Setting recorder_busy is normally handled in our macros
|
|
trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this
|
|
function since critical sections should not be used in the context switch
|
|
event...)
|
|
***************************************************************************/
|
|
|
|
/* Skip the event if the task has been excluded, using vTraceExcludeTask */
|
|
if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle))
|
|
{
|
|
skipEvent = 1;
|
|
inExcludedTask = 1;
|
|
}
|
|
else
|
|
{
|
|
inExcludedTask = 0;
|
|
}
|
|
|
|
trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY();
|
|
|
|
/* Skip the event if the same task is scheduled */
|
|
if (task_handle == handle_of_last_logged_task)
|
|
{
|
|
skipEvent = 1;
|
|
}
|
|
|
|
if (!RecorderDataPtr->recorderActive)
|
|
{
|
|
skipEvent = 1;
|
|
}
|
|
|
|
/* If this event should be logged, log it! */
|
|
if (skipEvent == 0)
|
|
{
|
|
dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
|
|
handle_of_last_logged_task = task_handle;
|
|
hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task);
|
|
ts = (TSEvent*)xTraceNextFreeEventBufferSlot();
|
|
|
|
if (ts != NULL)
|
|
{
|
|
if (uiTraceGetObjectState(TRACE_CLASS_TASK,
|
|
handle_of_last_logged_task) == TASK_STATE_INSTANCE_ACTIVE)
|
|
{
|
|
ts->type = TS_TASK_RESUME;
|
|
}
|
|
else
|
|
{
|
|
ts->type = TS_TASK_BEGIN;
|
|
}
|
|
|
|
ts->dts = dts3;
|
|
ts->objHandle = hnd8;
|
|
|
|
vTraceSetObjectState(TRACE_CLASS_TASK,
|
|
handle_of_last_logged_task,
|
|
TASK_STATE_INSTANCE_ACTIVE);
|
|
|
|
prvTraceUpdateCounters();
|
|
}
|
|
}
|
|
|
|
trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY();
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* vTraceStoreNameCloseEvent
|
|
*
|
|
* Updates the symbol table with the name of this object from the dynamic
|
|
* objects table and stores a "close" event, holding the mapping between handle
|
|
* and name (a symbol table handle). The stored name-handle mapping is thus the
|
|
* "old" one, valid up until this point.
|
|
******************************************************************************/
|
|
#if (INCLUDE_OBJECT_DELETE == 1)
|
|
void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
|
|
traceObjectClass objectclass)
|
|
{
|
|
ObjCloseNameEvent * ce;
|
|
const char * name;
|
|
traceLabel idx;
|
|
|
|
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
|
|
"vTraceStoreObjectNameOnCloseEvent: objectclass >= TRACE_NCLASSES", );
|
|
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
|
|
"vTraceStoreObjectNameOnCloseEvent: Invalid value for handle", );
|
|
|
|
if (RecorderDataPtr->recorderActive)
|
|
{
|
|
uint8_t hnd8 = prvTraceGet8BitHandle(handle);
|
|
name = TRACE_PROPERTY_NAME_GET(objectclass, handle);
|
|
idx = prvTraceOpenSymbol(name, 0);
|
|
|
|
// Interrupt disable not necessary, already done in trcHooks.h macro
|
|
ce = (ObjCloseNameEvent*) xTraceNextFreeEventBufferSlot();
|
|
if (ce != NULL)
|
|
{
|
|
ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass;
|
|
ce->objHandle = hnd8;
|
|
ce->symbolIndex = idx;
|
|
prvTraceUpdateCounters();
|
|
}
|
|
}
|
|
}
|
|
|
|
void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
|
|
traceObjectClass objectclass)
|
|
{
|
|
ObjClosePropEvent * pe;
|
|
|
|
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
|
|
"vTraceStoreObjectPropertiesOnCloseEvent: objectclass >= TRACE_NCLASSES", );
|
|
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
|
|
"vTraceStoreObjectPropertiesOnCloseEvent: Invalid value for handle", );
|
|
|
|
if (RecorderDataPtr->recorderActive)
|
|
{
|
|
// Interrupt disable not necessary, already done in trcHooks.h macro
|
|
pe = (ObjClosePropEvent*) xTraceNextFreeEventBufferSlot();
|
|
if (pe != NULL)
|
|
{
|
|
if (objectclass == TRACE_CLASS_TASK)
|
|
{
|
|
pe->arg1 = TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle);
|
|
}
|
|
else
|
|
{
|
|
pe->arg1 = TRACE_PROPERTY_OBJECT_STATE(objectclass, handle);
|
|
}
|
|
pe->type = EVENTGROUP_OBJCLOSE_PROP + objectclass;
|
|
prvTraceUpdateCounters();
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void vTraceSetPriorityProperty(uint8_t objectclass, objectHandleType id, uint8_t value)
|
|
{
|
|
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
|
|
"vTraceSetPriorityProperty: objectclass >= TRACE_NCLASSES", );
|
|
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
|
|
"vTraceSetPriorityProperty: Invalid value for id", );
|
|
|
|
TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id) = value;
|
|
}
|
|
|
|
uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, objectHandleType id)
|
|
{
|
|
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
|
|
"uiTraceGetPriorityProperty: Invalid objectclass number (>= TRACE_NCLASSES)", 0);
|
|
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
|
|
"uiTraceGetPriorityProperty: Task handle exceeds NTask. You may need to increase this constant in trcConfig.h.", 0);
|
|
|
|
return TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id);
|
|
}
|
|
|
|
void vTraceSetObjectState(uint8_t objectclass, objectHandleType id, uint8_t value)
|
|
{
|
|
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
|
|
"vTraceSetObjectState: objectclass >= TRACE_NCLASSES", );
|
|
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
|
|
"vTraceSetObjectState: Invalid value for id", );
|
|
|
|
TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value;
|
|
}
|
|
|
|
uint8_t uiTraceGetObjectState(uint8_t objectclass, objectHandleType id)
|
|
{
|
|
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
|
|
"uiTraceGetObjectState: objectclass >= TRACE_NCLASSES", 0);
|
|
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
|
|
"uiTraceGetObjectState: Invalid value for id", 0);
|
|
|
|
return TRACE_PROPERTY_OBJECT_STATE(objectclass, id);
|
|
}
|
|
|
|
void vTraceSetTaskInstanceFinished(objectHandleType handle)
|
|
{
|
|
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_TASK],
|
|
"vTraceSetTaskInstanceFinished: Invalid value for handle", );
|
|
|
|
#if (USE_IMPLICIT_IFE_RULES == 1)
|
|
TRACE_PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle) = 0;
|
|
#endif
|
|
}
|
|
|
|
#endif
|