Trace system description
The trace mechanism allows tracing PXROS-HR kernel activities during the execution of an application. If this module is activated, the kernel saves all service calls and user-defined records into the predefined trace buffer.
Defining a trace buffer
To use the trace mechanism of PXROS-HR, a user needs to define a memory area for the circular trace buffer. The memory area must be aligned to MPU restrictions (8B).
The memory block for the trace buffer must be writable and readable by the PXROS-HR kernel. In the example below, the buffer is placed in the system memory. The buffer size must be a multiple of the size of a trace entry — currently 24 bytes.
/* Size of one element in trace circular buffer */
#define TRACE_ENTRY_SIZE 24
/* Calculate size of trace circular buffer */
#define TRACE_ARRAY_SIZE(x) ((x) * TRACE_ENTRY_SIZE)
/* Number of trace entries */
#define TRACE_BUFFER_ENTRIES 500
Buffer area
There are two possible ways of how to allocate a buffer in system memory:
-
Static declaration during compile time
Code 2. Defining a trace buffer/* Trace buffer must be accessible by the PXROS-HR Kernel */ #pragma section ".CPU0.systemmemory" 8 awB PxAligned_t traceBuffer_CPU0[(TRACE_ARRAY_SIZE(TRACE_BUFFER_ENTRIES) + sizeof(PxAligned_t) - 1) / sizeof(PxAligned_t)] PXMEM_ALIGNED; #pragma sectionIt is necessary to set the
ReadProtectionorWRProtectionpermission to the buffer for the task that will assign it later as a trace buffer. -
Dynamic request during runtime
In this case, the task that will later assign the trace buffer must request the memory block from the system default memory class by calling the
PxMcTakeBlk()kernel service. This task must never be terminated; otherwise, the kernel would release all task resources, including the memory block for the trace buffer. It is necessary to enlarge the system memory by the trace buffer’s size not to affect the space for task control blocks (TCBs). TheSYSMEMSIZE_COREX(X = 0-5) is modified accordingly in the example below.Code 3. System memory size modification in "system_cfg.c"/* System memory (PXMcSystemdefault) shall be large enough to allow * allocation of all core's task control block (TCB) and to provide * all additional memory. */ #pragma section ".CPU0.systemmemory" 8 awB #define SYSMEMSIZE_CORE0 (PXMEM_ADJUST((NUM_OF_TASKS_CORE0) * (PXTASK_SIZE + PXMCVARSIZED_ADDON) + TRACE_ARRAY_SIZE(TRACE_BUFFER_ENTRIES))) PxMemAligned_t Sysmem_Core0[SYSMEMSIZE_CORE0 / sizeof(PxMemAligned_t)]; #pragma sectionCode 4. Definition and allocation in task functionPxMptr_t buffer; /* Taking a block from system default class */ buffer = PxMcTakeBlk(PXMcSystemdefault, TRACE_ARRAY_SIZE(TRACE_BUFFER_ENTRIES)); if(!buffer) { PxPanic(); } /* Clear the buffer */ PxBzero((PxUChar_t *)buffer, TRACE_ARRAY_SIZE(TRACE_BUFFER_ENTRIES));
Assigning the trace buffer to PXROS-HR is done through the PxTraceAssignBuffer() function:
/* Assign trace buffer */
PxError_t error = PxTraceAssignBuffer(traceBuffer_CPU0,
TRACE_BUFFER_ENTRIES,
TRACE_ENTRY_SIZE);
if (error != PXERR_NOERROR)
PxPanic();
The TRACE_ENTRY_SIZE must be given in bytes, and it must be 24 bytes for version 8.2.0 (or newer). An assigning task must have ReadProtection or WRProtection permission to the trace buffer.
Trace function
Besides assigning the trace buffer, the user must define a trace function PXROS-HR uses as a trace callback (hook). The trace function must have the following prototype:
typedef void (*PxTraceFunc_t)(PxInt_t, PxArg_t, PxArg_t, PxError_t);
For example, a trace function can be defined as follows:
void traceFunc(PxInt_t serviceType, PxArg_t Arg1, PxArg_t Arg2, PxError_t error)
{
/* Implementation */
}
The trace function is assigned to the system through one of these PXROS-HR API functions:
-
PxTraceCtrl/* Set trace function */ if (PxTraceCtrl(PXTraceSetTraceFunction, (PxArg_t) traceFunc) == -1) PxPanic();which returns the starting address of the old trace function or
-1in case of an error -
PxSetTraceFunc/* Set trace function */ if (PxSetTraceFunc((PxTraceFunc_t) traceFunc) != PXERR_NOERROR ) PxPanic();which returns error code
PXERR_NOERRORorPXERR_ACCESS_RIGHT
Trace control
PXROS-HR uses the PxTraceCtrl() function to control the trace mechanism. This function takes command and command-related arguments. It can set the trace function, start/stop tracing, get the tracing state (enabled, disabled), configure the tracing mask, and enable/disable tracing for a given task. All PxTraceCtrl() commands are further explained in commands.
Task willing to call PxTraceCtrl() must have at least PXACCESS_TRACECTRL access rights. When calling PxTraceCtrl() with the command PXTraceSetTraceFunction, the task must also have PXACCESS_SYSTEM_CONTROL.
Trace service codes
Each PXROS-HR kernel service is mapped to a number, the so-called service code. These codes are used for logging the kernel activity during runtime. The kernel reserves service codes 0-299. The user can define additional tracing service codes from 300 to 65535.
Kernel interface for trace function
The trace function is always executed on the kernel level, not the task level. As a result, it cannot call standard functions from the PXROS-HR API (these can be called only from tasks). PxTrace interface offers several kernel interface functions instead:
-
IPxTraceCheckService()— checks if a trace entry should be made or not based on the group mask -
IPxTraceCheckTask()— checks if a trace entry should be made or not based on the task issuing thePxTrace()call -
IPxTraceGetGroupMask()— returns the current group mask without triggering an additional syscall -
IPxTraceGetHandlerTaskID()— returns the ID of the handler task -
IPxTraceGetNextEntry()— get the next free entry in the trace buffer -
IPxTraceGetRunTaskID()— returns the ID of the runtask