summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus
diff options
context:
space:
mode:
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2014-02-17 12:45:56 +0000
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2014-02-17 12:45:56 +0000
commit7268fb7c2c7d67b9002aaa7a776b984a122a09d5 (patch)
tree5a0ac153f6824935a03ef7ff162496a9a6e2fa74 /FreeRTOS-Plus
parentd97243b3f55e022858ef6463d25ef3d3ec1dc18a (diff)
downloadfreertos-7268fb7c2c7d67b9002aaa7a776b984a122a09d5.tar.gz
Update trace recorder to include heap tracing and new v8 features.
git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@2207 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
Diffstat (limited to 'FreeRTOS-Plus')
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcConfig.h121
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcBase.h63
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h (renamed from FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcHardwarePort.h)260
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernel.h12
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelHooks.h31
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h368
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTypes.h7
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcUser.h8
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/debugger trace upload.txt30
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/readme.txt37
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcBase.c102
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c42
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernel.c220
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c58
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcUser.c483
15 files changed, 1226 insertions, 616 deletions
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcConfig.h
index f7d3ff044..e2d22e053 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcConfig.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcConfig.h
@@ -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
@@ -320,6 +329,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
- *
- * 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 ""
+* USE_PRIMASK_CS (for Cortex M devices only)
+*
+* An integer constant that selects between two options for the critical
+* sections of the recorder library.
+ *
+* 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
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcBase.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcBase.h
index e48dc88ec..31dad34e7 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcBase.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcBase.h
@@ -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) \
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcHardwarePort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h
index 993882b17..c66654e67 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcHardwarePort.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Tracealyzer v2.5.0 Recorder Library
+ * Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcHardwarePort.h
@@ -38,8 +38,7 @@
#ifndef TRCPORT_H
#define TRCPORT_H
-
-#include "trcKernelPort.h"
+#include <stdint.h>
/* If Win32 port */
#ifdef WIN32
@@ -76,60 +75,41 @@
* typically 1 KHz. This means that a task or ISR that executes in less than
* 1 ms get an execution time of zero.
*
- * PORT_Win32
- * "Accurate" timestamping based on the Windows performance counter for Win32 builds.
- * Note that this gives the host machine time, not the kernel time.
- *
- * Officially supported hardware timer ports:
- * - PORT_Atmel_AT91SAM7
- * - PORT_Atmel_UC3A0
- * - PORT_ARM_CortexM
- * - PORT_Renesas_RX600
- * - PORT_Microchip_dsPIC_AND_PIC24
+ * PORT_APPLICATION_DEFINED
+ * Allows for defining the port macros in other source code files.
*
- * We also provide several "unofficial" hardware-specific ports. There have
- * been developed by external contributors, and have not yet been verified
- * by Percepio AB. Let us know if you have problems getting these to work.
- *
- * Unofficial hardware specific ports provided are:
- * - PORT_TEXAS_INSTRUMENTS_TMS570
- * - PORT_TEXAS_INSTRUMENTS_MSP430
- * - PORT_MICROCHIP_PIC32
- * - PORT_XILINX_PPC405
- * - PORT_XILINX_PPC440
- * - PORT_XILINX_MICROBLAZE
- * - PORT_NXP_LPC210X
+ * PORT_Win32
+ * "Accurate" timestamping based on the Windows performance counter for Win32
+ * builds. Note that this gives the host machine time, not the kernel time.
*
+ * Hardware specific ports
+ * To get accurate timestamping, a hardware timer is necessary. Below are the
+ * available ports. Some of these are "unofficial", meaning that
+ * they have not yet been verified by Percepio but have been contributed by
+ * external developers. They should work, otherwise let us know by emailing
+ * support@percepio.com. Some work on any OS platform, while other are specific
+ * to a certain operating system.
*****************************************************************************/
-#define PORT_NOT_SET -1
-#define PORT_APPLICATION_DEFINED -2
-
-/*** Officially supported hardware timer ports *******************************/
-#define PORT_HWIndependent 0
-#define PORT_Win32 1
-#define PORT_Atmel_AT91SAM7 2
-#define PORT_Atmel_UC3A0 3
-#define PORT_ARM_CortexM 4
-#define PORT_Renesas_RX600 5
-#define PORT_Microchip_dsPIC_AND_PIC24 6
-
-/*** Unofficial ports, provided by external developers, not yet verified *****/
-#define PORT_TEXAS_INSTRUMENTS_TMS570 7
-#define PORT_TEXAS_INSTRUMENTS_MSP430 8
-#define PORT_MICROCHIP_PIC32 9
-#define PORT_XILINX_PPC405 10
-#define PORT_XILINX_PPC440 11
-#define PORT_XILINX_MICROBLAZE 12
-#define PORT_NXP_LPC210X 13
-
-/*** Select your port here! **************************************************/
-#define SELECTED_PORT PORT_NOT_SET
-/*****************************************************************************/
-
-#if (SELECTED_PORT == PORT_NOT_SET)
-#error "You need to define SELECTED_PORT here!"
-#endif
+/****** Port Name ******************** Code ** Official ** OS Platform *******/
+#define PORT_APPLICATION_DEFINED -2 /* - - */
+#define PORT_NOT_SET -1 /* - - */
+#define PORT_HWIndependent 0 /* Yes Any */
+#define PORT_Win32 1 /* Yes Windows (FreeRTOS)*/
+#define PORT_Atmel_AT91SAM7 2 /* No Any */
+#define PORT_Atmel_UC3A0 3 /* No Any */
+#define PORT_ARM_CortexM 4 /* Yes Any */
+#define PORT_Renesas_RX600 5 /* Yes Any */
+#define PORT_Microchip_dsPIC_AND_PIC24 6 /* Yes Any */
+#define PORT_TEXAS_INSTRUMENTS_TMS570 7 /* No Any */
+#define PORT_TEXAS_INSTRUMENTS_MSP430 8 /* No Any */
+#define PORT_MICROCHIP_PIC32 9 /* No Any */
+#define PORT_XILINX_PPC405 10 /* No FreeRTOS */
+#define PORT_XILINX_PPC440 11 /* No FreeRTOS */
+#define PORT_XILINX_MICROBLAZE 12 /* No Any */
+#define PORT_NXP_LPC210X 13 /* No Any */
+
+#include "trcConfig.h" // Where SELECTED_PORT is defined
/*******************************************************************************
* IRQ_PRIORITY_ORDER
@@ -144,25 +124,6 @@
* interrupts in priority order, in case you record interrupts using
* the vTraceStoreISRBegin and vTraceStoreISREnd routines.
*
- * We provide this setting for some hardware architectures below:
- * - ARM Cortex M: 0 (lower IRQ priority values are more significant)
- * - Atmel AT91SAM7x: 1 (higher IRQ priority values are more significant)
- * - Atmel AVR32: 1 (higher IRQ priority values are more significant)
- * - Renesas RX600: 1 (higher IRQ priority values are more significant)
- * - Microchip PIC24: 0 (lower IRQ priority values are more significant)
- * - Microchip dsPIC: 0 (lower IRQ priority values are more significant)
- * - TI TMS570: 0 (lower IRQ priority values are more significant)
- * - Freescale HCS08: 0 (lower IRQ priority values are more significant)
- * - Freescale HCS12: 0 (lower IRQ priority values are more significant)
- * - PowerPC 405: 0 (lower IRQ priority values are more significant)
- * - PowerPC 440: 0 (lower IRQ priority values are more significant)
- * - Freescale ColdFire: 1 (higher IRQ priority values are more significant)
- * - NXP LPC210x: 0 (lower IRQ priority values are more significant)
- * - MicroBlaze: 0 (lower IRQ priority values are more significant)
- *
- * If your chip is not on the above list, and you perhaps know this detail by
- * heart, please inform us by e-mail to support@percepio.com.
- *
******************************************************************************
*
* HWTC Macros
@@ -187,9 +148,11 @@
* interrupt is signaled.
*
* HWTC_PERIOD: The number of increments or decrements of HWTC_COUNT between
- * two tick interrupts. This should preferably be mapped to the reload
+ * two OS tick interrupts. This should preferably be mapped to the reload
* register of the hardware timer, to make it more portable between chips in the
* same family. The macro should in most cases be (reload register + 1).
+ * For FreeRTOS, this can in most cases be defined as
+ * #define HWTC_PERIOD (configCPU_CLOCK_HZ / configTICK_RATE_HZ)
*
* HWTC_DIVISOR: If the timer frequency is very high, like on the Cortex M chips
* (where the SysTick runs at the core clock frequency), the "differential
@@ -209,56 +172,47 @@
******************************************************************************/
#if (SELECTED_PORT == PORT_Win32)
-
+ // This can be used as a template for any free-running 32-bit counter
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (ulGetRunTimeCounterValue())
#define HWTC_PERIOD 0
#define HWTC_DIVISOR 1
-
- #define IRQ_PRIORITY_ORDER 1 // Please update according to your hardware...
-#elif (SELECTED_PORT == PORT_HWIndependent)
+ // Please update according to your system...
+ #define IRQ_PRIORITY_ORDER 1
+#elif (SELECTED_PORT == PORT_HWIndependent)
+ // OS Tick only (typically 1 ms resolution)
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT 0
#define HWTC_PERIOD 1
#define HWTC_DIVISOR 1
-
- #define IRQ_PRIORITY_ORDER 1 // Please update according to your hardware...
-
-#elif (SELECTED_PORT == PORT_Atmel_AT91SAM7)
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!
-
- /* HWTC_PERIOD is hardcoded for AT91SAM7X256-EK Board (48 MHz)
- A more generic solution is to get the period from pxPIT->PITC_PIMR */
- #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
- #define HWTC_COUNT (AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF)
- #define HWTC_PERIOD (AT91C_BASE_PITC->PITC_PIMR + 1)
- #define HWTC_DIVISOR 1
+ // Please update according to your system...
+ #define IRQ_PRIORITY_ORDER NOT_SET
- #define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
-
-#elif (SELECTED_PORT == PORT_Atmel_UC3A0)
-#error HWTC_PERIOD must point to the reload register! Not yet updated for this hardware port!
-
- /* For Atmel AVR32 (AT32UC3A) */
- #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
- #define HWTC_COUNT sysreg_read(AVR32_COUNT)
- #define HWTC_PERIOD
- #define HWTC_DIVISOR 1
-
- #define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_ARM_CortexM)
- /* For all chips using ARM Cortex M cores */
+ void prvTraceSetIRQMask(uint32_t priMask);
+ uint32_t prvTraceGetIRQMask(void);
+
+ void prvTraceEnableIRQ(void);
+ void prvTraceDisableIRQ(void);
+
+ void prvTraceInitCortexM(void);
+
+ #define PORT_SPECIFIC_INIT() prvTraceInitCortexM()
+
+ extern uint32_t DWT_CYCLES_ADDED;
+ #define DWT_CTRL_REG (*((uint32_t*)0xE0001000))
+ #define DWT_CYCLE_COUNTER (*((uint32_t*)0xE0001004))
+
+ #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
+ #define HWTC_COUNT (DWT_CYCLE_COUNTER + DWT_CYCLES_ADDED)
+ #define HWTC_PERIOD 0
+ #define HWTC_DIVISOR 4
- #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
- #define HWTC_COUNT (*((uint32_t*)0xE000E018))
- #define HWTC_PERIOD ((*(uint32_t*)0xE000E014) + 1)
- #define HWTC_DIVISOR 2
-
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_Renesas_RX600)
@@ -269,15 +223,14 @@
#define HWTC_COUNT (CMT0.CMCNT)
#define HWTC_PERIOD (CMT0.CMCOR + 1)
#define HWTC_DIVISOR 1
-
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_Microchip_dsPIC_AND_PIC24)
/* For Microchip PIC24 and dsPIC (16 bit) */
- /* Note: The trace library was originally designed for 32-bit MCUs, and is slower
- than intended on 16-bit MCUs. Storing an event on a PIC24 takes about 70 µs.
+ /* Note: The trace library is designed for 32-bit MCUs and is slower than
+ intended on 16-bit MCUs. Storing an event on a PIC24 takes about 70 usec.
In comparison, 32-bit MCUs are often 10-20 times faster. If recording overhead
becomes a problem on PIC24, use the filters to exclude less interesting tasks
or system calls. */
@@ -286,24 +239,42 @@
#define HWTC_COUNT (TMR1)
#define HWTC_PERIOD (PR1+1)
#define HWTC_DIVISOR 1
-
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
-#elif (SELECTED_PORT == PORT_NXP_LPC210X)
-#error HWTC_PERIOD must point to the reload register! Not yet updated for this hardware port!
+#elif (SELECTED_PORT == PORT_Atmel_AT91SAM7)
+
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
-
+
+ #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
+ #define HWTC_COUNT ((uint32_t)(AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF))
+ #define HWTC_PERIOD ((uint32_t)(AT91C_BASE_PITC->PITC_PIMR + 1))
+ #define HWTC_DIVISOR 1
+ #define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
+
+#elif (SELECTED_PORT == PORT_Atmel_UC3A0)
+
+ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
+ /* For Atmel AVR32 (AT32UC3A).*/
+
+ #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
+ #define HWTC_COUNT ((uint32_t)sysreg_read(AVR32_COUNT))
+ #define HWTC_PERIOD ((uint32_t)(sysreg_read(AVR32_COMPARE) + 1))
+ #define HWTC_DIVISOR 1
+ #define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
+
+#elif (SELECTED_PORT == PORT_NXP_LPC210X)
+
+ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* Tested with LPC2106, but should work with most LPC21XX chips. */
-
+
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT *((uint32_t *)0xE0004008 )
- #define HWTC_PERIOD
+ #define HWTC_PERIOD *((uint32_t *)0xE0004018 )
#define HWTC_DIVISOR 1
-
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_TMS570)
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!
+
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define RTIFRC0 *((uint32_t *)0xFFFFFC10)
@@ -317,52 +288,60 @@
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_MSP430)
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!
+
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (TA0R)
- #define HWTC_PERIOD TRACE_CPU_CLOCKS_PER_TICK
+ #define HWTC_PERIOD (((uint16_t)TACCR0)+1)
#define HWTC_DIVISOR 1
-
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_MICROCHIP_PIC32)
+
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (ReadTimer1()) /* Should be available in BSP */
#define HWTC_PERIOD (ReadPeriod1()+1) /* Should be available in BSP */
#define HWTC_DIVISOR 1
-
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_XILINX_PPC405)
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!
+
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
- #define HWTC_COUNT mfspr( 0x3db)
- #define HWTC_PERIOD
+ #define HWTC_COUNT mfspr(0x3db)
+ #if (defined configCPU_CLOCK_HZ && defined configTICK_RATE_HZ) // Check if FreeRTOS
+ /* For FreeRTOS only - found no generic OS independent solution for the PPC405 architecture. */
+ #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) // Same as in port.c for PPC405
+ #else
+ /* Not defined for other operating systems yet */
+ #error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick.
+ #endif
#define HWTC_DIVISOR 1
-
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_XILINX_PPC440)
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
-
- /* This should work with most PowerPC chips */
- #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
- #define HWTC_COUNT mfspr( 0x016 )
- #define HWTC_PERIOD
+ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
+ /* This should work with most PowerPC chips */
+
+ #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
+ #define HWTC_COUNT mfspr(0x016)
+ #if (defined configCPU_CLOCK_HZ && defined configTICK_RATE_HZ) // Check if FreeRTOS
+ /* For FreeRTOS only - found no generic OS independent solution for the PPC440 architecture. */
+ #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) // Same as in port.c for PPC440
+ #else
+ /* Not defined for other operating systems yet */
+ #error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick.
+ #endif
#define HWTC_DIVISOR 1
-
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_XILINX_MICROBLAZE)
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!
+
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* This should work with most Microblaze configurations.
@@ -373,9 +352,8 @@
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 )
- #define HWTC_PERIOD
+ #define HWTC_PERIOD (XTmrCtr_mGetLoadReg( XPAR_TMRCTR_0_BASEADDR, 0) + 1)
#define HWTC_DIVISOR 16
-
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_APPLICATION_DEFINED)
@@ -384,7 +362,6 @@
#error SELECTED_PORT is PORT_APPLICATION_DEFINED but not all of the necessary constants have been defined.
#endif
-
#elif (SELECTED_PORT != PORT_NOT_SET)
#error "SELECTED_PORT had unsupported value!"
@@ -419,7 +396,7 @@
#if (HWTC_DIVISOR < 1)
#error "HWTC_DIVISOR must be a non-zero positive value!"
#endif
-
+
#endif
/*******************************************************************************
* vTraceConsoleMessage
@@ -428,11 +405,6 @@
* This needs to be correctly defined to see status reports from the trace
* status monitor task (this is defined in trcUser.c).
******************************************************************************/
-#if (SELECTED_PORT == PORT_Atmel_AT91SAM7)
-/* Port specific includes */
-#include "console.h"
-#endif
-
#define vTraceConsoleMessage(x)
/*******************************************************************************
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernel.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernel.h
index 4c8bdd509..b92afa827 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernel.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernel.h
@@ -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)
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelHooks.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelHooks.h
index 69431ee95..a029124e4 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelHooks.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelHooks.h
@@ -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 */ \ No newline at end of file
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h
index 211878a5d..b08a1f13b 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Tracealyzer v2.5.0 Recorder Library
+ * Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernelPort.h
@@ -40,6 +40,9 @@
#define TRCKERNELPORT_H_
#include "FreeRTOS.h" // Defines configUSE_TRACE_FACILITY
+#include "trcHardwarePort.h"
+
+extern int uiInEventGroupSetBitsFromISR;
#define USE_TRACEALYZER_RECORDER configUSE_TRACE_FACILITY
@@ -48,18 +51,42 @@
/* Defines that must be set for the recorder to work properly */
#define TRACE_KERNEL_VERSION 0x1AA1
#define TRACE_TICK_RATE_HZ configTICK_RATE_HZ /* Defined in "FreeRTOS.h" */
+#define TRACE_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOSConfig.h" */
+
+#if ((SELECTED_PORT == PORT_ARM_CortexM) && (USE_PRIMASK_CS == 1))
+
+#define TRACE_SR_ALLOC_CRITICAL_SECTION() int __irq_status;
+
+#define TRACE_ENTER_CRITICAL_SECTION() { __irq_status = prvTraceGetIRQMask(); prvTraceDisableIRQ(); }
+
+#define TRACE_EXIT_CRITICAL_SECTION() { prvTraceSetIRQMask(__irq_status); }
+
+#define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_BEGIN
+#define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_END
+
+#else
+
+#define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL()
+#define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL()
+
+#define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY() recorder_busy++;
+#define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--;
+
+#endif
/************************************************************************/
/* KERNEL SPECIFIC OBJECT CONFIGURATION */
/************************************************************************/
-#define TRACE_NCLASSES 5
+#define TRACE_NCLASSES 7
#define TRACE_CLASS_QUEUE ((traceObjectClass)0)
#define TRACE_CLASS_SEMAPHORE ((traceObjectClass)1)
#define TRACE_CLASS_MUTEX ((traceObjectClass)2)
#define TRACE_CLASS_TASK ((traceObjectClass)3)
#define TRACE_CLASS_ISR ((traceObjectClass)4)
+#define TRACE_CLASS_TIMER ((traceObjectClass)5)
+#define TRACE_CLASS_EVENTGROUP ((traceObjectClass)6)
-#define TRACE_KERNEL_OBJECT_COUNT (NQueue + NSemaphore + NMutex + NTask + NISR)
+#define TRACE_KERNEL_OBJECT_COUNT (NQueue + NSemaphore + NMutex + NTask + NISR + NTimer + NEventGroup)
/* The size of the Object Property Table entries, in bytes, per object */
@@ -82,22 +109,30 @@
Byte 1: state (if already active) */
#define PropertyTableSizeISR (NameLenISR + 2)
+/* NTimer properties: Byte 0: state (unused for now) */
+#define PropertyTableSizeTimer (NameLenTimer + 1)
+
+/* NEventGroup properties: Byte 0-3: state (unused for now)*/
+#define PropertyTableSizeEventGroup (NameLenEventGroup + 4)
+
+
/* 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 StartIndexTimer StartIndexISR + NISR * PropertyTableSizeISR
+#define StartIndexEventGroup StartIndexTimer + NTimer * PropertyTableSizeTimer
/* Number of bytes used by the object table */
-#define TRACE_OBJECT_TABLE_SIZE StartIndexISR + NISR * PropertyTableSizeISR
-
+#define TRACE_OBJECT_TABLE_SIZE StartIndexEventGroup + NEventGroup * PropertyTableSizeEventGroup
/* Includes */
+#include "trcConfig.h" /* Must be first, even before trcTypes.h */
+#include "trcHardwarePort.h"
#include "trcTypes.h"
-#include "trcConfig.h"
#include "trcKernelHooks.h"
-#include "trcHardwarePort.h"
#include "trcBase.h"
#include "trcKernel.h"
#include "trcUser.h"
@@ -187,7 +222,7 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
* The lower three bits in the event code gives the object class, i.e., type of
* create operation (task, queue, semaphore, etc).
******************************************************************************/
-#define EVENTGROUP_CREATE_SUCCESS (EVENTGROUP_OBJCLOSE_PROP + 8) /*0x18*/
+#define EVENTGROUP_CREATE_OBJ_SUCCESS (EVENTGROUP_OBJCLOSE_PROP + 8) /*0x18*/
/*******************************************************************************
* EVENTGROUP_SEND
@@ -197,7 +232,7 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
* object class, i.e., what type of object that is operated on (queue, semaphore
* or mutex).
******************************************************************************/
-#define EVENTGROUP_SEND_SUCCESS (EVENTGROUP_CREATE_SUCCESS + 8) /*0x20*/
+#define EVENTGROUP_SEND_SUCCESS (EVENTGROUP_CREATE_OBJ_SUCCESS + 8) /*0x20*/
/*******************************************************************************
* EVENTGROUP_RECEIVE
@@ -219,10 +254,10 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
#define EVENTGROUP_KSE_FAILED (EVENTGROUP_RECEIVE_FROM_ISR_SUCCESS + 8) /*0x40*/
/* Failed create calls - memory allocation failed */
-#define EVENTGROUP_CREATE_FAILED (EVENTGROUP_KSE_FAILED) /*0x40*/
+#define EVENTGROUP_CREATE_OBJ_FAILED (EVENTGROUP_KSE_FAILED) /*0x40*/
/* Failed send/give - timeout! */
-#define EVENTGROUP_SEND_FAILED (EVENTGROUP_CREATE_FAILED + 8) /*0x48*/
+#define EVENTGROUP_SEND_FAILED (EVENTGROUP_CREATE_OBJ_FAILED + 8) /*0x48*/
/* Failed receive/take - timeout! */
#define EVENTGROUP_RECEIVE_FAILED (EVENTGROUP_SEND_FAILED + 8) /*0x50*/
@@ -245,10 +280,10 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
#define EVENTGROUP_PEEK_SUCCESS (EVENTGROUP_SEND_BLOCK + 8) /*0x78*/
/* Events on object delete (vTaskDelete or vQueueDelete) */
-#define EVENTGROUP_DELETE_SUCCESS (EVENTGROUP_PEEK_SUCCESS + 8) /*0x80*/
+#define EVENTGROUP_DELETE_OBJ_SUCCESS (EVENTGROUP_PEEK_SUCCESS + 8) /*0x80*/
/* Other events - object class is implied: TASK */
-#define EVENTGROUP_OTHERS (EVENTGROUP_DELETE_SUCCESS + 8) /*0x88*/
+#define EVENTGROUP_OTHERS (EVENTGROUP_DELETE_OBJ_SUCCESS + 8) /*0x88*/
#define TASK_DELAY_UNTIL (EVENTGROUP_OTHERS + 0) /*0x88*/
#define TASK_DELAY (EVENTGROUP_OTHERS + 1) /*0x89*/
#define TASK_SUSPEND (EVENTGROUP_OTHERS + 2) /*0x8A*/
@@ -258,11 +293,18 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
#define TASK_PRIORITY_INHERIT (EVENTGROUP_OTHERS + 6) /*0x8E*/
#define TASK_PRIORITY_DISINHERIT (EVENTGROUP_OTHERS + 7) /*0x8F*/
-/* Not yet used */
-#define EVENTGROUP_FTRACE_PLACEHOLDER (EVENTGROUP_OTHERS + 8) /*0x90*/
+#define EVENTGROUP_MISC_PLACEHOLDER (EVENTGROUP_OTHERS + 8) /*0x90*/
+#define PEND_FUNC_CALL (EVENTGROUP_MISC_PLACEHOLDER+0) /*0x90*/
+#define PEND_FUNC_CALL_FROM_ISR (EVENTGROUP_MISC_PLACEHOLDER+1) /*0x91*/
+#define PEND_FUNC_CALL_FAILED (EVENTGROUP_MISC_PLACEHOLDER+2) /*0x92*/
+#define PEND_FUNC_CALL_FROM_ISR_FAILED (EVENTGROUP_MISC_PLACEHOLDER+3) /*0x93*/
+#define MEM_MALLOC_SIZE (EVENTGROUP_MISC_PLACEHOLDER+4) /*0x94*/
+#define MEM_MALLOC_ADDR (EVENTGROUP_MISC_PLACEHOLDER+5) /*0x95*/
+#define MEM_FREE_SIZE (EVENTGROUP_MISC_PLACEHOLDER+6) /*0x96*/
+#define MEM_FREE_ADDR (EVENTGROUP_MISC_PLACEHOLDER+7) /*0x97*/
/* User events */
-#define EVENTGROUP_USEREVENT (EVENTGROUP_FTRACE_PLACEHOLDER + 8) /*0x98*/
+#define EVENTGROUP_USEREVENT (EVENTGROUP_MISC_PLACEHOLDER + 8) /*0x98*/
#define USER_EVENT (EVENTGROUP_USEREVENT + 0)
/* Allow for 0-15 arguments (the number of args is added to event code) */
@@ -300,7 +342,47 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
#define LOW_POWER_BEGIN (EVENTGROUP_SYS + 4) /*0xAC*/
#define LOW_POWER_END (EVENTGROUP_SYS + 5) /*0xAD*/
-
+#define XID (EVENTGROUP_SYS + 6) /*0xAE*/
+
+#define XTS16L (EVENTGROUP_SYS + 7) /*0xAF*/
+
+#define EVENTGROUP_TIMER (EVENTGROUP_SYS + 8) /*0xB0*/
+
+#define TIMER_CREATE (EVENTGROUP_TIMER + 0) /*0xB0*/
+#define TIMER_START (EVENTGROUP_TIMER + 1) /*0xB0*/
+#define TIMER_RESET (EVENTGROUP_TIMER + 2) /*0xB1*/
+#define TIMER_STOP (EVENTGROUP_TIMER + 3) /*0xB2*/
+#define TIMER_CHANGE_PERIOD (EVENTGROUP_TIMER + 4) /*0xB3*/
+#define TIMER_DELETE (EVENTGROUP_TIMER + 5) /*0xB4*/
+#define TIMER_START_FROM_ISR (EVENTGROUP_TIMER + 6) /*0xB6*/
+#define TIMER_RESET_FROM_ISR (EVENTGROUP_TIMER + 7) /*0xB7*/
+#define TIMER_STOP_FROM_ISR (EVENTGROUP_TIMER + 8) /*0xB8*/
+
+#define TIMER_CREATE_FAILED (EVENTGROUP_TIMER + 9) /*0xB9*/
+#define TIMER_START_FAILED (EVENTGROUP_TIMER + 10) /*0xBA*/
+#define TIMER_RESET_FAILED (EVENTGROUP_TIMER + 11) /*0xBB*/
+#define TIMER_STOP_FAILED (EVENTGROUP_TIMER + 12) /*0xBC*/
+#define TIMER_CHANGE_PERIOD_FAILED (EVENTGROUP_TIMER + 13) /*0xBD*/
+#define TIMER_DELETE_FAILED (EVENTGROUP_TIMER + 14) /*0xBE*/
+#define TIMER_START_FROM_ISR_FAILED (EVENTGROUP_TIMER + 15) /*0xBF*/
+#define TIMER_RESET_FROM_ISR_FAILED (EVENTGROUP_TIMER + 16) /*0xC0*/
+#define TIMER_STOP_FROM_ISR_FAILED (EVENTGROUP_TIMER + 17) /*0xC1*/
+
+#define EVENTGROUP_EG (EVENTGROUP_TIMER + 18) /*0xC2*/
+#define EVENT_GROUP_CREATE (EVENTGROUP_EG + 0) /*0xC2*/
+#define EVENT_GROUP_CREATE_FAILED (EVENTGROUP_EG + 1) /*0xC3*/
+#define EVENT_GROUP_SYNC_BLOCK (EVENTGROUP_EG + 2) /*0xC4*/
+#define EVENT_GROUP_SYNC_END (EVENTGROUP_EG + 3) /*0xC5*/
+#define EVENT_GROUP_WAIT_BITS_BLOCK (EVENTGROUP_EG + 4) /*0xC6*/
+#define EVENT_GROUP_WAIT_BITS_END (EVENTGROUP_EG + 5) /*0xC7*/
+#define EVENT_GROUP_CLEAR_BITS (EVENTGROUP_EG + 6) /*0xC8*/
+#define EVENT_GROUP_CLEAR_BITS_FROM_ISR (EVENTGROUP_EG + 7) /*0xC9*/
+#define EVENT_GROUP_SET_BITS (EVENTGROUP_EG + 8) /*0xCA*/
+#define EVENT_GROUP_DELETE (EVENTGROUP_EG + 9) /*0xCB*/
+#define EVENT_GROUP_SYNC_END_FAILED (EVENTGROUP_EG + 10) /*0xCC*/
+#define EVENT_GROUP_WAIT_BITS_END_FAILED (EVENTGROUP_EG + 11) /*0xCD*/
+#define EVENT_GROUP_SET_BITS_FROM_ISR (EVENTGROUP_EG + 12) /*0xCE*/
+#define EVENT_GROUP_SET_BITS_FROM_ISR_FAILED (EVENTGROUP_EG + 13) /*0xCF*/
/************************************************************************/
/* KERNEL SPECIFIC DATA AND FUNCTIONS NEEDED TO PROVIDE THE */
@@ -330,20 +412,18 @@ objectHandleType prvTraceGetTaskNumber(void* handle);
unsigned char prvTraceIsSchedulerActive(void);
unsigned char prvTraceIsSchedulerSuspended(void);
unsigned char prvTraceIsSchedulerStarted(void);
-void prvTraceEnterCritical(void);
-void prvTraceExitCritical(void);
void* prvTraceGetCurrentTaskHandle(void);
+#if (configUSE_TIMERS == 1)
+#undef INCLUDE_xTimerGetTimerDaemonTaskHandle
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1
+#endif
/************************************************************************/
/* KERNEL SPECIFIC MACROS USED BY THE TRACE RECORDER */
/************************************************************************/
#define TRACE_MALLOC(size) pvPortMalloc(size)
-
-#define TRACE_ENTER_CRITICAL_SECTION() prvTraceEnterCritical();
-#define TRACE_EXIT_CRITICAL_SECTION() prvTraceExitCritical();
-
#define TRACE_IS_SCHEDULER_ACTIVE() prvTraceIsSchedulerActive()
#define TRACE_IS_SCHEDULER_STARTED() prvTraceIsSchedulerStarted()
#define TRACE_IS_SCHEDULER_SUSPENDED() prvTraceIsSchedulerSuspended()
@@ -357,12 +437,20 @@ void* prvTraceGetCurrentTaskHandle(void);
#define TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass) TraceObjectClassTable[kernelClass]
#define TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject) TRACE_GET_CLASS_TRACE_CLASS(CLASS, prvTraceGetObjectType(pxObject))
+#define TRACE_GET_TIMER_NUMBER(tmr) ( ( objectHandleType ) ((Timer_t*)tmr)->uxTimerNumber )
+#define TRACE_SET_TIMER_NUMBER(tmr) ((Timer_t*)tmr)->uxTimerNumber = xTraceGetObjectHandle(TRACE_CLASS_TIMER);
+#define TRACE_GET_TIMER_NAME(pxTimer) pxTimer->pcTimerName
+#define TRACE_GET_TIMER_PERIOD(pxTimer) pxTimer->xTimerPeriodInTicks
+
+#define TRACE_GET_EVENTGROUP_NUMBER(eg) ( ( objectHandleType ) uxEventGroupGetNumber(eg) )
+#define TRACE_SET_EVENTGROUP_NUMBER(eg) ((EventGroup_t*)eg)->uxEventGroupNumber = xTraceGetObjectHandle(TRACE_CLASS_EVENTGROUP);
+
#define TRACE_GET_OBJECT_NUMBER(CLASS, pxObject) (prvTraceGetObjectNumber(pxObject))
#define TRACE_SET_OBJECT_NUMBER(CLASS, pxObject) pxObject->uxQueueNumber = xTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject));
#define TRACE_GET_CLASS_EVENT_CODE(SERVICE, RESULT, CLASS, kernelClass) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass))
#define TRACE_GET_OBJECT_EVENT_CODE(SERVICE, RESULT, CLASS, pxObject) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject))
-#define TRACE_GET_TASK_EVENT_CODE(SERVICE, RESULT, CLASS, pxTCB) (EVENTGROUP_##SERVICE##_##RESULT + TRACE_CLASS_TASK)
+#define TRACE_GET_TASK_EVENT_CODE(SERVICE, RESULT, CLASS, pxTCB) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_CLASS_TASK)
/************************************************************************/
/* KERNEL SPECIFIC WRAPPERS THAT SHOULD BE CALLED BY THE KERNEL */
@@ -386,17 +474,18 @@ void* prvTraceGetCurrentTaskHandle(void);
vTraceStoreLowPower(1); \
}
-/* A macro that will update the tick count when returning from tickless idle */
-#undef traceINCREASE_TICK_COUNT( xCount )
-#define traceINCREASE_TICK_COUNT( xCount ) { extern uint32_t uiTraceTickCount; uiTraceTickCount += xTickCount; }
-
#endif
+/* A macro that will update the tick count when returning from tickless idle */
+#undef traceINCREASE_TICK_COUNT
+/* Note: This can handle time adjustments of max 2^32 ticks, i.e., 35 seconds at 120 MHz. Thus, tick-less idle periods longer than 2^32 ticks will appear "compressed" on the time line.*/
+#define traceINCREASE_TICK_COUNT( xCount ) { DWT_CYCLES_ADDED += (xCount * (TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ)); }
+
/* Called for each task that becomes ready */
#undef traceMOVED_TASK_TO_READY_STATE
#define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB);
-
+
/* Called on each OS tick. Will call uiPortGetTimestamp to make sure it is called at least once every OS tick. */
#undef traceTASK_INCREMENT_TICK
#define traceTASK_INCREMENT_TICK( xTickCount ) \
@@ -411,38 +500,38 @@ void* prvTraceGetCurrentTaskHandle(void);
/* Called on vTaskSuspend */
#undef traceTASK_SUSPEND
#define traceTASK_SUSPEND( pxTaskToSuspend ) \
- trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend);
+ trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend);
/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */
#undef traceTASK_DELAY
#define traceTASK_DELAY() \
- TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY, pxCurrentTCB, xTicksToDelay); \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(UNUSED,pxCurrentTCB); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */
#undef traceTASK_DELAY_UNTIL
#define traceTASK_DELAY_UNTIL() \
- TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(UNUSED,pxCurrentTCB); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
#if (INCLUDE_OBJECT_DELETE == 1)
/* Called on vTaskDelete */
#undef traceTASK_DELETE
#define traceTASK_DELETE( pxTaskToDelete ) \
- trcKERNEL_HOOKS_TASK_DELETE(DELETE, pxTaskToDelete);
+ { TRACE_SR_ALLOC_CRITICAL_SECTION(); \
+ TRACE_ENTER_CRITICAL_SECTION(); \
+ trcKERNEL_HOOKS_TASK_DELETE(DELETE_OBJ, pxTaskToDelete); \
+ TRACE_EXIT_CRITICAL_SECTION(); }
#endif
#if (INCLUDE_OBJECT_DELETE == 1)
/* Called on vQueueDelete */
#undef traceQUEUE_DELETE
#define traceQUEUE_DELETE( pxQueue ) \
+ { TRACE_SR_ALLOC_CRITICAL_SECTION(); \
TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_OBJECT_DELETE(DELETE, UNUSED, pxQueue); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_OBJECT_DELETE(DELETE_OBJ, UNUSED, pxQueue); \
+ TRACE_EXIT_CRITICAL_SECTION(); }
#endif
/* Called on vTaskCreate */
@@ -450,94 +539,72 @@ void* prvTraceGetCurrentTaskHandle(void);
#define traceTASK_CREATE(pxNewTCB) \
if (pxNewTCB != NULL) \
{ \
- trcKERNEL_HOOKS_TASK_CREATE(CREATE, pxNewTCB); \
+ trcKERNEL_HOOKS_TASK_CREATE(CREATE_OBJ, UNUSED, pxNewTCB); \
}
/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */
#undef traceTASK_CREATE_FAILED
#define traceTASK_CREATE_FAILED() \
- TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_TASK_CREATE_FAILED(CREATE); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_TASK_CREATE_FAILED(CREATE_OBJ, UNUSED);
/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */
#undef traceQUEUE_CREATE
#define traceQUEUE_CREATE( pxNewQueue )\
- TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_OBJECT_CREATE(CREATE, UNUSED, pxNewQueue); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_OBJECT_CREATE(CREATE_OBJ, UNUSED, pxNewQueue);
/* Called in xQueueCreate, if the queue creation fails */
#undef traceQUEUE_CREATE_FAILED
#define traceQUEUE_CREATE_FAILED( queueType ) \
- TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE, UNUSED, queueType); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE_OBJ, UNUSED, queueType);
/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */
#undef traceCREATE_MUTEX
#define traceCREATE_MUTEX( pxNewQueue ) \
- TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_OBJECT_CREATE(CREATE, UNUSED, pxNewQueue); \
- TRACE_EXIT_CRITICAL_SECTION();
-
+ trcKERNEL_HOOKS_OBJECT_CREATE(CREATE_OBJ, UNUSED, pxNewQueue);
+
/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */
#undef traceCREATE_MUTEX_FAILED
#define traceCREATE_MUTEX_FAILED() \
- TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE, UNUSED, queueQUEUE_TYPE_MUTEX); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE_OBJ, UNUSED, queueQUEUE_TYPE_MUTEX);
/* Called when the Mutex can not be given, since not holder */
#undef traceGIVE_MUTEX_RECURSIVE_FAILED
#define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) \
- TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxMutex); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxMutex);
-/* Called when a message is sent to a queue */
+/* Called when a message is sent to a queue */ /* CS IS NEW ! */
#undef traceQUEUE_SEND
#define traceQUEUE_SEND( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, SUCCESS, UNUSED, pxQueue); \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(UNUSED, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, pxQueue) == TRACE_CLASS_MUTEX ? (uint8_t)0 : (uint8_t)(pxQueue->uxMessagesWaiting + 1)); /*For mutex, store the new owner rather than queue length */
+ trcKERNEL_HOOKS_SET_OBJECT_STATE(UNUSED, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, pxQueue) == TRACE_CLASS_MUTEX ? (uint8_t)0 : (uint8_t)(pxQueue->uxMessagesWaiting + 1));
/* Called when a message failed to be sent to a queue (timeout) */
#undef traceQUEUE_SEND_FAILED
#define traceQUEUE_SEND_FAILED( pxQueue ) \
- TRACE_ENTER_CRITICAL_SECTION();\
- trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxQueue); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxQueue);
/* Called when the task is blocked due to a send operation on a full queue */
#undef traceBLOCKING_ON_QUEUE_SEND
#define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) \
- TRACE_ENTER_CRITICAL_SECTION();\
- trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, BLOCK, UNUSED, pxQueue); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, BLOCK, UNUSED, pxQueue);
/* Called when a message is received from a queue */
#undef traceQUEUE_RECEIVE
#define traceQUEUE_RECEIVE( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, SUCCESS, UNUSED, pxQueue); \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(UNUSED, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, pxQueue) == TRACE_CLASS_MUTEX ? TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()) : (uint8_t)(pxQueue->uxMessagesWaiting - 1)); /*For mutex, store the new owner rather than queue length */
+ trcKERNEL_HOOKS_SET_OBJECT_STATE(UNUSED, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, pxQueue) == TRACE_CLASS_MUTEX ? TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()) : (uint8_t)(pxQueue->uxMessagesWaiting - 1));
/* Called when a receive operation on a queue fails (timeout) */
#undef traceQUEUE_RECEIVE_FAILED
#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \
- TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, FAILED, UNUSED, pxQueue); \
- TRACE_EXIT_CRITICAL_SECTION();
+ trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, FAILED, UNUSED, pxQueue);
/* Called when the task is blocked due to a receive operation on an empty queue */
#undef traceBLOCKING_ON_QUEUE_RECEIVE
#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \
- TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, BLOCK, UNUSED, pxQueue); \
if (TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, pxQueue) != TRACE_CLASS_MUTEX) \
- { \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(UNUSED, pxQueue); \
- } \
- TRACE_EXIT_CRITICAL_SECTION();
+ {trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();}
/* Called on xQueuePeek */
#undef traceQUEUE_PEEK
@@ -554,43 +621,138 @@ void* prvTraceGetCurrentTaskHandle(void);
#undef traceQUEUE_SEND_FROM_ISR_FAILED
#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND_FROM_ISR, FAILED, UNUSED, pxQueue);
-
+
/* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */
#undef traceQUEUE_RECEIVE_FROM_ISR
#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE_FROM_ISR, SUCCESS, UNUSED, pxQueue); \
trcKERNEL_HOOKS_SET_OBJECT_STATE(UNUSED, pxQueue, (uint8_t)(pxQueue->uxMessagesWaiting - 1));
-
+
/* Called when a message receive from interrupt context fails (since the queue was empty) */
#undef traceQUEUE_RECEIVE_FROM_ISR_FAILED
#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE_FROM_ISR, FAILED, UNUSED, pxQueue);
-
+
/* Called in vTaskPrioritySet */
#undef traceTASK_PRIORITY_SET
#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \
trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_SET, pxTask, uxNewPriority);
-
+
/* Called in vTaskPriorityInherit, which is called by Mutex operations */
#undef traceTASK_PRIORITY_INHERIT
#define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \
trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_INHERIT, pxTask, uxNewPriority);
-
+
/* Called in vTaskPriorityDisinherit, which is called by Mutex operations */
#undef traceTASK_PRIORITY_DISINHERIT
#define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \
trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_DISINHERIT, pxTask, uxNewPriority);
-
+
/* Called in vTaskResume */
#undef traceTASK_RESUME
#define traceTASK_RESUME( pxTaskToResume ) \
trcKERNEL_HOOKS_TASK_RESUME(TASK_RESUME, pxTaskToResume);
-
+
/* Called in vTaskResumeFromISR */
#undef traceTASK_RESUME_FROM_ISR
#define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) \
trcKERNEL_HOOKS_TASK_RESUME(TASK_RESUME_FROM_ISR, pxTaskToResume);
+
+
+/* Called in timer.c - xTimerCreate */
+#undef traceTIMER_CREATE
+#define traceTIMER_CREATE(tmr) \
+ trcKERNEL_HOOKS_TIMER_CREATE(TIMER_CREATE, tmr);
+
+#undef traceTIMER_CREATE_FAILED
+#define traceTIMER_CREATE_FAILED() \
+ trcKERNEL_HOOKS_TIMER_EVENT(TIMER_CREATE_FAILED, 0);
+
+/* Note that xCommandID can never be tmrCOMMAND_EXECUTE_CALLBACK (-1) since the trace macro is not called in that case */
+#undef traceTIMER_COMMAND_SEND
+#define traceTIMER_COMMAND_SEND(tmr, xCommandID, xOptionalValue, xReturn) \
+if (xCommandID > tmrCOMMAND_START_DONT_TRACE){\
+ if (xCommandID == tmrCOMMAND_CHANGE_PERIOD) vTraceStoreKernelCallWithParam((xReturn == pdPASS) ? TIMER_CHANGE_PERIOD : TIMER_CHANGE_PERIOD_FAILED, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(tmr), xOptionalValue);\
+ else if ((xCommandID == tmrCOMMAND_DELETE) && (xReturn == pdPASS)){ trcKERNEL_HOOKS_TIMER_DELETE(TIMER_DELETE, tmr); } \
+ else {trcKERNEL_HOOKS_TIMER_EVENT(EVENTGROUP_TIMER + xCommandID + ((xReturn == pdPASS)?0:(TIMER_CREATE_FAILED - TIMER_CREATE)), tmr); }\
+}
+#undef tracePEND_FUNC_CALL
+#define tracePEND_FUNC_CALL(func, arg1, arg2, ret) \
+if (ret == pdPASS) \
+ vTraceStoreKernelCall(PEND_FUNC_CALL, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTimerGetTimerDaemonTaskHandle()) ); \
+else \
+ vTraceStoreKernelCall(PEND_FUNC_CALL_FAILED, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTimerGetTimerDaemonTaskHandle()) );
+
+#undef tracePEND_FUNC_CALL_FROM_ISR
+#define tracePEND_FUNC_CALL_FROM_ISR(func, arg1, arg2, ret) \
+ if (! uiInEventGroupSetBitsFromISR) vTraceStoreKernelCall(PEND_FUNC_CALL_FROM_ISR, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTimerGetTimerDaemonTaskHandle()) ); \
+ uiInEventGroupSetBitsFromISR = 0;
+
+#undef traceEVENT_GROUP_CREATE
+#define traceEVENT_GROUP_CREATE(eg) \
+ TRACE_SET_EVENTGROUP_NUMBER(eg); \
+ vTraceStoreKernelCall(EVENT_GROUP_CREATE, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg));
+
+#undef traceEVENT_GROUP_DELETE
+#define traceEVENT_GROUP_DELETE(eg) \
+ vTraceStoreKernelCall(EVENT_GROUP_DELETE, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg)); \
+ vTraceStoreObjectNameOnCloseEvent(TRACE_GET_EVENTGROUP_NUMBER(eg), TRACE_CLASS_EVENTGROUP); \
+ vTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_EVENTGROUP_NUMBER(eg), TRACE_CLASS_EVENTGROUP); \
+ vTraceFreeObjectHandle(TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg));
+
+#undef traceEVENT_GROUP_CREATE_FAILED
+#define traceEVENT_GROUP_CREATE_FAILED() \
+ vTraceStoreKernelCall(EVENT_GROUP_CREATE_FAILED, TRACE_CLASS_EVENTGROUP, 0);
+
+#undef traceEVENT_GROUP_SYNC_BLOCK
+#define traceEVENT_GROUP_SYNC_BLOCK(eg, bitsToSet, bitsToWaitFor) \
+ vTraceStoreKernelCallWithParam(EVENT_GROUP_SYNC_BLOCK, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor);
+
+#undef traceEVENT_GROUP_SYNC_END
+#define traceEVENT_GROUP_SYNC_END(eg, bitsToSet, bitsToWaitFor, wasTimeout) \
+ if (wasTimeout){ vTraceStoreKernelCallWithParam(EVENT_GROUP_SYNC_END_FAILED, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor);} \
+ else{ vTraceStoreKernelCallWithParam(EVENT_GROUP_SYNC_END, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); }
+
+#undef traceEVENT_GROUP_WAIT_BITS_BLOCK
+#define traceEVENT_GROUP_WAIT_BITS_BLOCK(eg, bitsToWaitFor) \
+ vTraceStoreKernelCallWithParam(EVENT_GROUP_WAIT_BITS_BLOCK, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); \
+ trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
+
+#undef traceEVENT_GROUP_WAIT_BITS_END
+#define traceEVENT_GROUP_WAIT_BITS_END(eg, bitsToWaitFor, wasTimeout) \
+ if (wasTimeout){ vTraceStoreKernelCallWithParam(EVENT_GROUP_WAIT_BITS_END_FAILED, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); } \
+ else{ vTraceStoreKernelCallWithParam(EVENT_GROUP_WAIT_BITS_END, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); }
+
+#undef traceEVENT_GROUP_CLEAR_BITS
+#define traceEVENT_GROUP_CLEAR_BITS(eg, bitsToClear) \
+ if (bitsToClear) vTraceStoreKernelCallWithParam(EVENT_GROUP_CLEAR_BITS, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToClear);
+
+#undef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR
+#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(eg, bitsToClear) \
+ if (bitsToClear) vTraceStoreKernelCallWithParam(EVENT_GROUP_CLEAR_BITS_FROM_ISR, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToClear);
+
+#undef traceEVENT_GROUP_SET_BITS
+#define traceEVENT_GROUP_SET_BITS(eg, bitsToSet) \
+ vTraceStoreKernelCallWithParam(EVENT_GROUP_SET_BITS, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToSet);
+
+#undef traceEVENT_GROUP_SET_BITS_FROM_ISR
+#define traceEVENT_GROUP_SET_BITS_FROM_ISR(eg, bitsToSet) \
+ vTraceStoreKernelCallWithParam(EVENT_GROUP_SET_BITS_FROM_ISR, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToSet); \
+ uiInEventGroupSetBitsFromISR = 1;
+
+#if (INCLUDE_MEMMANG_EVENTS == 1)
+
+extern void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, uint32_t size);
+
+#undef traceMALLOC
+#define traceMALLOC( pvAddress, uiSize ) {vTraceStoreMemMangEvent(MEM_MALLOC_SIZE, ( uint32_t ) pvAddress, uiSize); TRACE_UPDATE_HEAP_USAGE_POSITIVE(uiSize);}
+
+
+#undef traceFREE
+#define traceFREE( pvAddress, uiSize ) {vTraceStoreMemMangEvent(MEM_FREE_SIZE, ( uint32_t ) pvAddress, uiSize); TRACE_UPDATE_HEAP_USAGE_NEGATIVE(uiSize);}
+
+#endif
/************************************************************************/
/* KERNEL SPECIFIC MACROS TO EXCLUDE OR INCLUDE THINGS IN TRACE */
@@ -615,6 +777,15 @@ uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, objectHandleType h
#define TRACE_CLEAR_TASK_FLAG_ISEXCLUDED(taskIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+taskIndex)
#define TRACE_GET_TASK_FLAG_ISEXCLUDED(taskIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+taskIndex)
+#define TRACE_SET_TIMER_FLAG_ISEXCLUDED(timerIndex) TRACE_SET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+timerIndex)
+#define TRACE_CLEAR_TIMER_FLAG_ISEXCLUDED(timerIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+timerIndex)
+#define TRACE_GET_TIMER_FLAG_ISEXCLUDED(timerIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+timerIndex)
+
+#define TRACE_SET_EVENTGROUP_FLAG_ISEXCLUDED(egIndex) TRACE_SET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+NTimer+1+egIndex)
+#define TRACE_CLEAR_EVENTGROUP_FLAG_ISEXCLUDED(egIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+NTimer+1+egIndex)
+#define TRACE_GET_EVENTGROUP_FLAG_ISEXCLUDED(egIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+NTimer+1+egIndex)
+
+
#define TRACE_CLEAR_OBJECT_FLAG_ISEXCLUDED(objectclass, handle) \
switch (objectclass) \
{ \
@@ -630,6 +801,12 @@ case TRACE_CLASS_MUTEX: \
case TRACE_CLASS_TASK: \
TRACE_CLEAR_TASK_FLAG_ISEXCLUDED(handle); \
break; \
+case TRACE_CLASS_TIMER: \
+ TRACE_CLEAR_TIMER_FLAG_ISEXCLUDED(handle); \
+ break; \
+case TRACE_CLASS_EVENTGROUP: \
+ TRACE_CLEAR_EVENTGROUP_FLAG_ISEXCLUDED(handle); \
+ break; \
}
#define TRACE_SET_OBJECT_FLAG_ISEXCLUDED(objectclass, handle) \
@@ -647,6 +824,12 @@ case TRACE_CLASS_MUTEX: \
case TRACE_CLASS_TASK: \
TRACE_SET_TASK_FLAG_ISEXCLUDED(handle); \
break; \
+case TRACE_CLASS_TIMER: \
+ TRACE_SET_TIMER_FLAG_ISEXCLUDED(handle); \
+ break; \
+case TRACE_CLASS_EVENTGROUP: \
+ TRACE_SET_EVENTGROUP_FLAG_ISEXCLUDED(handle); \
+ break; \
}
/* Task */
@@ -680,6 +863,20 @@ TRACE_SET_MUTEX_FLAG_ISEXCLUDED(TRACE_GET_OBJECT_NUMBER(UNUSED, handle));
#define vTraceIncludeMutexInTrace(handle) \
TRACE_CLEAR_QUEUE_FLAG_ISEXCLUDED(TRACE_GET_OBJECT_NUMBER(UNUSED, handle));
+/* Timer */
+#define vTraceExcludeTimerFromTrace(handle) \
+TRACE_SET_TIMER_FLAG_ISEXCLUDED(TRACE_GET_TIMER_NUMBER(handle));
+
+#define vTraceIncludeTimerInTrace(handle) \
+TRACE_CLEAR_QUEUE_FLAG_ISEXCLUDED(TRACE_GET_TIMER_NUMBER(handle));
+
+/* Event Group */
+#define vTraceExcludeEventGroupFromTrace(handle) \
+TRACE_SET_EVENTGROUP_FLAG_ISEXCLUDED(TRACE_GET_EVENTGROUP_NUMBER(handle));
+
+#define vTraceIncludeEventGroupInTrace(handle) \
+TRACE_CLEAR_EVENTGROUP_FLAG_ISEXCLUDED(TRACE_GET_EVENTGROUP_NUMBER(handle));
+
/* Kernel Services */
#define vTraceExcludeKernelServiceDelayFromTrace() \
@@ -770,6 +967,11 @@ vTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, object), TRACE_GET_OBJE
#define vTraceSetMutexName(object, name) \
vTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, object), TRACE_GET_OBJECT_NUMBER(UNUSED, object), name);
+#define vTraceSetEventGroupName(object, name) \
+vTraceSetObjectName(TRACE_CLASS_EVENTGROUP, uxEventGroupGetNumber(object), name);
+
+#undef traceQUEUE_REGISTRY_ADD
+#define traceQUEUE_REGISTRY_ADD(object, name) vTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, object), TRACE_GET_OBJECT_NUMBER(UNUSED, object), name);
#endif
#endif /* TRCKERNELPORT_H_ */ \ No newline at end of file
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTypes.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTypes.h
index e60b34ab9..f1d434a98 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTypes.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTypes.h
@@ -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;
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcUser.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcUser.h
index c6904008b..dba4432e6 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcUser.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcUser.h
@@ -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
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/debugger trace upload.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/debugger trace upload.txt
index f815e8b21..bb25213fd 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/debugger trace upload.txt
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/debugger trace upload.txt
@@ -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.
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/readme.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/readme.txt
index 883f85ebb..2c6c55195 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/readme.txt
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/readme.txt
@@ -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
-
-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!
+- Microchip PIC32
+- NXP LPC2106
+- Texas Instruments TMS570 (Cortex-R4)
+- Texas Instruments MSP430
+- Xilinx PowerPC 405
+- Xilinx PowerPC 440
+- Xilinx Microblaze
+
+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
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcBase.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcBase.c
index bfd6cb28c..be5f93530 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcBase.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcBase.c
@@ -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 \ No newline at end of file
+#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
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c
index 6570e3553..ac4a6f263 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c
@@ -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
*
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernel.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernel.c
index 0b1770867..e79294740 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernel.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernel.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Tracealyzer v2.5.0 Recorder Library
+ * Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernel.c
@@ -58,6 +58,7 @@ void vTraceStoreTaskReady(objectHandleType handle)
{
uint16_t dts3;
TREvent* tr;
+ TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(handle > 0 && handle <= NTask, "vTraceStoreTaskReady: Invalid value for handle", );
@@ -73,6 +74,7 @@ void vTraceStoreTaskReady(objectHandleType handle)
return;
}
+ trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
if (!TRACE_GET_TASK_FLAG_ISEXCLUDED(handle))
@@ -80,19 +82,22 @@ void vTraceStoreTaskReady(objectHandleType handle)
dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
+ uint8_t hnd8 = prvTraceGet8BitHandle(handle);
+
tr = (TREvent*)xTraceNextFreeEventBufferSlot();
if (tr != NULL)
{
tr->type = DIV_TASK_READY;
tr->dts = dts3;
- tr->objHandle = handle;
+ tr->objHandle = hnd8;
prvTraceUpdateCounters();
}
}
}
}
+ trcCRITICAL_SECTION_END();
}
#endif
@@ -105,6 +110,7 @@ void vTraceStoreLowPower(uint32_t flag)
{
uint16_t dts;
LPEvent* lp;
+ TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(flag <= 1, "vTraceStoreLowPower: Invalid flag value", );
@@ -119,7 +125,8 @@ void vTraceStoreLowPower(uint32_t flag)
vTraceError("Recorder busy - high priority ISR using syscall? (1)");
return;
}
-
+
+ trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
dts = (uint16_t)prvTraceGetDTS(0xFFFF);
@@ -135,9 +142,73 @@ void vTraceStoreLowPower(uint32_t flag)
}
}
}
+ 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.
+ ******************************************************************************/
+#if (INCLUDE_MEMMANG_EVENTS == 1)
+void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, uint32_t size)
+{
+ uint8_t dts1;
+ MemEventSize * ms;
+ MemEventAddr * ma;
+ uint16_t size_low;
+ uint16_t addr_low;
+ uint8_t addr_high;
+
+ TRACE_SR_ALLOC_CRITICAL_SECTION();
+
+ 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)
+ {
+ dts1 = (uint8_t)prvTraceGetDTS(0xFF);
+
+ size_low = (uint16_t)prvTraceGetParam(0xFFFF, size);
+
+ ms = (MemEventSize *)xTraceNextFreeEventBufferSlot();
+ if (ms != NULL)
+ {
+ ms->dts = dts1;
+ ms->type = (uint8_t)ecode;
+ ms->size = size_low;
+ prvTraceUpdateCounters();
+
+ /* Storing a second record with address (signals "failed" if null) */
+ #if (HEAP_SIZE_BELOW_16M)
+ addr_low = address & 0xFFFF;
+ addr_high = (address >> 16) & 0xFF;
+ #else
+ 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! */
+ prvTraceUpdateCounters();
+ }
+ }
+ }
+ }
+ trcCRITICAL_SECTION_END();
+}
+#endif
+
+/*******************************************************************************
* vTraceStoreKernelCall
*
* This is the main integration point for storing kernel calls, and
@@ -147,7 +218,8 @@ void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_
{
KernelCall * kse;
uint16_t dts1;
-
+ 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", );
@@ -170,96 +242,106 @@ void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_
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))
- {
- trcCRITICAL_SECTION_BEGIN();
+ {
dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
+ uint8_t hnd8 = prvTraceGet8BitHandle(objectNumber);
+
kse = (KernelCall*) xTraceNextFreeEventBufferSlot();
if (kse != NULL)
{
kse->dts = dts1;
kse->type = (uint8_t)ecode;
- kse->objHandle = (uint8_t)objectNumber;
+ kse->objHandle = hnd8;
prvTraceUpdateCounters();
}
- }
- trcCRITICAL_SECTION_END();
+ }
}
}
}
+ trcCRITICAL_SECTION_END();
}
/*******************************************************************************
* vTraceStoreKernelCallWithParam
*
- * Used for storing kernel calls with a handle and a numeric parameter. This is
- * only used for traceTASK_PRIORITY_SET at the moment.
+ * 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,
- uint8_t param)
+ uint32_t param)
{
KernelCallWithParamAndHandle * kse;
- uint8_t dts2;
+ uint8_t dts2;
+ 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))
{
- 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;
- }
-
+
/* Check if the referenced object or the event code is excluded */
if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
- {
- trcCRITICAL_SECTION_BEGIN();
+ {
dts2 = (uint8_t)prvTraceGetDTS(0xFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
+ uint8_t p8 = (uint8_t) prvTraceGetParam(0xFF, param);
+
+ uint8_t hnd8 = prvTraceGet8BitHandle((objectHandleType)objectNumber);
+
kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot();
if (kse != NULL)
{
kse->dts = dts2;
kse->type = (uint8_t)evtcode;
- kse->objHandle = (uint8_t)objectNumber;
- kse->param = param;
+ kse->objHandle = hnd8;
+ kse->param = p8;
prvTraceUpdateCounters();
}
- }
- trcCRITICAL_SECTION_END();
+ }
}
}
+ trcCRITICAL_SECTION_END();
}
/*******************************************************************************
* 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)
{
@@ -296,30 +378,33 @@ void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
{
KernelCallWithParam16 * kse;
uint8_t dts6;
- uint16_t restParam = 0;
+ 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))
- {
- 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();
+ {
dts6 = (uint8_t)prvTraceGetDTS(0xFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
@@ -337,10 +422,10 @@ void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
prvTraceUpdateCounters();
}
}
- }
- trcCRITICAL_SECTION_END();
+ }
}
}
+ trcCRITICAL_SECTION_END();
}
/*******************************************************************************
@@ -352,7 +437,10 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
{
uint16_t dts3;
TSEvent* ts;
- int8_t skipEvent = 0;
+ int8_t skipEvent;
+ TRACE_SR_ALLOC_CRITICAL_SECTION();
+
+ skipEvent = 0;
TRACE_ASSERT(task_handle <= NTask, "vTraceStoreTaskswitch: Invalid value for task_handle", );
@@ -370,8 +458,7 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
function since critical sections should not be used in the context switch
event...)
***************************************************************************/
- recorder_busy++;
-
+
/* Skip the event if the task has been excluded, using vTraceExcludeTask */
if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle))
{
@@ -383,13 +470,14 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
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;
@@ -402,7 +490,10 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
+ uint8_t hnd8;
handle_of_last_logged_task = task_handle;
+ hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task);
+
ts = (TSEvent*)xTraceNextFreeEventBufferSlot();
if (ts != NULL)
@@ -418,7 +509,7 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
}
ts->dts = dts3;
- ts->objHandle = handle_of_last_logged_task;
+ ts->objHandle = hnd8;
vTraceSetObjectState(TRACE_CLASS_TASK,
handle_of_last_logged_task,
@@ -429,8 +520,7 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
}
}
- /* See comment on recorder_busy++ above. */
- recorder_busy--;
+ trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY();
}
/*******************************************************************************
@@ -454,6 +544,8 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
if (RecorderDataPtr->recorderActive)
{
+ uint8_t hnd8 = prvTraceGet8BitHandle(handle);
+
name = TRACE_PROPERTY_NAME_GET(objectclass, handle);
idx = prvTraceOpenSymbol(name, 0);
@@ -463,7 +555,7 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
if (ce != NULL)
{
ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass;
- ce->objHandle = handle;
+ ce->objHandle = hnd8;
ce->symbolIndex = idx;
prvTraceUpdateCounters();
}
@@ -499,7 +591,7 @@ void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
}
#endif
-void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value)
+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", );
@@ -507,7 +599,7 @@ void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value)
TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id) = value;
}
-uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id)
+uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, objectHandleType id)
{
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetPriorityProperty: objectclass >= TRACE_NCLASSES", 0);
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetPriorityProperty: Invalid value for id", 0);
@@ -515,7 +607,7 @@ uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id)
return TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id);
}
-void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value)
+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", );
@@ -523,7 +615,7 @@ void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value)
TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value;
}
-uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id)
+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);
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c
index 91b6a8156..166dbcc34 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c
@@ -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;
}
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcUser.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcUser.c
index 74dc8079e..5f46a809d 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcUser.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcUser.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Tracealyzer v2.5.0 Recorder Library
+ * Tracealyzer v2.6.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcUser.c
@@ -34,6 +34,8 @@
* Copyright Percepio AB, 2013.
* www.percepio.com
******************************************************************************/
+#include "FreeRTOS.h"
+#include "task.h"
#include "trcUser.h"
@@ -47,7 +49,7 @@ TRACE_STOP_HOOK vTraceStopHookPtr = (TRACE_STOP_HOOK)0;
extern uint8_t inExcludedTask;
extern uint8_t nISRactive;
-extern uint8_t handle_of_last_logged_task;
+extern objectHandleType handle_of_last_logged_task;
extern uint32_t dts_min;
extern uint32_t hwtc_count_max_after_tick;
extern uint32_t hwtc_count_sum_after_tick;
@@ -99,12 +101,15 @@ void vTraceSetRecorderData(void* pRecorderData)
******************************************************************************/
void vTraceClear(void)
{
+ TRACE_SR_ALLOC_CRITICAL_SECTION();
trcCRITICAL_SECTION_BEGIN();
RecorderDataPtr->absTimeLastEvent = 0;
RecorderDataPtr->nextFreeIndex = 0;
RecorderDataPtr->numEvents = 0;
RecorderDataPtr->bufferIsFull = 0;
+ traceErrorMessage = NULL;
+ RecorderDataPtr->internalErrorOccured = 0;
trcCRITICAL_SECTION_END();
@@ -125,7 +130,10 @@ void vTraceClear(void)
uint32_t uiTraceStart(void)
{
- objectHandleType handle = 0;
+ objectHandleType handle;
+ TRACE_SR_ALLOC_CRITICAL_SECTION();
+
+ handle = 0;
if (RecorderDataPtr == NULL)
{
@@ -300,6 +308,103 @@ void vTraceSetISRProperties(objectHandleType handle, const char* name, char prio
vTraceSetPriorityProperty(TRACE_CLASS_ISR, handle, priority);
}
+#if (SELECTED_PORT == PORT_ARM_CortexM)
+/******************************************************************************
+ * (Advanced...)
+ *
+ * ISR_TAILCHAINING_THRESHOLD (For Cortex-M devices only)
+ *
+ * ARM Cortex-M devices may execute ISRs back-to-back (tail-chained) without
+ * resuming the previous context in between. Since this is decided in
+ * hardware, we can only detect this indirectly, in the following manner:
+ *
+ * When entering vTraceStoreISRBegin, we check the number of CPU cycles since
+ * the last return of vTraceStoreISREnd. If less or equal to the constant
+ * ISR_TAILCHAINING_THRESHOLD it is assumed that the ISRs executed back-to-back
+ * (tail-chained). In that case, the previously stored RESUME event
+ * (pointed to by ptrLastISRExitEvent) is then deleted to avoid showing a
+ * fragment of the previous context in between the ISR events. The delete is
+ * made by replacing the event code with a XTS16L event, that serves to keep
+ * the differential timestamp from the earlier event.
+ *
+ * The value of ISR_TAILCHAINING_THRESHOLD depends on the interrupt latency of
+ * the processor, on the compiler and on the compiler settings, but should be
+ * around 70 cycles. The default value is 66 cycles, which should be correct when
+ * using GCC with optimizations disabled (-O0) and Cortex-M3/M4.
+ *
+ * To measure this value, see MEASURE_ISR_TAILCHAINING_THRESHOLD below.
+ *
+ * If this value set too low, tail-chained ISRs will incorrectly be shown
+ * separated, with a short fragment of the previous task or ISR in between.
+ * If this value is set too high, you get the opposite effect - separate ISRs
+ * will appear to execute tail-chained and will appear to have higher execution
+ * time and response time (maximum ISR_TAILCHAINING_THRESHOLD cycles more).
+ *****************************************************************************/
+#define ISR_TAILCHAINING_THRESHOLD 66
+
+uint8_t* ptrLastISRExitEvent = NULL;
+uint32_t DWTCycleCountAtLastISRExit = 0;
+
+/******************************************************************************
+ * (Advanced...)
+ *
+ * MEASURE_ISR_TAILCHAINING_THRESHOLD (For Cortex-M devices only)
+ *
+ * Allows for measuring the value of ISR_TAILCHAINING_THRESHOLD (see above).
+ *
+ * This is intended to measure the minimum number of clock cycles from the end
+ * of vTraceStoreISREnd to the beginning of the following vTraceStoreISRBegin.
+ * For this purpose, we assume a test setup using the SysTick interrupt, which
+ * is available on most Cortex-M devices and typically used by the RTOS kernel.
+ * To do the measurement, follow these steps:
+ *
+ * 1. Make sure MEASURE_ISR_TAILCHAINING_THRESHOLD is enabled (defined as 1)
+ *
+ * 2. Temporarily replace your SysTick handler with the following:
+ *
+ * void xPortSysTickHandler( void )
+ * {
+ * vTraceStoreISRBegin(1);
+ * vTraceStoreISREnd();
+ * }
+ *
+ * 3. To make sure that the ISRs execute back-to-back, increase the OS tick
+ * frequency to a very high level so that the OS tick interrupt execute
+ * continuously with no application tasks in between. A tick frequency of
+ * 1 MHz (1.000.000) should be sufficient.
+ *
+ * 4. Put a breakpoint in the highest priority task and make sure it is not
+ * reached. This means that the SysTick handler is executing at maximum rate
+ * and thereby tail-chained, where the interrupt latency is 6 cycles.
+ *
+ * 5. Let the system run without breakpoints and inspect the value of
+ * threshold_low_watermark. This is the minimum total latency observed.
+ * The hardware latency is 6 clock cycles due to the tail-chaining, so the
+ * software latency (SL) is then SL = threshold_low_watermark - 6.
+ *
+ * The threshold value ISR_TAILCHAINING_THRESHOLD should be SL + 2 * HL, where
+ * HL is the normal hardware interrupt latency, i.e., the number of CPU
+ * cycles to enter or exit the exception handler for an exception in task
+ * context. The HL value is 12-16 depending on core, as shown below.
+ *
+ * Values for ISR_TAILCHAINING_THRESHOLD, assuming SL = 42
+ * Cortex-M3 and M4 (HL = 12): 66 cycles
+ * Cortex-M0 (HL = 16): 74 cycles
+ * Cortex-M0+ (HL = 15): 72 cycles
+ *
+ * If the ISR_TAILCHAINING_THRESHOLD value is set too low, some tail-chained
+ * ISRs be shown separated, with a short fragment of the previous actor. If
+ * the value is set too high, separate ISRs will appear to execute tail-chained
+ * and for too long time.
+ *****************************************************************************/
+#define MEASURE_ISR_TAILCHAINING_THRESHOLD 1
+
+#if (MEASURE_ISR_TAILCHAINING_THRESHOLD == 1)
+volatile uint32_t threshold_low_watermark = 2000000000;
+#endif
+
+#endif
+
/*******************************************************************************
* vTraceStoreISRBegin
*
@@ -318,34 +423,64 @@ void vTraceSetISRProperties(objectHandleType handle, const char* name, char prio
* vTraceStoreISREnd();
* }
*
- * NOTE: You need to make sure that any traced interrupts actually are
- * disabled by trcCRITICAL_SECTION_BEGIN().
- * If an invalid call to vTraceStoreISRBegin is detected (i.e., that preempted
- * a critical section of the recorder) this will generate a recorder error
- * using vTraceError.
******************************************************************************/
void vTraceStoreISRBegin(objectHandleType handle)
{
uint16_t dts4;
- TSEvent* ts = NULL;
+ #if (SELECTED_PORT == PORT_ARM_CortexM)
+ uint32_t CPUCyclesSinceLastISRExit = DWT_CYCLE_COUNTER - DWTCycleCountAtLastISRExit;
+ #endif
+ TSEvent* ts;
+ TRACE_SR_ALLOC_CRITICAL_SECTION();
- TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid value for handle", );
+ ts = NULL;
+#if (SELECTED_PORT == PORT_ARM_CortexM)
+ if (DWTCycleCountAtLastISRExit > 0)
+ {
+ #if (MEASURE_ISR_TAILCHAINING_THRESHOLD == 1)
+ /* Allows for verifying the value of ISR_TAILCHAINING_THRESHOLD */
+ if (CPUCyclesSinceLastISRExit < threshold_low_watermark)
+ {
+ threshold_low_watermark = CPUCyclesSinceLastISRExit;
+ }
+ #endif
+
+ if (CPUCyclesSinceLastISRExit <= ISR_TAILCHAINING_THRESHOLD)
+ {
+ /* This is judged to be a case of ISR tail-chaining since the
+ number of cycles since the last vTraceStoreISREnd is shorter or equal to
+ the threshold (ISR_TAILCHAINING_THRESHOLD) */
+
+ if (ptrLastISRExitEvent != NULL)
+ {
+ /* Overwrite the last ISR exit event with a "neutral" event that only
+ accounts for the time passed */
+ *ptrLastISRExitEvent = XTS16L;
+ }
+ }
+
+ }
+#endif
+
if (recorder_busy)
{
vTraceError("Illegal call to vTraceStoreISRBegin, recorder busy!");
return;
}
+ trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
{
- trcCRITICAL_SECTION_BEGIN();
+
+ TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid value for handle", );
+
dts4 = (uint16_t)prvTraceGetDTS(0xFFFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
-
if (nISRactive < MAX_ISR_NESTING)
{
+ uint8_t hnd8 = prvTraceGet8BitHandle(handle);
isrstack[nISRactive] = handle;
nISRactive++;
ts = (TSEvent*)xTraceNextFreeEventBufferSlot();
@@ -353,7 +488,7 @@ void vTraceStoreISRBegin(objectHandleType handle)
{
ts->type = TS_ISR_BEGIN;
ts->dts = dts4;
- ts->objHandle = handle;
+ ts->objHandle = hnd8;
prvTraceUpdateCounters();
}
}
@@ -362,40 +497,11 @@ void vTraceStoreISRBegin(objectHandleType handle)
/* This should not occur unless something is very wrong */
vTraceError("Too many nested interrupts!");
}
- }
- trcCRITICAL_SECTION_END();
- }
-}
-
-
-#if (SELECTED_PORT == PORT_ARM_CortexM)
-
-static int tailchain_irq_pending(void);
-
-/*******************************************************************************
- * tailchain_irq_pending
- *
- * For Cortex-M chips only. Returns 1 if an interrupt is pending, by checking
- * the 8 NVIC IRQ pend registers at 0xE000E200 to 0xE000E21C. Returns 0 if no
- * interrupt is pending. This is used to predict tailchaining of ISRs.
- ******************************************************************************/
-static int tailchain_irq_pending(void)
-{
- uint32_t* pend_reg = ((uint32_t*)0xE000E200);
- int i;
-
- for (i=0; i<8; i++)
- {
- if (pend_reg[i] != 0)
- {
- return 1;
+ }
}
- }
- return 0;
+ trcCRITICAL_SECTION_END();
}
-#endif
-
/*******************************************************************************
* vTraceStoreISREnd
*
@@ -414,63 +520,61 @@ static int tailchain_irq_pending(void)
* vTraceStoreISREnd();
* }
*
- * NOTE: You need to make sure that any traced interrupts actually are
- * disabled by trcCRITICAL_SECTION_BEGIN().
- * If an invalid call to vTraceStoreISREnd is detected (i.e., that preempted
- * a critical section of the recorder) this will generate a recorder error
- * using vTraceError.
******************************************************************************/
void vTraceStoreISREnd(void)
{
- TSEvent* ts;
- uint16_t dts5;
+ TSEvent* ts;
+ uint16_t dts5;
+ TRACE_SR_ALLOC_CRITICAL_SECTION();
- if (recorder_busy)
- {
- vTraceError("Illegal call to vTraceStoreISREnd, recorder busy!");
- return;
- }
+ if (recorder_busy)
+ {
+ vTraceError("Illegal call to vTraceStoreISREnd, recorder busy!");
+ return;
+ }
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- {
- #if (SELECTED_PORT == PORT_ARM_CortexM)
- if (tailchain_irq_pending() > 0)
- {
- nISRactive--; /* If an IRQ strikes exactly here, the resulting
- ISR tailchaining is not detected. The trace instead shows a very
- short fragment of the earlier preempted task/ISR, and then the new
- ISR begins. */
- return;
- }
- #endif
+ trcCRITICAL_SECTION_BEGIN();
+ if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
+ {
+ dts5 = (uint16_t)prvTraceGetDTS(0xFFFF);
- trcCRITICAL_SECTION_BEGIN();
- dts5 = (uint16_t)prvTraceGetDTS(0xFFFF);
+ if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
+ {
+ uint8_t hnd8, type;
- if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
- {
- ts = (TSEvent*)xTraceNextFreeEventBufferSlot();
- if (ts != NULL)
- {
- if (nISRactive > 1)
- {
- /* return to another isr */
- ts->type = TS_ISR_RESUME;
- ts->objHandle = isrstack[nISRactive];
- }
- else
- {
- /* return to task */
- ts->type = TS_TASK_RESUME;
- ts->objHandle = handle_of_last_logged_task;
- }
- ts->dts = dts5;
- nISRactive--;
- prvTraceUpdateCounters();
- }
- }
- trcCRITICAL_SECTION_END();
- }
+ if (nISRactive > 1)
+ {
+ /* return to another isr */
+ type = TS_ISR_RESUME;
+ hnd8 = prvTraceGet8BitHandle(isrstack[nISRactive]);
+ }
+ else
+ {
+ /* return to task */
+ type = TS_TASK_RESUME;
+ hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task);
+ }
+
+ ts = (TSEvent*)xTraceNextFreeEventBufferSlot();
+
+ if (ts != NULL)
+ {
+ ts->type = type;
+ ts->objHandle = hnd8;
+ ts->dts = dts5;
+ nISRactive--;
+ prvTraceUpdateCounters();
+ }
+
+ }
+
+ #if (SELECTED_PORT == PORT_ARM_CortexM)
+ /* Remember the last ISR exit event, as the event needs to be modified in case of a following ISR entry (if tail-chained ISRs) */
+ ptrLastISRExitEvent = (uint8_t*)ts;
+ DWTCycleCountAtLastISRExit = DWT_CYCLE_COUNTER;
+ #endif
+ }
+ trcCRITICAL_SECTION_END();
}
#else
@@ -605,7 +709,7 @@ static uint8_t writeDouble(void * buffer, uint8_t i, double value)
{
TRACE_ASSERT(buffer != NULL, "writeDouble: buffer == NULL", 0);
- uint32_t * dest = buffer;
+ uint32_t * dest;
uint32_t * src = (void*)&value;
/* The double is written as two 32 bit values, and should begin at an even
4-byte address (to avoid having to align with 8 byte) */
@@ -624,9 +728,11 @@ static uint8_t writeDouble(void * buffer, uint8_t i, double value)
{
return 255;
}
+
+ dest = &(((uint32_t *)buffer)[i]);
- dest[i/4+0] = src[0];
- dest[i/4+1] = src[1];
+ dest[0] = src[0];
+ dest[1] = src[1];
return i + 8;
}
@@ -1049,6 +1155,7 @@ void vTracePrintF_Helper(traceLabel eventLabel, const char* formatStr, va_list v
uint32_t noOfSlots;
UserEvent* ue1;
uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];
+ TRACE_SR_ALLOC_CRITICAL_SECTION();
/**************************************************************************
* The array tempDataBuffer is a local buffer used in a two-phase commit of
@@ -1063,108 +1170,102 @@ void vTracePrintF_Helper(traceLabel eventLabel, const char* formatStr, va_list v
TRACE_ASSERT(formatStr != NULL, "vTracePrintF: formatStr == NULL", );
+ trcCRITICAL_SECTION_BEGIN();
+
if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)
{
/* First, write the "primary" user event entry in the local buffer, but
let the event type be "EVENT_BEING_WRITTEN" for now...*/
ue1 = (UserEvent*)(&tempDataBuffer[0]);
+
ue1->type = EVENT_BEING_WRITTEN; /* Update this as the last step */
noOfSlots = prvTraceUserEventFormat(formatStr, vl, (uint8_t*)tempDataBuffer, 4);
/* Store the format string, with a reference to the channel symbol */
- ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel);
-
- trcCRITICAL_SECTION_BEGIN();
+ ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel);
ue1->dts = (uint8_t)prvTraceGetDTS(0xFF);
- if (! RecorderDataPtr->recorderActive)
+
+ /* prvTraceGetDTS might stop the recorder in some cases... */
+ if (RecorderDataPtr->recorderActive)
{
- /* Abort, since an XTS event (created by prvTraceGetDTS) filled the
- buffer, and the recorder stopped since not circular buffer. */
- trcCRITICAL_SECTION_END();
-
- return;
- }
-
- /* If the data does not fit in the remaining main buffer, wrap around to
- 0 if allowed, otherwise stop the recorder and quit). */
- if (RecorderDataPtr->nextFreeIndex + noOfSlots > RecorderDataPtr->maxEvents)
- {
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)
- (void)memset(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],
- 0,
- (RecorderDataPtr->maxEvents - RecorderDataPtr->nextFreeIndex)*4);
- RecorderDataPtr->nextFreeIndex = 0;
- RecorderDataPtr->bufferIsFull = 1;
-#else
- /* Abort and stop recorder, since the event data will not fit in the
- buffer and not circular buffer in this case... */
- trcCRITICAL_SECTION_END();
- vTraceStop();
-
-
- return;
-#endif
- }
-
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)
- /* Check that the buffer to be overwritten does not contain any user
- events that would be partially overwritten. If so, they must be "killed"
- by replacing the user event and following data with NULL events (i.e.,
- using a memset to zero).*/
- prvCheckDataToBeOverwrittenForMultiEntryEvents((uint8_t)noOfSlots);
-#endif
- /* Copy the local buffer to the main buffer */
- (void)memcpy(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],
- tempDataBuffer,
- noOfSlots * 4);
-
- /* Update the event type, i.e., number of data entries following the
- main USER_EVENT entry (Note: important that this is after the memcpy,
- but within the critical section!)*/
- RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4] =
- (uint8_t) ( USER_EVENT + noOfSlots - 1 );
-
- /* Update the main buffer event index (already checked that it fits in
- the buffer, so no need to check for wrapping)*/
-
- RecorderDataPtr->nextFreeIndex += noOfSlots;
- RecorderDataPtr->numEvents += noOfSlots;
-
-
-
- if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE)
- {
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)
- /* We have reached the end, but this is a ring buffer. Start from the beginning again. */
- RecorderDataPtr->bufferIsFull = 1;
- RecorderDataPtr->nextFreeIndex = 0;
-#else
- /* We have reached the end so we stop. */
- vTraceStop();
-#endif
- }
-
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)
- /* Make sure the next entry is cleared correctly */
- prvCheckDataToBeOverwrittenForMultiEntryEvents(1);
-#endif
-
-#ifdef STOP_AFTER_N_EVENTS
-#if (STOP_AFTER_N_EVENTS > -1)
- /* Check if we have reached the desired number of events */
- if (RecorderDataPtr->numEvents >= STOP_AFTER_N_EVENTS)
- {
- vTraceStop();
+ /* If the data does not fit in the remaining main buffer, wrap around to
+ 0 if allowed, otherwise stop the recorder and quit). */
+ if (RecorderDataPtr->nextFreeIndex + noOfSlots > RecorderDataPtr->maxEvents)
+ {
+ #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)
+ (void)memset(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],
+ 0,
+ (RecorderDataPtr->maxEvents - RecorderDataPtr->nextFreeIndex)*4);
+ RecorderDataPtr->nextFreeIndex = 0;
+ RecorderDataPtr->bufferIsFull = 1;
+ #else
+
+ /* Stop recorder, since the event data will not fit in the
+ buffer and not circular buffer in this case... */
+ vTraceStop();
+ #endif
+ }
+
+ /* Check if recorder has been stopped (i.e., vTraceStop above) */
+ if (RecorderDataPtr->recorderActive)
+ {
+ /* Check that the buffer to be overwritten does not contain any user
+ events that would be partially overwritten. If so, they must be "killed"
+ by replacing the user event and following data with NULL events (i.e.,
+ using a memset to zero).*/
+ #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)
+ prvCheckDataToBeOverwrittenForMultiEntryEvents((uint8_t)noOfSlots);
+ #endif
+ /* Copy the local buffer to the main buffer */
+ (void)memcpy(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],
+ tempDataBuffer,
+ noOfSlots * 4);
+
+ /* Update the event type, i.e., number of data entries following the
+ main USER_EVENT entry (Note: important that this is after the memcpy,
+ but within the critical section!)*/
+ RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4] =
+ (uint8_t) ( USER_EVENT + noOfSlots - 1 );
+
+ /* Update the main buffer event index (already checked that it fits in
+ the buffer, so no need to check for wrapping)*/
+
+ RecorderDataPtr->nextFreeIndex += noOfSlots;
+ RecorderDataPtr->numEvents += noOfSlots;
+
+ if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE)
+ {
+ #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)
+ /* We have reached the end, but this is a ring buffer. Start from the beginning again. */
+ RecorderDataPtr->bufferIsFull = 1;
+ RecorderDataPtr->nextFreeIndex = 0;
+ #else
+ /* We have reached the end so we stop. */
+ vTraceStop();
+ #endif
+ }
+
+ #if (STOP_AFTER_N_EVENTS > -1)
+ /* Check if we have reached the desired number of events */
+ if (RecorderDataPtr->numEvents >= STOP_AFTER_N_EVENTS)
+ {
+ vTraceStop();
+ }
+ #endif
+ }
+
+ #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)
+ /* Make sure the next entry is cleared correctly */
+ prvCheckDataToBeOverwrittenForMultiEntryEvents(1);
+ #endif
+
}
-#endif
-#endif
-
- trcCRITICAL_SECTION_END();
- }
+ }
+ trcCRITICAL_SECTION_END();
#elif (USE_SEPARATE_USER_EVENT_BUFFER == 1)
/* Use the separate user event buffer */
@@ -1195,13 +1296,13 @@ void vTraceUserEvent(traceLabel eventLabel)
#if (USE_SEPARATE_USER_EVENT_BUFFER == 0)
UserEvent* ue;
uint8_t dts1;
+ TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(eventLabel > 0, "vTraceUserEvent: Invalid value for eventLabel", );
+ trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)
- {
- trcCRITICAL_SECTION_BEGIN();
-
+ {
dts1 = (uint8_t)prvTraceGetDTS(0xFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
@@ -1214,14 +1315,14 @@ void vTraceUserEvent(traceLabel eventLabel)
ue->payload = eventLabel;
prvTraceUpdateCounters();
}
- }
- trcCRITICAL_SECTION_END();
+ }
}
+ trcCRITICAL_SECTION_END();
+
#elif (USE_SEPARATE_USER_EVENT_BUFFER == 1)
UserEventChannel channel;
uint32_t noOfSlots = 1;
- uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];
-
+ uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];
if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)
{
channel = xTraceRegisterChannelFormat(0, eventLabel);
@@ -1235,7 +1336,7 @@ void vTraceUserEvent(traceLabel eventLabel)
}
prvTraceUserEventHelper2(channel, tempDataBuffer, noOfSlots);
- }
+ }
#endif
}