Update trace recorder to include heap tracing and new v8 features.

This commit is contained in:
Richard Barry
2014-02-17 12:45:56 +00:00
parent 853696a991
commit 04ae37ef12
15 changed files with 1218 additions and 608 deletions

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.5.0 Recorder Library
* Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcConfig.h
@ -91,9 +91,15 @@
* stores User Events labels and names of deleted tasks, queues, or other kernel
* objects. Note that the names of active objects not stored here but in the
* Object Table. Thus, if you don't use User Events or delete any kernel
* objects you set this to zero (0) to minimize RAM usage.
* objects you set this to a very low value, e.g. 4, but not zero (0) since
* this causes a declaration of a zero-sized array, for which the C compiler
* behavior is not standardized and may cause misaligned data.
******************************************************************************/
#define SYMBOL_TABLE_SIZE 1000
#define SYMBOL_TABLE_SIZE 800
#if (SYMBOL_TABLE_SIZE == 0)
#error "SYMBOL_TABLE_SIZE may not be zero!"
#endif
/*******************************************************************************
* USE_SEPARATE_USER_EVENT_BUFFER
@ -119,7 +125,7 @@
*
* Only in use if USE_SEPARATE_USER_EVENT_BUFFER is set to 1.
******************************************************************************/
#define USER_EVENT_BUFFER_SIZE 500
#define USER_EVENT_BUFFER_SIZE 10
/*******************************************************************************
* USER_EVENT_CHANNELS
@ -169,6 +175,8 @@
#define NQueue 10
#define NSemaphore 10
#define NMutex 10
#define NTimer 2
#define NEventGroup 2
/* Maximum object name length for each class (includes zero termination) */
#define NameLenTask 15
@ -176,6 +184,8 @@
#define NameLenQueue 15
#define NameLenSemaphore 15
#define NameLenMutex 15
#define NameLenTimer 15
#define NameLenEventGroup 15
/******************************************************************************
* TRACE_DESCRIPTION
@ -234,7 +244,7 @@
* If this is one (1), the TRACE_ASSERT macro will verify that a condition is
* true. If the condition is false, vTraceError() will be called.
*****************************************************************************/
#define USE_TRACE_ASSERT 0
#define USE_TRACE_ASSERT 1
/******************************************************************************
* INCLUDE_FLOAT_SUPPORT
@ -264,8 +274,7 @@
* much faster than a printf and can therefore be used in timing critical code.
* See vTraceUserEvent() and vTracePrintF() in trcUser.h
*
* Note that Tracealyzer Professional Edition is required for User Events,
* they are not displayed in Tracealyzer Free Edition.
* Note that User Events are not displayed in FreeRTOS+Trace Free Edition.
*****************************************************************************/
#define INCLUDE_USER_EVENTS 1
@ -319,6 +328,17 @@
*****************************************************************************/
#define INCLUDE_OBJECT_DELETE 1
/******************************************************************************
* INCLUDE_MEMMANG_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* This controls if malloc and free calls should be traced. Set this to zero to
* exclude malloc/free calls from the tracing.
*****************************************************************************/
#define INCLUDE_MEMMANG_EVENTS 1
/******************************************************************************
* CONFIGURATION RELATED TO BEHAVIOR
*****************************************************************************/
@ -425,29 +445,86 @@
*****************************************************************************/
#define USE_IMPLICIT_IFE_RULES 1
/******************************************************************************
* INCLUDE_SAVE_TO_FILE
* USE_16BIT_OBJECT_HANDLES
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 0.
*
* If enabled (1), the recorder will include code for saving the trace
* to a local file system.
******************************************************************************/
#ifdef WIN32
#define INCLUDE_SAVE_TO_FILE 1
#else
#define INCLUDE_SAVE_TO_FILE 0
* If set to 0 (zero), the recorder uses 8-bit handles to identify kernel
* objects such as tasks and queues. This limits the supported number of
* concurrently active objects to 255 of each type (object class).
*
* If set to 1 (one), the recorder uses 16-bit handles to identify kernel
* objects such as tasks and queues. This limits the supported number of
* concurrent objects to 65535 of each type (object class). However, since the
* object property table is limited to 64 KB, the practical limit is about
* 3000 objects in total.
*
* NOTE: An object with a high ID (> 255) will generate an extra event
* (= 4 byte) in the event buffer.
*
* NOTE: Some internal tables in the recorder gets larger when using 16-bit
* handles. The additional RAM usage is 5-10 byte plus 1 byte per kernel object
*, i.e., task, queue, semaphore, mutex, etc.
*****************************************************************************/
#define USE_16BIT_OBJECT_HANDLES 0
/****** Port Name ******************** Code ** Official ** OS Platform ******
* PORT_APPLICATION_DEFINED -2 - -
* PORT_NOT_SET -1 - -
* PORT_HWIndependent 0 Yes Any
* PORT_Win32 1 Yes FreeRTOS Win32
* PORT_Atmel_AT91SAM7 2 No Any
* PORT_Atmel_UC3A0 3 No Any
* PORT_ARM_CortexM 4 Yes Any
* PORT_Renesas_RX600 5 Yes Any
* PORT_Microchip_dsPIC_AND_PIC24 6 Yes Any
* PORT_TEXAS_INSTRUMENTS_TMS570 7 No Any
* PORT_TEXAS_INSTRUMENTS_MSP430 8 No Any
* PORT_MICROCHIP_PIC32 9 No Any
* PORT_XILINX_PPC405 10 No FreeRTOS
* PORT_XILINX_PPC440 11 No FreeRTOS
* PORT_XILINX_MICROBLAZE 12 No Any
* PORT_NXP_LPC210X 13 No Any
*****************************************************************************/
#define SELECTED_PORT PORT_ARM_CortexM
#if (SELECTED_PORT == PORT_NOT_SET)
#error "You need to define SELECTED_PORT here!"
#endif
/******************************************************************************
* TEAM_LICENSE_CODE
* USE_PRIMASK_CS (for Cortex M devices only)
*
* An integer constant that selects between two options for the critical
* sections of the recorder library.
*
* Macro which defines a string - the team license code.
* If no team license is available, this should be an empty string "".
* This should be maximum 32 chars, including zero-termination.
*****************************************************************************/
#define TEAM_LICENSE_CODE ""
* 0: The default FreeRTOS critical section (BASEPRI) - default setting
* 1: Always disable ALL interrupts (using PRIMASK)
*
* Option 0 uses the standard FreeRTOS macros for critical sections.
* However, on Cortex-M devices they only disable interrupts with priorities
* below a certain configurable level, while higher priority ISRs remain active.
* Such high-priority ISRs may not use the recorder functions in this mode.
*
* Option 1 allows you to safely call the recorder from any ISR, independent of
* the interrupt priority. This mode may however cause higher IRQ latencies
* (some microseconds) since ALL configurable interrupts are disabled during
* the recorder's critical sections in this mode, using the PRIMASK register.
******************************************************************************/
#define USE_PRIMASK_CS 0
/******************************************************************************
* HEAP_SIZE_BELOW_16M
*
* An integer constant that can be used to reduce the buffer usage of memory
* allocation events (malloc/free). This value should be 1 if the heap size is
* below 16 MB (2^24 byte), and you can live with addresses truncated to the
* lower 24 bit. Otherwise set it to 0 to get the full 32-bit addresses.
******************************************************************************/
#define HEAP_SIZE_BELOW_16M 0
#endif

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.5.0 Recorder Library
* Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcBase.h
@ -38,7 +38,7 @@
#ifndef TRCBASE_H
#define TRCBASE_H
#define TRACE_MINOR_VERSION 2
#define TRACE_MINOR_VERSION 4
#define TRACE_STORE_MODE_STOP_WHEN_FULL 1
#define TRACE_STORE_MODE_RING_BUFFER 2
#define TRACE_DATA_ALLOCATION_STATIC 1
@ -56,6 +56,10 @@
#define USE_SEPARATE_USER_EVENT_BUFFER 0
#endif
#ifndef TRACE_SR_ALLOC_CRITICAL_SECTION
#define TRACE_SR_ALLOC_CRITICAL_SECTION()
#endif
/* Max number of event codes supported */
#define NEventCodes 0x100
@ -96,16 +100,16 @@ extern uint8_t excludedEventCodes[NEventCodes / 8 + 1];
typedef struct
{
/* For each object class, the index of the next handle to allocate */
int16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ];
uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ];
/* The lowest index of this class (constant) */
int16_t lowestIndexOfClass[ TRACE_NCLASSES ];
uint16_t lowestIndexOfClass[ TRACE_NCLASSES ];
/* The highest index of this class (constant) */
int16_t highestIndexOfClass[ TRACE_NCLASSES ];
uint16_t highestIndexOfClass[ TRACE_NCLASSES ];
/* The highest use count for this class (for statistics) */
int16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ];
uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ];
/* The free object handles - a set of stacks within this array */
objectHandleType objectHandles[ TRACE_KERNEL_OBJECT_COUNT ];
@ -139,7 +143,11 @@ typedef struct
/* This is used to calculate the index in the dynamic object table
(handle - 1 - nofStaticObjects = index)*/
uint8_t NumberOfObjectsPerClass[ 4*((TRACE_NCLASSES+3)/4)];
#if (USE_16BIT_OBJECT_HANDLES == 1)
objectHandleType NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)];
#else
objectHandleType NumberOfObjectsPerClass[4*((TRACE_NCLASSES+3)/4)];
#endif
/* Allocation size rounded up to the closest multiple of 4 */
uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/4) ];
@ -179,7 +187,7 @@ typedef struct
typedef struct
{
uint8_t type;
objectHandleType objHandle;
uint8_t objHandle;
uint16_t dts; /* differential timestamp - time since last event */
} TSEvent, TREvent;
@ -200,7 +208,7 @@ typedef struct
typedef struct
{
uint8_t type;
objectHandleType objHandle;
uint8_t objHandle;
uint8_t param;
uint8_t dts; /* differential timestamp - time since last event */
} KernelCallWithParamAndHandle;
@ -215,7 +223,7 @@ typedef struct
typedef struct
{
uint8_t type;
objectHandleType objHandle; /* the handle of the closed object */
uint8_t objHandle; /* the handle of the closed object */
uint16_t symbolIndex; /* the name of the closed object */
} ObjCloseNameEvent;
@ -254,6 +262,18 @@ typedef struct
uint16_t xps_16;
} XPSEvent;
typedef struct{
uint8_t type;
uint8_t dts;
uint16_t size;
} MemEventSize;
typedef struct{
uint8_t type;
uint8_t addr_high;
uint16_t addr_low;
} MemEventAddr;
/*******************************************************************************
* The separate user event buffer structure. Can be enabled in trcConfig.h.
******************************************************************************/
@ -305,7 +325,7 @@ typedef struct
/* Used to determine Kernel and Endianess */
uint16_t version;
/* Currently 1 for v2.2.2 (0 earlier)*/
/* Currently 3, since v2.6.0 */
uint8_t minor_version;
/* This should be 0 if lower IRQ priority values implies higher priority
@ -342,12 +362,18 @@ typedef struct
This is a 32 bit variable due to alignment issues. */
uint32_t recorderActive;
/* For storing a Team License key */
uint8_t teamLicenceKey[32];
/* Not used, remains for compatibility and future use */
uint8_t notused[28];
/* The amount of heap memory remaining at the last malloc or free event */
uint32_t heapMemUsage;
/* 0xF0F0F0F0 - for control only */
int32_t debugMarker0;
/* Set to value of USE_16BIT_OBJECT_HANDLES */
uint32_t isUsing16bitHandles;
/* 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. */
@ -444,10 +470,16 @@ void vTraceSetObjectName(traceObjectClass objectclass,
void* xTraceNextFreeEventBufferSlot(void);
#if (USE_16BIT_OBJECT_HANDLES == 1)
unsigned char prvTraceGet8BitHandle(objectHandleType handle);
#else
#define prvTraceGet8BitHandle(x) ((unsigned char)x)
#endif
uint16_t uiIndexOfObject(objectHandleType objecthandle,
uint8_t objectclass);
/*******************************************************************************
* vTraceError
*
@ -487,6 +519,9 @@ RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclas
#define TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)
#define TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_GET_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)
#define TRACE_UPDATE_HEAP_USAGE_POSITIVE(change) {if (RecorderDataPtr != NULL) RecorderDataPtr->heapMemUsage += change;}
#define TRACE_UPDATE_HEAP_USAGE_NEGATIVE(change) {if (RecorderDataPtr != NULL) RecorderDataPtr->heapMemUsage -= change;}
/* DEBUG ASSERTS */
#if defined USE_TRACE_ASSERT && USE_TRACE_ASSERT != 0
#define TRACE_ASSERT(eval, msg, defRetVal) \

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.5.0 Recorder Library
* Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernel.h
@ -58,17 +58,17 @@ void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode,
uint32_t param);
void vTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass,
uint32_t objectNumber, uint8_t param);
uint32_t objectNumber, uint32_t param);
void vTraceSetTaskInstanceFinished(objectHandleType handle);
void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value);
void vTraceSetPriorityProperty(uint8_t objectclass, objectHandleType id, uint8_t value);
uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id);
uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, objectHandleType id);
void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value);
void vTraceSetObjectState(uint8_t objectclass, objectHandleType id, uint8_t value);
uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id);
uint8_t uiTraceGetObjectState(uint8_t objectclass, objectHandleType id);
#if (INCLUDE_OBJECT_DELETE == 1)

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.5.0 Recorder Library
* Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernelHooks.h
@ -97,7 +97,7 @@
/* This macro will create a task in the object table */
#undef trcKERNEL_HOOKS_TASK_CREATE
#define trcKERNEL_HOOKS_TASK_CREATE(SERVICE, pxTCB) \
#define trcKERNEL_HOOKS_TASK_CREATE(SERVICE, CLASS, pxTCB) \
TRACE_SET_TASK_NUMBER(pxTCB) \
vTraceSetObjectName(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_NAME(pxTCB)); \
vTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \
@ -105,8 +105,8 @@
/* This macro will create a failed create call to create a task */
#undef trcKERNEL_HOOKS_TASK_CREATE_FAILED
#define trcKERNEL_HOOKS_TASK_CREATE_FAILED(SERVICE) \
vTraceStoreKernelCall(TRACE_GET_TASK_EVENT_CODE(SERVICE, FAILED, CLASS, pxTCB), TRACE_CLASS_TASK, 0);
#define trcKERNEL_HOOKS_TASK_CREATE_FAILED(SERVICE, CLASS) \
vTraceStoreKernelCall(TRACE_GET_TASK_EVENT_CODE(SERVICE, FAILED, CLASS, 0), TRACE_CLASS_TASK, 0);
/* This macro will setup a task in the object table */
#undef trcKERNEL_HOOKS_OBJECT_CREATE
@ -132,7 +132,7 @@
/* This macro will flag a certain task as a finished instance */
#undef trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED
#define trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(CLASS, pxObject) \
#define trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED() \
vTraceSetTaskInstanceFinished(TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()));
#if INCLUDE_READY_EVENTS == 1
@ -187,7 +187,24 @@
#undef trcKERNEL_HOOKS_TASK_RESUME
#define trcKERNEL_HOOKS_TASK_RESUME(SERVICE, pxTCB) \
vTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
#undef trcKERNEL_HOOKS_TIMER_EVENT
#define trcKERNEL_HOOKS_TIMER_EVENT(SERVICE, pxTimer) \
vTraceStoreKernelCall(SERVICE, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer));
/* This macro will create a timer in the object table and assign the timer a trace handle (timer number).*/
#undef trcKERNEL_HOOKS_TIMER_CREATE
#define trcKERNEL_HOOKS_TIMER_CREATE(SERVICE, pxTimer) \
TRACE_SET_TIMER_NUMBER(pxTimer); \
vTraceSetObjectName(TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_GET_TIMER_NAME(pxTimer)); \
vTraceStoreKernelCall(SERVICE, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer));
#endif
#endif /* TRCKERNELHOOKS_H */
#undef trcKERNEL_HOOKS_TIMER_DELETE
#define trcKERNEL_HOOKS_TIMER_DELETE(SERVICE, pxTimer) \
vTraceStoreKernelCall(SERVICE, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer)); \
vTraceStoreObjectNameOnCloseEvent(TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_CLASS_TIMER); \
vTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_CLASS_TIMER); \
vTraceFreeObjectHandle(TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer));
#endif /* TRCKERNELHOOKS_H */

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.5.0 Recorder Library
* Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcTypes.h
@ -39,12 +39,17 @@
#define TRCTYPES_H
#include <stdint.h>
#include <trcConfig.h>
typedef uint16_t traceLabel;
typedef uint8_t UserEventChannel;
#if (USE_16BIT_OBJECT_HANDLES == 1)
typedef uint16_t objectHandleType;
#else
typedef uint8_t objectHandleType;
#endif
typedef uint8_t traceObjectClass;

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.5.0 Recorder Library
* Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcUser.h
@ -421,6 +421,12 @@ void vTraceChannelUserEvent(UserEventChannel channel);
#define vTraceSetISRProperties(handle, name, priority)
#define vTraceStoreISRBegin(id)
#define vTraceStoreISREnd()
#define vTraceExcludeTaskFromTrace(handle)
#define vTraceSetQueueName(a, b)
#define vTraceSetMutexName(a, b)
#define vTraceSetSemaphoreName(a, b)
#define vTraceSetEventGroupName(a, b)
#endif
#ifdef __cplusplus

View File

@ -1,7 +1,7 @@
Tracealyzer - Uploading the trace data
-----------------------------------------
Percepio AB, Nov. 8, 2012
Percepio AB, Jan. 23, 2014
This document decribes how to upload the trace data from the target system to
Tracealyzer.
@ -11,15 +11,6 @@ chip RAM. This is a plain RAM dump, that is done whenever you want to look at
the trace buffer contents. This means it works with essentially with any debug
probe on the market.
If the device has a file system and some possibility of accessing this file
system from the development PC, it is also possible to write the recorder data
to a file, using vTraceGetTraceBuffer() and uiTraceGetTraceBufferSize()
found in trcUser.h/.c.
Note that hardware-generated trace is not required (or used by) Tracealyzer.
We however plan to add support for that in future versions of Tracealyzer
and other Tracealyzer products.
Built-in support for Segger J-Link/J-Trace and Atmel SAM-ICE
------------------------------------------------------------
Tracealyzer v2.3 supports Segger J-Link and J-Link compatible debuggers
@ -27,9 +18,8 @@ directly, without any debugger IDE involved. Using other debug probes is
also possible, but requires some extra steps, described below.
If you have a Segger J-Link/J-Trace debug probe or another J-Link compatible
debug probe, just select
"File" menu -> "Upload from <debug probe name>".
debug probe, just select "Read Trace" in the "J-Link" menu. Note that this
menu is only available if a compatible debug probe is found.
This opens a dialog where you get to enter the memory region where
the recorder data structure is located. Normally you select the entire
@ -37,23 +27,17 @@ internal RAM according to the datasheet of your MCU, but the exact address
can be found can by inspecting the "RecorderData" struct or the
"RecorderDataPtr" pointer with your debugger.
Typical values are 0x0, 0x10000000 or 0x20000000 as start address
and 0x10000 or 0x20000 as size (64 KB or 128 KB).
This makes Tracealyzer reads the chip RAM and locate the trace data.
Note that this option is only available if a compatible debug probe is found.
J-Link compatible debug probes also include Atmel SAM-ICE and many built-in
debug interfaces on demonstration/evaluation boards (where there is a USB
connection directly to the board). Look for a Segger J-Link label on the board.
MemoryLogger extension in Atmel Studio 6
----------------------------------------
Atmel's new MemoryLogger extension provides a superb integration with
Tracealyzer. Look for "MemoryLogger" in Atmel Gallery, available in
Atmel Studio and at the Atmel website.
Atmel's MemoryLogger extension provides a superb integration with FreeRTOS+Trace.
Look for "MemoryLogger" in Atmel Gallery, available in Atmel Studio and at the
Atmel website (http://gallery.atmel.com).
This extension automatically detects the path to Tracealyzer, if
This extension automatically detects the path to FreeRTOS+Trace, if
installed, and gives you a single-click upload/refresh. You can use it
while debugging and optionally get an automatic refresh eash time the
MCU is halted, e.g., on each breakpoint.

View File

@ -4,38 +4,45 @@ Tracealyzer Trace Recorder Library
Percepio AB
www.percepio.com
This directory contains the a generic trace recorder library for Tracealyzer v2.5.
This directory contains the a generic trace recorder library for Tracealyzer v2.6.
For information on how to upload the trace data from your target system RAM to
Tracealyzer, see "debugger trace upload.txt"
Files included
--------------
- trcConfig.h - The recorder's configuration file, check this!
- trcUser.c / trcUser.h - The main API towards the application (trcUser.h in the only include necessary).
- trcKernel.c / trcKernel.h - Internal routines for storing kernel events.
- trcBase.c / trcBase.h - Internal routines for manipulating the data structures and calculating timestamps.
- trcHardwarePort.c / trcHardwarePort.h - The port layer, abstracting the hardware (mainly the timer used for timestamping).
- trcKernelHooks.h - The interface between the Kernel and the recorder, containing trace macro defintions.
- trcKernelPort.h - Kernel specific implementations of macros and data.
- trcTypes.h - Type definitions used.
- trcConfig.h - The recorder's configuration file, set your recorder configuration here!
- trcUser.c/.h - The main API towards the application (trcUser.h in the only include necessary).
- trcKernel.c/.h - Internal routines for storing kernel events.
- trcBase.c/.h - Internal routines for manipulating the data structures and calculating timestamps.
- trcHardwarePort.c/.h - The hardware interface, especially for timestamping.
- trcKernelPort.c/.h - Kernel specific implementations of macros and data.
- trcKernelHooks.h - The trace macro defines (OS independent).
- trcTypes.h - Type definitions used.
Hardware Timer Ports
--------------------
This release contains hardware timer ports for the following hardware architectures:
- ARM Cortex M3/M4 (all brands, such as Atmel SAM3/SAM4, NXP 17xx, 18xx, 43xx, STM32, Freescale Kinetis, ...)
- ARM Cortex M3/M4/M0/M0+ (all brands, such as Atmel SAM3x/SAM4x/SAM D20, NXP 17xx, 18xx, 43xx, STM32, Freescale Kinetis, ...)
- Atmel AT91SAM7x
- Atmel AT32UC3 (AVR32)
- Renesas RX600 (e.g., RX62N)
- Microchip dsPIC/PIC24
- Microchip PIC32
- NXP LPC2106
- Texas Instruments TMS570 (Cortex-R4)
- Texas Instruments MSP430
- Xilinx PowerPC 405
- Xilinx PowerPC 440
- Xilinx Microblaze
These are defined in trcPort.h. This also contains several "unofficial" ports, provided by external contributors.
By unofficial, it means that they are not yet verified by Percepio AB. Please refer to trcPort.h for detailed information.
If you use an unofficial port and beleive it is incorrect, please let us know!
These are defined in trcHardwarePort.h. Some of these are "unofficial" ports, provided by external contributors.
By unofficial, it means that they are not yet verified by Percepio AB. Please refer to trcHardwarePort.h for detailed information.
If you use an unofficial port and beleive it is incorrect, please let us know! (support@percepio.com)
In case your MCU is not yet supported directly, developing a new port is quite easy, just a matter of defining a few macros
according to your specific MCU. See trcPort.h for further information.
according to your specific MCU. See trcHardwarePort.h for further information.
In case you have any questions, do not hesitate to contact support@percepio.com

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.5.0 Recorder Library
* Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcBase.c
@ -113,6 +113,7 @@ void prvTraceInitTraceData()
/* DO NOTHING */
#endif
TRACE_ASSERT(RecorderDataPtr != NULL, "prvTraceInitTraceData, RecorderDataPtr == NULL", );
if (! RecorderDataPtr)
@ -120,7 +121,7 @@ void prvTraceInitTraceData()
vTraceError("No recorder data structure allocated!");
return;
}
(void)memset(RecorderDataPtr, 0, sizeof(RecorderDataType));
RecorderDataPtr->startmarker0 = 0x00;
@ -145,6 +146,8 @@ void prvTraceInitTraceData()
RecorderDataPtr->debugMarker0 = 0xF0F0F0F0;
RecorderDataPtr->isUsing16bitHandles = USE_16BIT_OBJECT_HANDLES;
/* This function is kernel specific */
vTraceInitObjectPropertyTable();
@ -182,6 +185,10 @@ void prvTraceInitTraceData()
/* Fix the start markers of the trace data structure */
vInitStartMarkers();
#ifdef PORT_SPECIFIC_INIT
PORT_SPECIFIC_INIT();
#endif
}
static void vInitStartMarkers()
@ -255,7 +262,7 @@ uint16_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass)
objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass)
{
static objectHandleType handle;
objectHandleType handle;
static int indexOfHandle;
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "xTraceGetObjectHandle: Invalid value for objectclass", (objectHandleType)0);
@ -314,7 +321,7 @@ void vTraceFreeObjectHandle(traceObjectClass objectclass, objectHandleType handl
objectHandleStacks.lowestIndexOfClass[objectclass])
{
/* Error */
vTraceError("Attempt to free more handles than allocated! (duplicate xTaskDelete or xQueueDelete?)");
vTraceError("Attempt to free more handles than allocated!");
}
else
{
@ -389,8 +396,11 @@ traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel)
uint16_t result;
uint8_t len;
uint8_t crc;
TRACE_SR_ALLOC_CRITICAL_SECTION();
len = 0;
crc = 0;
TRACE_ASSERT(name != NULL, "prvTraceOpenSymbol: name == NULL", (traceLabel)0);
@ -411,8 +421,6 @@ traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel)
* Supporting functions
******************************************************************************/
extern volatile uint32_t rtest_error_flag;
/*******************************************************************************
* vTraceError
*
@ -430,8 +438,8 @@ void vTraceError(const char* msg)
TRACE_ASSERT(msg != NULL, "vTraceError: msg == NULL", );
TRACE_ASSERT(RecorderDataPtr != NULL, "vTraceError: RecorderDataPtr == NULL", );
// Stop the recorder. Note: We do not call vTraceStop, since that adds a weird
// and unnecessary dependency to trcUser.c.
/* Stop the recorder. Note: We do not call vTraceStop, since that adds a weird
and unnecessary dependency to trcUser.c */
RecorderDataPtr->recorderActive = 0;
@ -503,12 +511,12 @@ void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nofEntriesToCheck)
* Updates the index of the event buffer.
******************************************************************************/
void prvTraceUpdateCounters(void)
{
if (RecorderDataPtr->recorderActive == 0)
{
if (RecorderDataPtr->recorderActive == 0)
{
return;
}
RecorderDataPtr->numEvents++;
RecorderDataPtr->nextFreeIndex++;
@ -556,13 +564,17 @@ uint16_t prvTraceGetDTS(uint16_t param_maxDTS)
TRACE_ASSERT(param_maxDTS == 0xFF || param_maxDTS == 0xFFFF, "prvTraceGetDTS: Invalid value for param_maxDTS", 0);
#if (SELECTED_PORT != PORT_ARM_CortexM)
if (RecorderDataPtr->frequency == 0 && init_hwtc_count != HWTC_COUNT)
{
/* If HWTC_PERIOD is mapped to the timer reload register,
such as in the Cortex M port, it might not be initialized
before the Kernel scheduler has been started has been
started. We therefore store the frequency of the timer
once the counter register has changed. */
it might not be initialized before the scheduler has been started.
We therefore store the frequency of the timer when the counter
register has changed from its initial value.
(Note that this function is called also by vTraceStart and
uiTraceStart, which might be called before the scheduler
has been started.) */
#if (SELECTED_PORT == PORT_Win32)
RecorderDataPtr->frequency = 100000;
@ -572,15 +584,15 @@ uint16_t prvTraceGetDTS(uint16_t param_maxDTS)
RecorderDataPtr->frequency = (HWTC_PERIOD * TRACE_TICK_RATE_HZ) / (uint32_t)HWTC_DIVISOR;
#endif
}
#endif
/**************************************************************************
* The below statements read the timestamp from the timer port module.
* If necessary, whole seconds are extracted using division while the rest
* comes from the modulo operation.
**************************************************************************/
vTracePortGetTimeStamp(&timestamp);
vTracePortGetTimeStamp(&timestamp);
/***************************************************************************
* Since dts is unsigned the result will be correct even if timestamp has
* wrapped around.
@ -770,7 +782,7 @@ uint16_t prvTraceCreateSymbolTableEntry(const char* name,
void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength)
{
unsigned char c;
int length = 0;
int length = 1;
int crc = 0;
TRACE_ASSERT(pname != NULL, "prvTraceGetChecksum: pname == NULL", );
@ -789,4 +801,52 @@ void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength)
*plength = (uint8_t)length;
}
#endif
#if (USE_16BIT_OBJECT_HANDLES == 1)
void prvTraceStoreXID(objectHandleType handle);
/******************************************************************************
* prvTraceStoreXID
*
* Stores an XID (eXtended IDentifier) event.
* This is used if an object/task handle is larger than 255.
* The parameter "handle" is the full (16 bit) handle, assumed to be 256 or
* larger. Handles below 256 should not use this function.
*
* NOTE: this function MUST be called from within a critical section.
*****************************************************************************/
void prvTraceStoreXID(objectHandleType handle)
{
XPSEvent* xid;
TRACE_ASSERT(handle >= 256, "prvTraceStoreXID: Handle < 256", );
xid = (XPSEvent*)xTraceNextFreeEventBufferSlot();
if (xid != NULL)
{
xid->type = XID;
/* This function is (only) used when objectHandleType is 16 bit... */
xid->xps_16 = handle;
prvTraceUpdateCounters();
}
}
unsigned char prvTraceGet8BitHandle(objectHandleType handle)
{
if (handle > 255)
{
prvTraceStoreXID(handle);
/* The full handle (16 bit) is stored in the XID event.
This code (255) is used instead of zero (which is an error code).*/
return 255;
}
return (unsigned char)(handle & 0xFF);
}
#endif
#endif

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.5.0 Recorder Library
* Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcHardwarePort.c
@ -37,6 +37,7 @@
******************************************************************************/
#include "trcHardwarePort.h"
#include "trcKernelPort.h"
#if (USE_TRACEALYZER_RECORDER == 1)
@ -55,6 +56,45 @@ uint32_t last_timestamp = 0;
******************************************************************************/
uint32_t uiTraceTickCount = 0;
uint32_t DWT_CYCLES_ADDED = 0;
#if (SELECTED_PORT == PORT_ARM_CortexM)
void prvTraceEnableIRQ(void)
{
asm volatile ("cpsie i");
}
void prvTraceDisableIRQ(void)
{
asm volatile ("cpsid i");
}
void prvTraceSetIRQMask(uint32_t priMask)
{
asm volatile ("MSR primask, %0" : : "r" (priMask) );
}
uint32_t prvTraceGetIRQMask(void)
{
uint32_t result;
asm volatile ("MRS %0, primask" : "=r" (result) );
return result;
}
void prvTraceInitCortexM()
{
DWT_CTRL_REG |= 1; /* Enable the cycle counter */
DWT_CYCLE_COUNTER = 0;
if (RecorderDataPtr->frequency == 0)
{
RecorderDataPtr->frequency = TRACE_CPU_CLOCK_HZ / HWTC_DIVISOR;
}
}
#endif
/******************************************************************************
* vTracePortGetTimeStamp
*

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.5.0 Recorder Library
* Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernelPort.c
@ -43,6 +43,8 @@
#include "task.h"
/* For classes implemented as FreeRTOS Queues:
This translates queue.type to the corresponding trace object class. */
traceObjectClass TraceObjectClassTable[5] = {
TRACE_CLASS_QUEUE,
TRACE_CLASS_MUTEX,
@ -51,12 +53,14 @@ traceObjectClass TraceObjectClassTable[5] = {
TRACE_CLASS_MUTEX
};
int uiInEventGroupSetBitsFromISR = 0;
extern unsigned char ucQueueGetQueueType(void*);
extern unsigned portBASE_TYPE uxQueueGetQueueNumber(void*);
extern portBASE_TYPE uxQueueGetQueueNumber(void*);
objectHandleType prvTraceGetObjectNumber(void* handle)
{
return uxQueueGetQueueNumber(handle);
return ( objectHandleType ) uxQueueGetQueueNumber(handle);
}
unsigned char prvTraceGetObjectType(void* handle)
@ -69,16 +73,6 @@ objectHandleType prvTraceGetTaskNumber(void* handle)
return (objectHandleType)uxTaskGetTaskNumber(handle);
}
void prvTraceEnterCritical()
{
taskENTER_CRITICAL();
}
void prvTraceExitCritical()
{
taskEXIT_CRITICAL();
}
unsigned char prvTraceIsSchedulerActive()
{
return xTaskGetSchedulerState() == taskSCHEDULER_RUNNING;
@ -108,42 +102,50 @@ void vTraceInitObjectPropertyTable()
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = NMutex;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = NTask;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = NISR;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = NTimer;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = NEventGroup;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = NameLenQueue;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = NameLenSemaphore;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = NameLenMutex;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = NameLenTask;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = NameLenISR;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = NameLenTimer;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = NameLenEventGroup;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[3] = PropertyTableSizeTask;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[5] = PropertyTableSizeTimer;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[6] = PropertyTableSizeEventGroup;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[3] = StartIndexTask;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[5] = StartIndexTimer;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[6] = StartIndexEventGroup;
RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;
}
/* Initialization of the handle mechanism, see e.g, xTraceGetObjectHandle */
void vTraceInitObjectHandleStack()
{
objectHandleStacks.indexOfNextAvailableHandle[0] = 0;
objectHandleStacks.indexOfNextAvailableHandle[1] = NQueue;
objectHandleStacks.indexOfNextAvailableHandle[2] = NQueue + NSemaphore;
objectHandleStacks.indexOfNextAvailableHandle[3] = NQueue + NSemaphore + NMutex;
objectHandleStacks.indexOfNextAvailableHandle[4] = NQueue + NSemaphore + NMutex + NTask;
objectHandleStacks.lowestIndexOfClass[0] = 0;
objectHandleStacks.lowestIndexOfClass[1] = NQueue;
objectHandleStacks.lowestIndexOfClass[2] = NQueue + NSemaphore;
objectHandleStacks.lowestIndexOfClass[3] = NQueue + NSemaphore + NMutex;
objectHandleStacks.lowestIndexOfClass[4] = NQueue + NSemaphore + NMutex + NTask;
objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0;
objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = NQueue;
objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = NQueue + NSemaphore;
objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = NQueue + NSemaphore + NMutex;
objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = NQueue + NSemaphore + NMutex + NTask;
objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = NQueue + NSemaphore + NMutex + NTask + NISR;
objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer;
objectHandleStacks.highestIndexOfClass[0] = NQueue - 1;
objectHandleStacks.highestIndexOfClass[1] = NQueue + NSemaphore - 1;
objectHandleStacks.highestIndexOfClass[2] = NQueue + NSemaphore + NMutex - 1;
objectHandleStacks.highestIndexOfClass[3] = NQueue + NSemaphore + NMutex + NTask - 1;
objectHandleStacks.highestIndexOfClass[4] = NQueue + NSemaphore + NMutex + NTask + NISR - 1;
objectHandleStacks.highestIndexOfClass[5] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer - 1;
objectHandleStacks.highestIndexOfClass[6] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer + NEventGroup - 1;
}
/* Returns the "Not enough handles" error message for this object class */
@ -161,6 +163,10 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)
return "Not enough MUTEX handles - increase NMutex in trcConfig.h";
case TRACE_CLASS_QUEUE:
return "Not enough QUEUE handles - increase NQueue in trcConfig.h";
case TRACE_CLASS_TIMER:
return "Not enough TIMER handles - increase NTimer in trcConfig.h";
case TRACE_CLASS_EVENTGROUP:
return "Not enough EVENTGROUP handles - increase NEventGroup in trcConfig.h";
default:
return "pszTraceGetErrorHandles: Invalid objectclass!";
}
@ -182,8 +188,14 @@ uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, objectHandleType h
return TRACE_GET_MUTEX_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_QUEUE:
return TRACE_GET_QUEUE_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_TIMER:
return TRACE_GET_TIMER_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_EVENTGROUP:
return TRACE_GET_EVENTGROUP_FLAG_ISEXCLUDED(handle);
}
vTraceError("Invalid object class ID in uiTraceIsObjectExcluded!");
/* Must never reach */
return 1;
}

File diff suppressed because it is too large Load Diff