Trace function
Example implementation of a trace function.
The function traces PxTrace() call arguments alongside the timestamp when the trace entry is added to the buffer. The atomic reading of the STM is used to get a 64-bit value timestamp. The trace function first checks if the current task should be traced or not. If not, the function still traces the Enter scheduling service as a special case to trace task scheduling. If the task should be traced, the entry is added in the following two cases:
-
the call is done by the user
-
the PXROS-HR service should be traced
The user argument of the trace entry is used to mark that the PxTrace() call of the PXROS-HR services was done in a handler.
#include "bsp.h"
#include "pxdef.h"
#include "pxtrace_internal.h"
#include "pxservices.h"
#define PXSV_USER 300
typedef struct
{
PxUShort_t Type; /* Service type */
PxUShort_t From; /* Task ID that called PxTrace */
PxUShort_t Error; /* Error passed to PxTrace */
PxUShort_t UserArg; /* User-defined argument */
PxULong_t Data1; /* Argument 1 to PxTrace */
PxULong_t Data2; /* Argument 2 to PxTrace */
} TraceUserEntry_t;
typedef struct
{
unsigned long long timestamp;
TraceUserEntry_t traceUserEntry;
} TraceEntry_t;
/**************************************************************************************
* _IPxvGetCurrentTime
*
* Description
* Atomic time reading function from the STM. The time stamp is 64bit value
*************************************************************************************/
__attribute__ ((always_inline)) static inline long long _IPxvGetCurrentTime()
{
union
{
struct
{
PxUInt_t lo;
PxUInt_t up;
} u;
PxUInt64_t ll;
} timestamp;
timestamp.u.lo = STM0_TIM0.U;
timestamp.u.up = STM0_CAP.U;
return timestamp.ll;
}
/**************************************************************************************
* traceAddEntry
*
* Description
* Adds a new entry log into the trace buffer, Time stamp and user entry data
*************************************************************************************/
__attribute__ ((always_inline)) static inline void traceAddEntry(
TraceUserEntry_t userentry)
{
/* Get the next trace entry */
TraceEntry_t *PxvEntry = (TraceEntry_t*) IPxTraceGetNextEntry();
if (PxvEntry != 0)
{
/* Adds the time stamp to buffer entry */
PxvEntry->timestamp = _IPxvGetCurrentTime();
/* Adds the user data to buffer entry */
PxvEntry->traceUserEntry = userentry;
}
}
/**************************************************************************************
* Trace function
*
* Description
* The function adds the log/report into the trace buffer.
*************************************************************************************/
void traceFunc(PxInt_t svType, PxArg_t Arg1, PxArg_t Arg2, PxError_t err)
{
PxBool_t addEntry = 0;
TraceUserEntry_t userentry;
PxTask_t runtask = IPxTraceGetRunTaskID();
PxUInt_t Task = runtask.id;
PxUShort_t userArg = 0;
PxBool_t traceRuntask = IPxTraceCheckTask(runtask);
PxULong_t GroupMask = IPxTraceGetGroupMask();
/* Should the PxTrace call from the task be traced?
* The case for Scheduling events will be treated in the else case */
if (traceRuntask)
{
/* Check if the call is done by a user */
if (svType >= PXSV_USER)
{
/* Check if user PxTrace call should be traced */
if (GroupMask & PXVT_USER)
{
addEntry = true;
}
}
else
{
/* Check if the service should be traced */
if (IPxTraceCheckService(svType))
{
/* Is the call coming from a handler? */
if (PxTaskIdIsValid(IPxTraceGetHandlerTaskID()))
{
userArg = 1; // mark that the call is done by a handler
}
addEntry = true;
}
}
}
else
{
/* Special case */
if (svType == PXSvTraceEnterScheduling)
{
addEntry = true;
}
}
if (addEntry)
{
userentry.Type = (PxUShort_t) svType;
userentry.From = (PxUShort_t) Task;
userentry.Error = (PxUShort_t) err;
userentry.UserArg = (PxUShort_t) userArg;
userentry.Data1 = (PxULong_t) Arg1;
userentry.Data2 = (PxULong_t) Arg2;
traceAddEntry(userentry);
}
}