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.
498 lines
19 KiB
C
498 lines
19 KiB
C
13 years ago
|
/*******************************************************************************
|
||
|
* FreeRTOS+Trace v2.2.3 Recorder Library
|
||
|
* Percepio AB, www.percepio.se
|
||
|
*
|
||
|
* trcBase.h
|
||
|
*
|
||
|
* Core functionallity of the FreeRTOS+Trace recorder library.
|
||
|
*
|
||
|
* 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 trcPort.c and trcPort.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.
|
||
|
*
|
||
|
* FreeRTOS+Trace is available as Free Edition and in two premium editions.
|
||
|
* You may use the premium features during 30 days for evaluation.
|
||
|
* Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads
|
||
|
*
|
||
|
* Copyright Percepio AB, 2012.
|
||
|
* www.percepio.se
|
||
|
******************************************************************************/
|
||
|
|
||
|
#ifndef TRCBASE_H
|
||
|
#define TRCBASE_H
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdint.h>
|
||
|
#include "FreeRTOS.h"
|
||
|
#include "trcConfig.h"
|
||
|
#include "trcTypes.h"
|
||
|
#include "trcPort.h"
|
||
|
|
||
|
|
||
|
#define NCLASSES 5
|
||
|
#define VERSION 0x1AA1
|
||
|
#define MINOR_VERSION 1
|
||
|
#define STORE_MODE_STOP_WHEN_FULL 1
|
||
|
#define STORE_MODE_RING_BUFFER 2
|
||
|
#define TRACE_DATA_ALLOCATION_STATIC 1
|
||
|
#define TRACE_DATA_ALLOCATION_DYNAMIC 2
|
||
|
|
||
|
/******************************************************************************
|
||
|
* Object Property Table
|
||
|
* The Object Table contains name and other properties of the objects (tasks,
|
||
|
* queues, mutexes, etc). The below data structures defines the properties of
|
||
|
* each object class and are used to cast the byte buffer into a cleaner format.
|
||
|
*
|
||
|
* The values in the object table are continously overwritten and always
|
||
|
* represent the current state. If a property is changed during runtime, the OLD
|
||
|
* value should be stored in the trace buffer, not the new value (since the new
|
||
|
* value is found in the Object Property Table).
|
||
|
* For close events this mechanism is the old names are stored in the symbol
|
||
|
* table), for "priority set" (the old priority is stored in the event data)
|
||
|
* and for "isActive", where the value decides is the taskswitch event type
|
||
|
* should be "new" or "resume".
|
||
|
******************************************************************************/
|
||
|
|
||
|
/* The size of the Object Property Table entries, in bytes, per object */
|
||
|
|
||
|
/* Queue properties (except name): current number of message in queue */
|
||
|
#define PropertyTableSizeQueue (NameLenQueue + 1)
|
||
|
|
||
|
/* Semaphore properties (except name): state (signaled = 1, cleared = 0) */
|
||
|
#define PropertyTableSizeSemaphore (NameLenSemaphore + 1)
|
||
|
|
||
|
/* Mutex properties (except name): owner (task handle, 0 = free) */
|
||
|
#define PropertyTableSizeMutex (NameLenMutex + 1)
|
||
|
|
||
|
/* Task properties (except name): Byte 0: Current priority
|
||
|
Byte 1: state (if already active)
|
||
|
Byte 2: InstanceFinishEvent_ServiceCode
|
||
|
Byte 3: InstanceFinishEvent_ObjHandle */
|
||
|
#define PropertyTableSizeTask (NameLenTask + 4)
|
||
|
|
||
|
/* ISR properties: Byte 0: priority
|
||
|
Byte 1: state (if already active) */
|
||
|
#define PropertyTableSizeISR (NameLenISR + 2)
|
||
|
|
||
|
/* The layout of the byte array representing the Object Property Table */
|
||
|
#define StartIndexQueue 0
|
||
|
#define StartIndexSemaphore StartIndexQueue + NQueue * PropertyTableSizeQueue
|
||
|
#define StartIndexMutex StartIndexSemaphore + NSemaphore * PropertyTableSizeSemaphore
|
||
|
#define StartIndexTask StartIndexMutex + NMutex * PropertyTableSizeMutex
|
||
|
#define StartIndexISR StartIndexTask + NTask * PropertyTableSizeTask
|
||
|
#define DynObjTableSize StartIndexISR + NISR * PropertyTableSizeISR
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
/* = NCLASSES */
|
||
|
uint32_t NumberOfObjectClasses;
|
||
|
|
||
|
uint32_t ObjectPropertyTableSizeInBytes;
|
||
|
|
||
|
/* This is used to calculate the index in the dynamic object table
|
||
|
(handle - 1 - nofStaticObjects = index)*/
|
||
|
uint8_t NumberOfObjectsPerClass[ 4*((NCLASSES+3)/4)];
|
||
|
|
||
|
/* Allocation size rounded up to the closest multiple of 4 */
|
||
|
uint8_t NameLengthPerClass[ 4*((NCLASSES+3)/4) ];
|
||
|
|
||
|
uint8_t TotalPropertyBytesPerClass[ 4*((NCLASSES+3)/4) ];
|
||
|
|
||
|
/* Allocation size rounded up to the closest multiple of 2 */
|
||
|
uint16_t StartIndexOfClass[ 2*((NCLASSES+1)/2) ];
|
||
|
|
||
|
/* The actual handles issued, should be Initiated to all zeros */
|
||
|
uint8_t objbytes[ 4*((DynObjTableSize+3)/4) ];
|
||
|
} ObjectPropertyTableType;
|
||
|
|
||
|
/* Symbol table data structure */
|
||
|
typedef struct
|
||
|
{
|
||
|
/* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */
|
||
|
uint32_t symTableSize;
|
||
|
|
||
|
/* Entry 0 is reserved. Any reference to entry 0 implies NULL*/
|
||
|
uint32_t nextFreeSymbolIndex;
|
||
|
|
||
|
/* Size rounded up to closest multiple of 4, to avoid alignment issues*/
|
||
|
uint8_t symbytes[4*((SYMBOL_TABLE_SIZE+3)/4)];
|
||
|
|
||
|
/* Used for lookups - Up to 64 linked lists within the symbol table
|
||
|
connecting all entries with the same 6 bit checksum.
|
||
|
This field holds the current list heads. Should be initiated to zeros */
|
||
|
uint16_t latestEntryOfChecksum[64];
|
||
|
} symbolTableType;
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* The data structures of the different events, all 4 bytes long
|
||
|
******************************************************************************/
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t type;
|
||
|
objectHandleType objHandle;
|
||
|
uint16_t dts; /* differential timestamp - time since last event */
|
||
|
} TSEvent;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t type;
|
||
|
uint8_t objHandle;
|
||
|
uint16_t dts;
|
||
|
} KernelCall;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t type;
|
||
|
objectHandleType objHandle;
|
||
|
uint8_t param;
|
||
|
uint8_t dts;
|
||
|
} KernelCallWithParamAndHandle;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t type;
|
||
|
uint8_t dts;
|
||
|
uint16_t param;
|
||
|
} KernelCallWithParam16;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t type;
|
||
|
objectHandleType objHandle; /* the handle of the closed object */
|
||
|
uint16_t symbolIndex; /* the name of the closed object */
|
||
|
} ObjCloseNameEvent;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t type;
|
||
|
uint8_t arg1;
|
||
|
uint8_t arg2;
|
||
|
uint8_t arg3;
|
||
|
} ObjClosePropEvent;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t type;
|
||
|
uint8_t dts;
|
||
|
uint16_t payload; /* the name of the user event */
|
||
|
} UserEvent;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t type;
|
||
|
|
||
|
/* 8 bits extra for storing DTS, if it does not fit in ordinary event
|
||
|
(this one is always MSB if used) */
|
||
|
uint8_t xts_8;
|
||
|
|
||
|
/* 16 bits extra for storing DTS, if it does not fit in ordinary event. */
|
||
|
uint16_t xts_16;
|
||
|
} XTSEvent;
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* The main datastructure, read by FreeRTOS+Trace from the RAM dump
|
||
|
******************************************************************************/
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t startmarker0;
|
||
|
uint8_t startmarker1;
|
||
|
uint8_t startmarker2;
|
||
|
uint8_t startmarker3;
|
||
|
uint8_t startmarker4;
|
||
|
uint8_t startmarker5;
|
||
|
uint8_t startmarker6;
|
||
|
uint8_t startmarker7;
|
||
|
uint8_t startmarker8;
|
||
|
uint8_t startmarker9;
|
||
|
uint8_t startmarker10;
|
||
|
uint8_t startmarker11;
|
||
|
|
||
|
/* For FreeRTOS: 0x1AA1 */
|
||
|
uint16_t version;
|
||
|
|
||
|
/* Currently 1 for v2.2.2 (0 earlier)*/
|
||
|
uint8_t minor_version;
|
||
|
|
||
|
/* This should be 0 if lower irq priority values implies higher priority
|
||
|
levels, such as on ARM Cortex M. If the opposite scheme is used, i.e.,
|
||
|
if higher irq priority values means higher priority, this should be 1. */
|
||
|
uint8_t irq_priority_order;
|
||
|
|
||
|
/* sizeof(RecorderDataType) - just for control */
|
||
|
uint32_t filesize;
|
||
|
|
||
|
/* Current number of events recorded */
|
||
|
uint32_t numEvents;
|
||
|
|
||
|
/* The buffer size, in number of event records */
|
||
|
uint32_t maxEvents;
|
||
|
|
||
|
/* The event buffer index, where to write the next event */
|
||
|
uint32_t nextFreeIndex;
|
||
|
|
||
|
/* 1 if the buffer is full, 0 otherwise */
|
||
|
uint32_t bufferIsFull;
|
||
|
|
||
|
/* The frequency of the clock/timer/counter used as time base */
|
||
|
uint32_t frequency;
|
||
|
|
||
|
/* The absolute timestamp of the last stored event, in the native
|
||
|
timebase, modulo frequency! */
|
||
|
uint32_t absTimeLastEvent;
|
||
|
|
||
|
/* The number of seconds in total - lasts for 136 years */
|
||
|
uint32_t absTimeLastEventSecond;
|
||
|
|
||
|
/* 1 if the recorder has been started, 0 if not yet started or stopped.
|
||
|
This is a 32 bit variable due to alignment issues. */
|
||
|
uint32_t recorderActive;
|
||
|
|
||
|
/* For storing a Team License key */
|
||
|
uint8_t teamLicenceKey[32];
|
||
|
|
||
|
/* 0xF0F0F0F0 - for control only */
|
||
|
int32_t debugMarker0;
|
||
|
|
||
|
/* The Object Property Table holds information about currently active
|
||
|
tasks, queues, and other recorded objects. This is updated on each
|
||
|
create call and includes object name and other properties. */
|
||
|
ObjectPropertyTableType ObjectPropertyTable;
|
||
|
|
||
|
/* 0xF1F1F1F1 - for control only */
|
||
|
int32_t debugMarker1;
|
||
|
|
||
|
/* The Symbol Table stores strings for User Events and is also used to
|
||
|
store names of deleted objects, which still may be in the trace but no
|
||
|
longer are available. */
|
||
|
symbolTableType SymbolTable;
|
||
|
|
||
|
/* For includsion of float support, and for endian detection of floats.
|
||
|
The value should be (float)1 or (uint32_t)0 */
|
||
|
#if (INCLUDE_FLOAT_SUPPORT == 1)
|
||
|
float exampleFloatEncoding;
|
||
|
#else
|
||
|
uint32_t exampleFloatEncoding;
|
||
|
#endif
|
||
|
/* This is non-zero if an internal error occured in the recorder, e.g., if
|
||
|
one of the Nxxx constants was too small. The systemInfo string will then
|
||
|
contain an error message that is displayed when attempting to view the
|
||
|
trace file. */
|
||
|
uint32_t internalErrorOccured;
|
||
|
|
||
|
/* 0xF2F2F2F2 - for control only */
|
||
|
int32_t debugMarker2;
|
||
|
|
||
|
/* Generic system information string, presented in the tool. Note that this
|
||
|
is also used for storing any internal error messages from the recorder, so
|
||
|
do not make TRACE_DESCRIPTION_MAX_LENGTH too small. 80 is recommended. */
|
||
|
char systemInfo[TRACE_DESCRIPTION_MAX_LENGTH];
|
||
|
|
||
|
/* 0xF3F3F3F3 - for control only */
|
||
|
int32_t debugMarker3;
|
||
|
|
||
|
/* The event data, in 4-byte records */
|
||
|
uint8_t eventData[ EVENT_BUFFER_SIZE * 4 ];
|
||
|
|
||
|
uint8_t endmarker0;
|
||
|
uint8_t endmarker1;
|
||
|
uint8_t endmarker2;
|
||
|
uint8_t endmarker3;
|
||
|
uint8_t endmarker4;
|
||
|
uint8_t endmarker5;
|
||
|
uint8_t endmarker6;
|
||
|
uint8_t endmarker7;
|
||
|
uint8_t endmarker8;
|
||
|
uint8_t endmarker9;
|
||
|
uint8_t endmarker10;
|
||
|
uint8_t endmarker11;
|
||
|
|
||
|
} RecorderDataType;
|
||
|
|
||
|
extern RecorderDataType* RecorderDataPtr;
|
||
|
|
||
|
/******************************************************************************
|
||
|
* ObjectHandleStack
|
||
|
* This data-structure is used to provide a mechanism for 1-byte trace object
|
||
|
* handles. This way, only 1 byte is necessary instead of 4 bytes (a pointer)
|
||
|
* when storing a reference to an object. This allows for up to 255 objects of
|
||
|
* each object class - Task, ISR, Semaphore, CountingSemaphore, Mutex and Queue,
|
||
|
* active at any given moment. There can be more "historic" objects, that have
|
||
|
* been deleted - that number is only limited by the size of the symbol table.
|
||
|
* Note that handle zero (0) is not used, it is a code for an invalid handle.
|
||
|
*
|
||
|
* This data structure keeps track of the FREE handles, not the handles in use.
|
||
|
* This datastructure contains one stack per object class. When a handle is
|
||
|
* allocated to an object, the next free handle is popped from the stack. When
|
||
|
* a handle is released (on object delete), it is pushed back on the stack.
|
||
|
* Note that there is no initialization code that pushed the free handles
|
||
|
* initially, that is not necessary due to the following optimization:
|
||
|
*
|
||
|
* The stack of handles (objectHandles) is initially all zeros. Since zero
|
||
|
* is not a valid handle, that is a signal of additional handles needed.
|
||
|
* If a zero is received when popping a new handle, it is replaced by the
|
||
|
* index of the popped handle instead.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
typedef struct
|
||
|
{
|
||
|
/* For each object class, the index of the next handle to allocate */
|
||
|
int16_t indexOfNextAvailableHandle[ NCLASSES ];
|
||
|
|
||
|
/* The lowest index of this class (constant) */
|
||
|
int16_t lowestIndexOfClass[ NCLASSES ];
|
||
|
|
||
|
/* The highest index of this class (constant) */
|
||
|
int16_t highestIndexOfClass[ NCLASSES ];
|
||
|
|
||
|
/* The highest use count for this class (for statistics) */
|
||
|
int16_t handleCountWaterMarksOfClass[ NCLASSES ];
|
||
|
|
||
|
/* The free object handles - a set of stacks within this array */
|
||
|
objectHandleType objectHandles[ NTask+NISR+NSemaphore+NMutex+NQueue ];
|
||
|
|
||
|
} objectHandleStackType;
|
||
|
|
||
|
/* Internal data */
|
||
|
|
||
|
extern objectHandleStackType objectHandleStacks;
|
||
|
|
||
|
extern uint8_t taskFlags[NTask];
|
||
|
|
||
|
/* Internal functions */
|
||
|
|
||
|
uint32_t prvTraceGetDTS(uint32_t param_maxDTS);
|
||
|
|
||
|
void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength);
|
||
|
|
||
|
traceLabel prvTraceCreateSymbolTableEntry(const char* name,
|
||
|
uint8_t crc6,
|
||
|
uint8_t len,
|
||
|
traceLabel channel);
|
||
|
|
||
|
traceLabel prvTraceLookupSymbolTableEntry(const char* name,
|
||
|
uint8_t crc6,
|
||
|
uint8_t len,
|
||
|
traceLabel channel);
|
||
|
|
||
|
traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel);
|
||
|
|
||
|
void prvTraceUpdateCounters(void);
|
||
|
|
||
|
void prvCheckDataToBeOverwrittenForMultiEntryUserEvents(uint32_t nEntries);
|
||
|
|
||
|
objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass);
|
||
|
|
||
|
void vTraceFreeObjectHandle(traceObjectClass objectclass,
|
||
|
objectHandleType handle);
|
||
|
|
||
|
void vTraceSetObjectName(traceObjectClass objectclass,
|
||
|
objectHandleType handle,
|
||
|
const char* name);
|
||
|
|
||
|
void* xTraceNextFreeEventBufferSlot(void);
|
||
|
|
||
|
uint32_t uiIndexOfObject(objectHandleType objecthandle,
|
||
|
uint8_t objectclass);
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* vTraceError
|
||
|
*
|
||
|
* Called by various parts in the recorder. Stops the recorder and stores a
|
||
|
* pointer to an error message, which is printed by the monitor task.
|
||
|
******************************************************************************/
|
||
|
void vTraceError(char* msg);
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* xTraceGetLastError
|
||
|
*
|
||
|
* Gives the last error message, if any. NULL if no error message is stored.
|
||
|
* The message is cleared on read.
|
||
|
******************************************************************************/
|
||
|
char* xTraceGetLastError(void);
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* xTraceInitTraceData
|
||
|
*
|
||
|
* Allocates and initializes the recorder datastructure, based on the constants
|
||
|
* in trcConfig.h. This allows for allocating the data on the heap, instead of
|
||
|
* using a static declaration.
|
||
|
******************************************************************************/
|
||
|
RecorderDataType* xTraceInitTraceData(void);
|
||
|
|
||
|
/* Internal macros */
|
||
|
|
||
|
#define PROPERTY_NAME_GET(objectclass, objecthandle) \
|
||
|
(const char*)(& RecorderDataPtr->ObjectPropertyTable.objbytes \
|
||
|
[uiIndexOfObject(objecthandle, objectclass)])
|
||
|
|
||
|
#define PROPERTY_OBJECT_STATE(objectclass, handle) \
|
||
|
RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
|
||
|
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass]]
|
||
|
|
||
|
#define PROPERTY_ACTOR_PRIORITY(objectclass, handle) \
|
||
|
RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
|
||
|
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass] + 1]
|
||
|
|
||
|
#define PROPERTY_TASK_IFE_SERVICECODE(handle) \
|
||
|
RecorderDataPtr->ObjectPropertyTable.objbytes \
|
||
|
[uiIndexOfObject(handle, TRACE_CLASS_TASK) \
|
||
|
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[TRACE_CLASS_TASK]+2]
|
||
|
|
||
|
#define PROPERTY_TASK_IFE_OBJHANDLE(handle) \
|
||
|
RecorderDataPtr->ObjectPropertyTable.objbytes \
|
||
|
[uiIndexOfObject(handle, TRACE_CLASS_TASK) \
|
||
|
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[TRACE_CLASS_TASK]+3]
|
||
|
|
||
|
#define TASK_FLAG_BITMASK_ExcludeTaskFromTrace 1
|
||
|
#define TASK_FLAG_BITMASK_MarkNextEventAsTaskInstanceFinish 2
|
||
|
|
||
|
#define SET_TASK_FLAG_ISEXCLUDED(taskHandle) taskFlags[taskHandle] |= 0x01
|
||
|
#define CLEAR_TASK_FLAG_ISEXCLUDED(taskHandle) taskFlags[taskHandle] &= 0xFE
|
||
|
#define GET_TASK_FLAG_ISEXCLUDED(taskHandle) (taskFlags[taskHandle] & 0x01)
|
||
|
|
||
|
#define SET_TASK_FLAG_MARKIFE(taskHandle) taskFlags[taskHandle] |= 0x02
|
||
|
#define CLEAR_TASK_FLAG_MARKIFE(taskHandle) taskFlags[taskHandle] &= 0xFD
|
||
|
#define GET_TASK_FLAG_MARKIFE(taskHandle) (taskFlags[taskHandle] & 0x02)
|
||
|
|
||
|
|
||
|
/* For debug printouts - the names of the object classes */
|
||
|
extern char OBJECTCLASSNAME[NCLASSES][10];
|
||
|
/*=
|
||
|
{
|
||
|
"QUEUE"
|
||
|
"SEMAPHORE",
|
||
|
"MUTEX",
|
||
|
"TASK",
|
||
|
"ISR"
|
||
|
};*/
|
||
|
|
||
|
#endif
|
||
|
|