]> git.sur5r.net Git - freertos/commitdiff
Update trace recorder to include heap tracing and new v8 features.
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 17 Feb 2014 12:45:56 +0000 (12:45 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 17 Feb 2014 12:45:56 +0000 (12:45 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2207 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

16 files changed:
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcConfig.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcHardwarePort.h [deleted file]
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcBase.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernel.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelHooks.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTypes.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcUser.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/debugger trace upload.txt
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/readme.txt
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcBase.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernel.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcUser.c

index f7d3ff044ce8c4abf2525500024f078251796a47..e2d22e053a764e807e148c98cd6510ae930b77dd 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcConfig.h\r
  * stores User Events labels and names of deleted tasks, queues, or other kernel\r
  * objects. Note that the names of active objects not stored here but in the \r
  * Object Table. Thus, if you don't use User Events or delete any kernel \r
- * objects you set this to zero (0) to minimize RAM usage.\r
+ * objects you set this to a very low value, e.g. 4, but not zero (0) since \r
+ * this causes a declaration of a zero-sized array, for which the C compiler\r
+ * behavior is not standardized and may cause misaligned data.\r
  ******************************************************************************/\r
-#define SYMBOL_TABLE_SIZE 1000\r
+#define SYMBOL_TABLE_SIZE 800\r
+\r
+#if (SYMBOL_TABLE_SIZE == 0)\r
+#error "SYMBOL_TABLE_SIZE may not be zero!"\r
+#endif\r
 \r
 /*******************************************************************************\r
  * USE_SEPARATE_USER_EVENT_BUFFER\r
  *\r
  * Only in use if USE_SEPARATE_USER_EVENT_BUFFER is set to 1.\r
  ******************************************************************************/\r
-#define USER_EVENT_BUFFER_SIZE 500\r
+#define USER_EVENT_BUFFER_SIZE 10\r
 \r
 /*******************************************************************************\r
  * USER_EVENT_CHANNELS\r
 #define NQueue            10\r
 #define NSemaphore        10\r
 #define NMutex            10\r
+#define NTimer            2\r
+#define NEventGroup       2\r
 \r
 /* Maximum object name length for each class (includes zero termination) */\r
 #define NameLenTask       15\r
 #define NameLenQueue      15\r
 #define NameLenSemaphore  15\r
 #define NameLenMutex      15\r
+#define NameLenTimer      15\r
+#define NameLenEventGroup 15\r
 \r
 /******************************************************************************\r
  * TRACE_DESCRIPTION\r
  * If this is one (1), the TRACE_ASSERT macro will verify that a condition is \r
  * true. If the condition is false, vTraceError() will be called.\r
  *****************************************************************************/\r
-#define USE_TRACE_ASSERT 0\r
+#define USE_TRACE_ASSERT 1\r
 \r
 /******************************************************************************\r
  * INCLUDE_FLOAT_SUPPORT\r
  * much faster than a printf and can therefore be used in timing critical code.\r
  * See vTraceUserEvent() and vTracePrintF() in trcUser.h\r
  * \r
- * Note that Tracealyzer Professional Edition is required for User Events, \r
- * they are not displayed in Tracealyzer Free Edition.\r
+ * Note that User Events are not displayed in FreeRTOS+Trace Free Edition.\r
  *****************************************************************************/\r
 #define INCLUDE_USER_EVENTS 1\r
 \r
  *****************************************************************************/\r
 #define INCLUDE_OBJECT_DELETE 1\r
 \r
+/******************************************************************************\r
+ * INCLUDE_MEMMANG_EVENTS\r
+ * \r
+ * Macro which should be defined as either zero (0) or one (1). \r
+ * Default is 1.\r
+ *\r
+ * This controls if malloc and free calls should be traced. Set this to zero to\r
+ * exclude malloc/free calls from the tracing.\r
+ *****************************************************************************/\r
+#define INCLUDE_MEMMANG_EVENTS 1\r
+\r
 /******************************************************************************\r
  * CONFIGURATION RELATED TO BEHAVIOR\r
  *****************************************************************************/\r
  *****************************************************************************/\r
 #define USE_IMPLICIT_IFE_RULES 1\r
 \r
+\r
 /******************************************************************************\r
- * INCLUDE_SAVE_TO_FILE\r
+ * USE_16BIT_OBJECT_HANDLES\r
  *\r
  * Macro which should be defined as either zero (0) or one (1).\r
  * Default is 0.\r
  *\r
- * If enabled (1), the recorder will include code for saving the trace\r
- * to a local file system.\r
- ******************************************************************************/\r
-#ifdef WIN32\r
-    #define INCLUDE_SAVE_TO_FILE 1\r
-#else\r
-    #define INCLUDE_SAVE_TO_FILE 0\r
+ * If set to 0 (zero), the recorder uses 8-bit handles to identify kernel \r
+ * objects such as tasks and queues. This limits the supported number of\r
+ * concurrently active objects to 255 of each type (object class).\r
+ *\r
+ * If set to 1 (one), the recorder uses 16-bit handles to identify kernel \r
+ * objects such as tasks and queues. This limits the supported number of\r
+ * concurrent objects to 65535 of each type (object class). However, since the\r
+ * object property table is limited to 64 KB, the practical limit is about\r
+ * 3000 objects in total. \r
+ * \r
+ * NOTE: An object with a high ID (> 255) will generate an extra event \r
+ * (= 4 byte) in the event buffer. \r
+ * \r
+ * NOTE: Some internal tables in the recorder gets larger when using 16-bit \r
+ * handles. The additional RAM usage is 5-10 byte plus 1 byte per kernel object\r
+ *, i.e., task, queue, semaphore, mutex, etc.\r
+ *****************************************************************************/\r
+#define USE_16BIT_OBJECT_HANDLES 0\r
+\r
+/****** Port Name ******************** Code ** Official ** OS Platform ******\r
+* PORT_APPLICATION_DEFINED               -2     -           -                 \r
+* PORT_NOT_SET                           -1     -           -                 \r
+* PORT_HWIndependent                     0      Yes         Any               \r
+* PORT_Win32                             1      Yes         FreeRTOS Win32\r
+* PORT_Atmel_AT91SAM7                    2      No          Any               \r
+* PORT_Atmel_UC3A0                       3      No          Any               \r
+* PORT_ARM_CortexM                       4      Yes         Any               \r
+* PORT_Renesas_RX600                     5      Yes         Any               \r
+* PORT_Microchip_dsPIC_AND_PIC24         6      Yes         Any               \r
+* PORT_TEXAS_INSTRUMENTS_TMS570          7      No          Any               \r
+* PORT_TEXAS_INSTRUMENTS_MSP430          8      No          Any               \r
+* PORT_MICROCHIP_PIC32                   9      No          Any               \r
+* PORT_XILINX_PPC405                     10     No          FreeRTOS          \r
+* PORT_XILINX_PPC440                     11     No          FreeRTOS          \r
+* PORT_XILINX_MICROBLAZE                 12     No          Any               \r
+* PORT_NXP_LPC210X                       13     No          Any               \r
+*****************************************************************************/\r
+#define SELECTED_PORT PORT_ARM_CortexM\r
+\r
+#if (SELECTED_PORT == PORT_NOT_SET)\r
+#error "You need to define SELECTED_PORT here!"\r
 #endif\r
 \r
 /******************************************************************************\r
- * TEAM_LICENSE_CODE\r
- *\r
- * Macro which defines a string - the team license code.\r
- * If no team license is available, this should be an empty string "".\r
- * This should be maximum 32 chars, including zero-termination.\r
- *****************************************************************************/\r
-#define TEAM_LICENSE_CODE ""\r
+* USE_PRIMASK_CS (for Cortex M devices only)\r
+*\r
+* An integer constant that selects between two options for the critical\r
+* sections of the recorder library.\r
+ *\r
+*   0: The default FreeRTOS critical section (BASEPRI) - default setting\r
+*   1: Always disable ALL interrupts (using PRIMASK)\r
+ *\r
+* Option 0 uses the standard FreeRTOS macros for critical sections.\r
+* However, on Cortex-M devices they only disable interrupts with priorities \r
+* below a certain configurable level, while higher priority ISRs remain active.\r
+* Such high-priority ISRs may not use the recorder functions in this mode.\r
+*\r
+* Option 1 allows you to safely call the recorder from any ISR, independent of \r
+* the interrupt priority. This mode may however cause higher IRQ latencies\r
+* (some microseconds) since ALL configurable interrupts are disabled during \r
+* the recorder's critical sections in this mode, using the PRIMASK register.\r
+ ******************************************************************************/\r
+#define USE_PRIMASK_CS 0\r
+\r
+/******************************************************************************\r
+* HEAP_SIZE_BELOW_16M\r
+*\r
+* An integer constant that can be used to reduce the buffer usage of memory\r
+* allocation events (malloc/free). This value should be 1 if the heap size is \r
+* below 16 MB (2^24 byte), and you can live with addresses truncated to the \r
+* lower 24 bit. Otherwise set it to 0 to get the full 32-bit addresses.\r
+******************************************************************************/\r
+#define HEAP_SIZE_BELOW_16M 0\r
 \r
 #endif\r
 \r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcHardwarePort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/ConfigurationTemplate/trcHardwarePort.h
deleted file mode 100644 (file)
index 993882b..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-/******************************************************************************* \r
- * Tracealyzer v2.5.0 Recorder Library\r
- * Percepio AB, www.percepio.com\r
- *\r
- * trcHardwarePort.h\r
- *\r
- * Contains together with trcHardwarePort.c all hardware portability issues of \r
- * the trace recorder library.\r
- *\r
- * Terms of Use\r
- * This software is copyright Percepio AB. The recorder library is free for\r
- * use together with Percepio products. You may distribute the recorder library\r
- * in its original form, including modifications in trcPort.c and trcPort.h\r
- * given that these modification are clearly marked as your own modifications\r
- * and documented in the initial comment section of these source files. \r
- * This software is the intellectual property of Percepio AB and may not be \r
- * sold or in other ways commercially redistributed without explicit written \r
- * permission by Percepio AB.\r
- *\r
- * Disclaimer \r
- * The trace tool and recorder library is being delivered to you AS IS and \r
- * Percepio AB makes no warranty as to its use or performance. Percepio AB does \r
- * not and cannot warrant the performance or results you may obtain by using the \r
- * software or documentation. Percepio AB make no warranties, express or \r
- * implied, as to noninfringement of third party rights, merchantability, or \r
- * fitness for any particular purpose. In no event will Percepio AB, its \r
- * technology partners, or distributors be liable to you for any consequential, \r
- * incidental or special damages, including any lost profits or lost savings, \r
- * even if a representative of Percepio AB has been advised of the possibility \r
- * of such damages, or for any claim by any third party. Some jurisdictions do \r
- * not allow the exclusion or limitation of incidental, consequential or special \r
- * damages, or the exclusion of implied warranties or limitations on how long an \r
- * implied warranty may last, so the above limitations may not apply to you.\r
- *\r
- * Copyright Percepio AB, 2013.\r
- * www.percepio.com\r
- ******************************************************************************/\r
-\r
-#ifndef TRCPORT_H\r
-#define TRCPORT_H\r
-\r
-#include "trcKernelPort.h"\r
-\r
-/* If Win32 port */\r
-#ifdef WIN32\r
-\r
-   #undef _WIN32_WINNT\r
-   #define _WIN32_WINNT 0x0600\r
-\r
-   /* Standard includes. */\r
-   #include <stdio.h>\r
-   #include <windows.h>\r
-   #include <direct.h>\r
-\r
-/*******************************************************************************\r
- * The Win32 port by default saves the trace to file and then kills the\r
- * program when the recorder is stopped, to facilitate quick, simple tests\r
- * of the recorder.\r
- ******************************************************************************/\r
-   #define WIN32_PORT_SAVE_WHEN_STOPPED 1\r
-   #define WIN32_PORT_EXIT_WHEN_STOPPED 1\r
-\r
-#endif\r
-\r
-#define DIRECTION_INCREMENTING 1\r
-#define DIRECTION_DECREMENTING 2\r
-\r
-/******************************************************************************\r
- * Supported ports\r
- * \r
- * PORT_HWIndependent\r
- * A hardware independent fallback option for event timestamping. Provides low \r
- * resolution timestamps based on the OS tick.\r
- * This may be used on the Win32 port, but may also be used on embedded hardware \r
- * platforms. All time durations will be truncated to the OS tick frequency, \r
- * typically 1 KHz. This means that a task or ISR that executes in less than \r
- * 1 ms get an execution time of zero.\r
- *\r
- * PORT_Win32\r
- * "Accurate" timestamping based on the Windows performance counter for Win32 builds.\r
- * Note that this gives the host machine time, not the kernel time.\r
- *\r
- * Officially supported hardware timer ports:\r
- * - PORT_Atmel_AT91SAM7\r
- * - PORT_Atmel_UC3A0\r
- * - PORT_ARM_CortexM \r
- * - PORT_Renesas_RX600\r
- * - PORT_Microchip_dsPIC_AND_PIC24\r
- *\r
- * We also provide several "unofficial" hardware-specific ports. There have \r
- * been developed by external contributors, and have not yet been verified \r
- * by Percepio AB. Let us know if you have problems getting these to work.\r
- * \r
- * Unofficial hardware specific ports provided are:\r
- * - PORT_TEXAS_INSTRUMENTS_TMS570\r
- * - PORT_TEXAS_INSTRUMENTS_MSP430\r
- * - PORT_MICROCHIP_PIC32\r
- * - PORT_XILINX_PPC405\r
- * - PORT_XILINX_PPC440\r
- * - PORT_XILINX_MICROBLAZE\r
- * - PORT_NXP_LPC210X\r
- *\r
- *****************************************************************************/\r
-\r
-#define PORT_NOT_SET                          -1\r
-#define PORT_APPLICATION_DEFINED                         -2\r
-\r
-/*** Officially supported hardware timer ports *******************************/\r
-#define PORT_HWIndependent                     0\r
-#define PORT_Win32                             1\r
-#define PORT_Atmel_AT91SAM7                    2\r
-#define PORT_Atmel_UC3A0                       3\r
-#define PORT_ARM_CortexM                       4\r
-#define PORT_Renesas_RX600                     5\r
-#define PORT_Microchip_dsPIC_AND_PIC24         6\r
-\r
-/*** Unofficial ports, provided by external developers, not yet verified *****/\r
-#define PORT_TEXAS_INSTRUMENTS_TMS570          7\r
-#define PORT_TEXAS_INSTRUMENTS_MSP430          8\r
-#define PORT_MICROCHIP_PIC32                   9\r
-#define PORT_XILINX_PPC405                    10\r
-#define PORT_XILINX_PPC440                    11\r
-#define PORT_XILINX_MICROBLAZE                12\r
-#define PORT_NXP_LPC210X                      13\r
-\r
-/*** Select your port here! **************************************************/\r
-#define SELECTED_PORT PORT_NOT_SET\r
-/*****************************************************************************/\r
-\r
-#if (SELECTED_PORT == PORT_NOT_SET) \r
-#error "You need to define SELECTED_PORT here!"\r
-#endif\r
-\r
-/*******************************************************************************\r
- * IRQ_PRIORITY_ORDER\r
- *\r
- * Macro which should be defined as an integer of 0 or 1.\r
- *\r
- * This should be 0 if lower IRQ priority values implies higher priority \r
- * levels, such as on ARM Cortex M. If the opposite scheme is used, i.e., \r
- * if higher IRQ priority values means higher priority, this should be 1.\r
- *\r
- * This setting is not critical. It is used only to sort and colorize the \r
- * interrupts in priority order, in case you record interrupts using\r
- * the vTraceStoreISRBegin and vTraceStoreISREnd routines.\r
- *\r
- * We provide this setting for some hardware architectures below:\r
- * - ARM Cortex M:       0 (lower IRQ priority values are more significant)\r
- * - Atmel AT91SAM7x:    1 (higher IRQ priority values are more significant)\r
- * - Atmel AVR32:        1 (higher IRQ priority values are more significant)\r
- * - Renesas RX600:      1 (higher IRQ priority values are more significant)\r
- * - Microchip PIC24:    0 (lower IRQ priority values are more significant)\r
- * - Microchip dsPIC:    0 (lower IRQ priority values are more significant)\r
- * - TI TMS570:          0 (lower IRQ priority values are more significant)\r
- * - Freescale HCS08:    0 (lower IRQ priority values are more significant)\r
- * - Freescale HCS12:    0 (lower IRQ priority values are more significant)\r
- * - PowerPC 405:        0 (lower IRQ priority values are more significant)\r
- * - PowerPC 440:        0 (lower IRQ priority values are more significant)\r
- * - Freescale ColdFire: 1 (higher IRQ priority values are more significant)\r
- * - NXP LPC210x:        0 (lower IRQ priority values are more significant)\r
- * - MicroBlaze:        0  (lower IRQ priority values are more significant)\r
- *\r
- * If your chip is not on the above list, and you perhaps know this detail by \r
- * heart, please inform us by e-mail to support@percepio.com.\r
- *\r
- ******************************************************************************\r
- *\r
- * HWTC Macros \r
- *\r
- * These four HWTC macros provides a hardware isolation layer representing a \r
- * generic hardware timer/counter used for driving the operating system tick, \r
- * such as the SysTick feature of ARM Cortex M3/M4, or the PIT of the Atmel \r
- * AT91SAM7X.\r
- *\r
- * HWTC_COUNT: The current value of the counter. This is expected to be reset \r
- * a each tick interrupt. Thus, when the tick handler starts, the counter has \r
- * already wrapped.\r
- *\r
- * HWTC_COUNT_DIRECTION: Should be one of:\r
- * - DIRECTION_INCREMENTING - for hardware timer/counters of incrementing type\r
- *   such as the PIT on Atmel AT91SAM7X.\r
- *   When the counter value reach HWTC_PERIOD, it is reset to zero and the\r
- *   interrupt is signaled.\r
- * - DIRECTION_DECREMENTING - for hardware timer/counters of decrementing type\r
- *   such as the SysTick on ARM Cortex M3/M4 chips.\r
- *   When the counter value reach 0, it is reset to HWTC_PERIOD and the\r
- *   interrupt is signaled.\r
- *\r
- * HWTC_PERIOD: The number of increments or decrements of HWTC_COUNT between\r
- * two tick interrupts. This should preferably be mapped to the reload\r
- * register of the hardware timer, to make it more portable between chips in the \r
- * same family. The macro should in most cases be (reload register + 1).\r
- *\r
- * HWTC_DIVISOR: If the timer frequency is very high, like on the Cortex M chips\r
- * (where the SysTick runs at the core clock frequency), the "differential \r
- * timestamping" used in the recorder will more frequently insert extra XTS \r
- * events to store the timestamps, which increases the event buffer usage. \r
- * In such cases, to reduce the number of XTS events and thereby get longer \r
- * traces, you use HWTC_DIVISOR to scale down the timestamps and frequency.\r
- * Assuming a OS tick rate of 1 KHz, it is suggested to keep the effective timer\r
- * frequency below 65 MHz to avoid an excessive amount of XTS events. Thus, a\r
- * Cortex M chip running at 72 MHZ should use a HWTC_DIVISOR of 2, while a \r
- * faster chip require a higher HWTC_DIVISOR value. \r
- *\r
- * The HWTC macros and vTracePortGetTimeStamp is the main porting issue\r
- * or the trace recorder library. Typically you should not need to change\r
- * the code of vTracePortGetTimeStamp if using the HWTC macros.\r
- *\r
- ******************************************************************************/\r
-\r
-#if (SELECTED_PORT == PORT_Win32)\r
-    \r
-    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
-    #define HWTC_COUNT (ulGetRunTimeCounterValue())\r
-    #define HWTC_PERIOD 0\r
-    #define HWTC_DIVISOR 1\r
-    \r
-    #define IRQ_PRIORITY_ORDER 1  // Please update according to your hardware...\r
-\r
-#elif (SELECTED_PORT == PORT_HWIndependent)\r
-    \r
-    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
-    #define HWTC_COUNT 0\r
-    #define HWTC_PERIOD 1\r
-    #define HWTC_DIVISOR 1\r
-\r
-    #define IRQ_PRIORITY_ORDER 1  // Please update according to your hardware...\r
-\r
-#elif (SELECTED_PORT == PORT_Atmel_AT91SAM7)\r
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!\r
-\r
-    /* HWTC_PERIOD is hardcoded for AT91SAM7X256-EK Board (48 MHz)\r
-    A more generic solution is to get the period from pxPIT->PITC_PIMR */\r
-    \r
-    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
-    #define HWTC_COUNT (AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF)\r
-    #define HWTC_PERIOD (AT91C_BASE_PITC->PITC_PIMR + 1)\r
-    #define HWTC_DIVISOR 1\r
-\r
-    #define IRQ_PRIORITY_ORDER 1  // higher IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_Atmel_UC3A0)\r
-#error HWTC_PERIOD must point to the reload register! Not yet updated for this hardware port!\r
-  \r
-    /* For Atmel AVR32 (AT32UC3A) */\r
-    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
-    #define HWTC_COUNT sysreg_read(AVR32_COUNT)\r
-    #define HWTC_PERIOD \r
-    #define HWTC_DIVISOR 1    \r
-\r
-    #define IRQ_PRIORITY_ORDER 1  // higher IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_ARM_CortexM)\r
-\r
-    /* For all chips using ARM Cortex M cores */\r
-\r
-    #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING\r
-    #define HWTC_COUNT (*((uint32_t*)0xE000E018))\r
-    #define HWTC_PERIOD ((*(uint32_t*)0xE000E014) + 1)\r
-    #define HWTC_DIVISOR 2\r
-    \r
-    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_Renesas_RX600)    \r
-\r
-    #include "iodefine.h"\r
-\r
-    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
-    #define HWTC_COUNT (CMT0.CMCNT)\r
-    #define HWTC_PERIOD (CMT0.CMCOR + 1)\r
-    #define HWTC_DIVISOR 1\r
-\r
-    #define IRQ_PRIORITY_ORDER 1  // higher IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_Microchip_dsPIC_AND_PIC24)\r
-\r
-    /* For Microchip PIC24 and dsPIC (16 bit) */\r
-\r
-    /* Note: The trace library was originally designed for 32-bit MCUs, and is slower\r
-       than intended on 16-bit MCUs. Storing an event on a PIC24 takes about 70 Âµs. \r
-       In comparison, 32-bit MCUs are often 10-20 times faster. If recording overhead \r
-       becomes a problem on PIC24, use the filters to exclude less interesting tasks \r
-       or system calls. */\r
-\r
-    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
-    #define HWTC_COUNT (TMR1)\r
-    #define HWTC_PERIOD (PR1+1)\r
-    #define HWTC_DIVISOR 1\r
-\r
-    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_NXP_LPC210X)\r
-#error HWTC_PERIOD must point to the reload register! Not yet updated for this hardware port!\r
-    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
-    \r
-    /* Tested with LPC2106, but should work with most LPC21XX chips. */\r
-      \r
-    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
-    #define HWTC_COUNT  *((uint32_t *)0xE0004008 )\r
-    #define HWTC_PERIOD \r
-    #define HWTC_DIVISOR 1    \r
-\r
-    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_TMS570)\r
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!\r
-    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
-\r
-    #define RTIFRC0 *((uint32_t *)0xFFFFFC10)\r
-    #define RTICOMP0 *((uint32_t *)0xFFFFFC50)\r
-    #define RTIUDCP0 *((uint32_t *)0xFFFFFC54)\r
-    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
-    #define HWTC_COUNT (RTIFRC0 - (RTICOMP0 - RTIUDCP0))\r
-    #define HWTC_PERIOD (RTIUDCP0)\r
-    #define HWTC_DIVISOR 1\r
-\r
-    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_MSP430)\r
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!\r
-    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
-\r
-    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
-    #define HWTC_COUNT (TA0R)\r
-    #define HWTC_PERIOD TRACE_CPU_CLOCKS_PER_TICK      \r
-    #define HWTC_DIVISOR 1\r
-\r
-    #define IRQ_PRIORITY_ORDER 1  // higher IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_MICROCHIP_PIC32)\r
-    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
-\r
-    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
-    #define HWTC_COUNT (ReadTimer1())     /* Should be available in BSP */\r
-    #define HWTC_PERIOD (ReadPeriod1()+1) /* Should be available in BSP */\r
-    #define HWTC_DIVISOR 1\r
-\r
-    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_XILINX_PPC405)\r
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!\r
-    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
-\r
-    #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING\r
-    #define HWTC_COUNT  mfspr( 0x3db)\r
-    #define HWTC_PERIOD \r
-    #define HWTC_DIVISOR 1\r
-\r
-    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_XILINX_PPC440)\r
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!\r
-    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
-\r
-    /* This should work with most PowerPC chips */\r
-    \r
-    #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING\r
-    #define HWTC_COUNT  mfspr( 0x016 )\r
-    #define HWTC_PERIOD \r
-    #define HWTC_DIVISOR 1    \r
-\r
-    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
-    \r
-#elif (SELECTED_PORT == PORT_XILINX_MICROBLAZE)\r
-#error HWTC_PERIOD must point to the reload register! Not verified for this hardware port!\r
-    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
-\r
-    /* This should work with most Microblaze configurations.\r
-     * It uses the AXI Timer 0 - the tick interrupt source.\r
-     * If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required.\r
-     */\r
-    #include "xtmrctr_l.h"\r
-\r
-    #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING\r
-    #define HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 )\r
-    #define HWTC_PERIOD \r
-    #define HWTC_DIVISOR 16\r
-\r
-    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
-\r
-#elif (SELECTED_PORT == PORT_APPLICATION_DEFINED)\r
-\r
-       #if !( defined (HWTC_COUNT_DIRECTION) && defined (HWTC_COUNT) && defined (HWTC_PERIOD) && defined (HWTC_DIVISOR) && defined (IRQ_PRIORITY_ORDER) )\r
-               #error SELECTED_PORT is PORT_APPLICATION_DEFINED but not all of the necessary constants have been defined.\r
-       #endif\r
-\r
-\r
-#elif (SELECTED_PORT != PORT_NOT_SET)\r
-\r
-    #error "SELECTED_PORT had unsupported value!"\r
-    #define SELECTED_PORT PORT_NOT_SET\r
-\r
-#endif\r
-\r
-#if (SELECTED_PORT != PORT_NOT_SET)\r
-    \r
-    #ifndef HWTC_COUNT_DIRECTION\r
-    #error "HWTC_COUNT_DIRECTION is not set!"\r
-    #endif \r
-    \r
-    #ifndef HWTC_COUNT\r
-    #error "HWTC_COUNT is not set!"    \r
-    #endif \r
-    \r
-    #ifndef HWTC_PERIOD\r
-    #error "HWTC_PERIOD is not set!"\r
-    #endif \r
-    \r
-    #ifndef HWTC_DIVISOR\r
-    #error "HWTC_DIVISOR is not set!"    \r
-    #endif \r
-    \r
-    #ifndef IRQ_PRIORITY_ORDER\r
-    #error "IRQ_PRIORITY_ORDER is not set!"\r
-    #elif (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1)\r
-    #error "IRQ_PRIORITY_ORDER has bad value!"\r
-    #endif \r
-    \r
-    #if (HWTC_DIVISOR < 1)\r
-    #error "HWTC_DIVISOR must be a non-zero positive value!"\r
-    #endif \r
-\r
-#endif\r
-/*******************************************************************************\r
- * vTraceConsoleMessage\r
- *\r
- * A wrapper for your system-specific console "printf" console output function.\r
- * This needs to be correctly defined to see status reports from the trace \r
- * status monitor task (this is defined in trcUser.c).\r
- ******************************************************************************/         \r
-#if (SELECTED_PORT == PORT_Atmel_AT91SAM7)\r
-/* Port specific includes */\r
-#include "console.h"\r
-#endif\r
-\r
-#define vTraceConsoleMessage(x)\r
-\r
-/*******************************************************************************\r
- * vTracePortGetTimeStamp\r
- *\r
- * Returns the current time based on the HWTC macros which provide a hardware\r
- * isolation layer towards the hardware timer/counter.\r
- *\r
- * The HWTC macros and vTracePortGetTimeStamp is the main porting issue\r
- * or the trace recorder library. Typically you should not need to change\r
- * the code of vTracePortGetTimeStamp if using the HWTC macros.\r
- *\r
- ******************************************************************************/\r
-void vTracePortGetTimeStamp(uint32_t *puiTimestamp);\r
-\r
-/*******************************************************************************\r
- * vTracePortEnd\r
- * \r
- * This function is called when the recorder is stopped due to full buffer.\r
- * Mainly intended to show a message in the console.\r
- * This is used by the Win32 port to store the trace to a file. The file path is\r
- * set using vTracePortSetFileName.\r
- ******************************************************************************/\r
-void vTracePortEnd(void);\r
-\r
-#endif\r
index e48dc88ecc28567273c79fc8ade3a0cee5a78c62..31dad34e78e5eb746d9ae955fa46ada3bd0b3d76 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcBase.h\r
@@ -38,7 +38,7 @@
 #ifndef TRCBASE_H\r
 #define TRCBASE_H\r
 \r
-#define TRACE_MINOR_VERSION 2\r
+#define TRACE_MINOR_VERSION 4\r
 #define TRACE_STORE_MODE_STOP_WHEN_FULL 1\r
 #define TRACE_STORE_MODE_RING_BUFFER 2\r
 #define TRACE_DATA_ALLOCATION_STATIC 1\r
 #define USE_SEPARATE_USER_EVENT_BUFFER 0\r
 #endif\r
 \r
+#ifndef TRACE_SR_ALLOC_CRITICAL_SECTION\r
+#define TRACE_SR_ALLOC_CRITICAL_SECTION()\r
+#endif\r
+\r
 /* Max number of event codes supported */\r
 #define NEventCodes 0x100\r
 \r
@@ -96,16 +100,16 @@ extern uint8_t excludedEventCodes[NEventCodes / 8 + 1];
 typedef struct\r
 {\r
     /* For each object class, the index of the next handle to allocate */\r
-    int16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ];\r
+    uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ];\r
 \r
     /* The lowest index of this class (constant) */\r
-    int16_t lowestIndexOfClass[ TRACE_NCLASSES ];\r
+    uint16_t lowestIndexOfClass[ TRACE_NCLASSES ];\r
 \r
     /* The highest index of this class (constant) */\r
-    int16_t highestIndexOfClass[ TRACE_NCLASSES ];\r
+    uint16_t highestIndexOfClass[ TRACE_NCLASSES ];\r
 \r
     /* The highest use count for this class (for statistics) */\r
-    int16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ];\r
+    uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ];\r
 \r
     /* The free object handles - a set of stacks within this array */\r
     objectHandleType objectHandles[ TRACE_KERNEL_OBJECT_COUNT ];\r
@@ -139,7 +143,11 @@ typedef struct
 \r
     /* This is used to calculate the index in the dynamic object table\r
     (handle - 1 - nofStaticObjects = index)*/\r
-    uint8_t NumberOfObjectsPerClass[ 4*((TRACE_NCLASSES+3)/4)];\r
+#if (USE_16BIT_OBJECT_HANDLES == 1)    \r
+    objectHandleType NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)];\r
+#else\r
+       objectHandleType NumberOfObjectsPerClass[4*((TRACE_NCLASSES+3)/4)];\r
+#endif\r
 \r
     /* Allocation size rounded up to the closest multiple of 4 */\r
     uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/4) ];\r
@@ -179,7 +187,7 @@ typedef struct
 typedef struct\r
 {\r
     uint8_t type;\r
-    objectHandleType objHandle;\r
+    uint8_t objHandle;\r
     uint16_t dts;    /* differential timestamp - time since last event */\r
 } TSEvent, TREvent;\r
 \r
@@ -200,7 +208,7 @@ typedef struct
 typedef struct\r
 {\r
     uint8_t type;\r
-    objectHandleType objHandle;\r
+    uint8_t objHandle;\r
     uint8_t param;\r
     uint8_t dts;    /* differential timestamp - time since last event */\r
 } KernelCallWithParamAndHandle;\r
@@ -215,7 +223,7 @@ typedef struct
 typedef struct\r
 {\r
     uint8_t type;\r
-    objectHandleType objHandle;    /* the handle of the closed object */\r
+    uint8_t objHandle;    /* the handle of the closed object */\r
     uint16_t symbolIndex;          /* the name of the closed object */\r
 } ObjCloseNameEvent;\r
 \r
@@ -254,6 +262,18 @@ typedef struct
        uint16_t xps_16;\r
 } XPSEvent;\r
 \r
+typedef struct{\r
+       uint8_t type;\r
+       uint8_t dts;\r
+       uint16_t size;\r
+} MemEventSize;\r
+\r
+typedef struct{\r
+       uint8_t type;\r
+       uint8_t addr_high;\r
+       uint16_t addr_low;\r
+} MemEventAddr;\r
+\r
 /*******************************************************************************\r
  * The separate user event buffer structure. Can be enabled in trcConfig.h.\r
  ******************************************************************************/\r
@@ -305,7 +325,7 @@ typedef struct
     /* Used to determine Kernel and Endianess */\r
     uint16_t version;\r
 \r
-    /* Currently 1 for v2.2.2 (0 earlier)*/\r
+    /* Currently 3, since v2.6.0 */\r
     uint8_t minor_version;\r
 \r
     /* This should be 0 if lower IRQ priority values implies higher priority\r
@@ -342,12 +362,18 @@ typedef struct
     This is a 32 bit variable due to alignment issues. */\r
     uint32_t recorderActive;\r
 \r
-    /* For storing a Team License key */\r
-    uint8_t teamLicenceKey[32];\r
+    /* Not used, remains for compatibility and future use */\r
+    uint8_t notused[28];\r
+\r
+       /* The amount of heap memory remaining at the last malloc or free event */ \r
+       uint32_t heapMemUsage;\r
 \r
     /* 0xF0F0F0F0 - for control only */\r
     int32_t debugMarker0;\r
 \r
+       /* Set to value of USE_16BIT_OBJECT_HANDLES */\r
+       uint32_t isUsing16bitHandles;\r
+\r
     /* The Object Property Table holds information about currently active\r
     tasks, queues, and other recorded objects. This is updated on each\r
     create call and includes object name and other properties. */\r
@@ -444,10 +470,16 @@ void vTraceSetObjectName(traceObjectClass objectclass,
 \r
 void* xTraceNextFreeEventBufferSlot(void);\r
 \r
+#if (USE_16BIT_OBJECT_HANDLES == 1)\r
+unsigned char prvTraceGet8BitHandle(objectHandleType handle);\r
+#else\r
+#define prvTraceGet8BitHandle(x) ((unsigned char)x)\r
+#endif\r
+\r
+\r
 uint16_t uiIndexOfObject(objectHandleType objecthandle,\r
                          uint8_t objectclass);\r
 \r
-\r
 /*******************************************************************************\r
  * vTraceError\r
  *\r
@@ -487,6 +519,9 @@ RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclas
 #define TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)\r
 #define TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_GET_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)\r
 \r
+#define TRACE_UPDATE_HEAP_USAGE_POSITIVE(change) {if (RecorderDataPtr != NULL) RecorderDataPtr->heapMemUsage += change;}\r
+#define TRACE_UPDATE_HEAP_USAGE_NEGATIVE(change) {if (RecorderDataPtr != NULL) RecorderDataPtr->heapMemUsage -= change;}\r
+\r
 /* DEBUG ASSERTS */\r
 #if defined USE_TRACE_ASSERT && USE_TRACE_ASSERT != 0\r
 #define TRACE_ASSERT(eval, msg, defRetVal) \\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h
new file mode 100644 (file)
index 0000000..c66654e
--- /dev/null
@@ -0,0 +1,433 @@
+/******************************************************************************* \r
+ * Tracealyzer v2.6.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
+ *\r
+ * trcHardwarePort.h\r
+ *\r
+ * Contains together with trcHardwarePort.c all hardware portability issues of \r
+ * the trace recorder library.\r
+ *\r
+ * Terms of Use\r
+ * This software is copyright Percepio AB. The recorder library is free for\r
+ * use together with Percepio products. You may distribute the recorder library\r
+ * in its original form, including modifications in trcPort.c and trcPort.h\r
+ * given that these modification are clearly marked as your own modifications\r
+ * and documented in the initial comment section of these source files. \r
+ * This software is the intellectual property of Percepio AB and may not be \r
+ * sold or in other ways commercially redistributed without explicit written \r
+ * permission by Percepio AB.\r
+ *\r
+ * Disclaimer \r
+ * The trace tool and recorder library is being delivered to you AS IS and \r
+ * Percepio AB makes no warranty as to its use or performance. Percepio AB does \r
+ * not and cannot warrant the performance or results you may obtain by using the \r
+ * software or documentation. Percepio AB make no warranties, express or \r
+ * implied, as to noninfringement of third party rights, merchantability, or \r
+ * fitness for any particular purpose. In no event will Percepio AB, its \r
+ * technology partners, or distributors be liable to you for any consequential, \r
+ * incidental or special damages, including any lost profits or lost savings, \r
+ * even if a representative of Percepio AB has been advised of the possibility \r
+ * of such damages, or for any claim by any third party. Some jurisdictions do \r
+ * not allow the exclusion or limitation of incidental, consequential or special \r
+ * damages, or the exclusion of implied warranties or limitations on how long an \r
+ * implied warranty may last, so the above limitations may not apply to you.\r
+ *\r
+ * Copyright Percepio AB, 2013.\r
+ * www.percepio.com\r
+ ******************************************************************************/\r
+\r
+#ifndef TRCPORT_H\r
+#define TRCPORT_H\r
+#include <stdint.h>\r
+\r
+/* If Win32 port */\r
+#ifdef WIN32\r
+\r
+   #undef _WIN32_WINNT\r
+   #define _WIN32_WINNT 0x0600\r
+\r
+   /* Standard includes. */\r
+   #include <stdio.h>\r
+   #include <windows.h>\r
+   #include <direct.h>\r
+\r
+/*******************************************************************************\r
+ * The Win32 port by default saves the trace to file and then kills the\r
+ * program when the recorder is stopped, to facilitate quick, simple tests\r
+ * of the recorder.\r
+ ******************************************************************************/\r
+   #define WIN32_PORT_SAVE_WHEN_STOPPED 1\r
+   #define WIN32_PORT_EXIT_WHEN_STOPPED 1\r
+\r
+#endif\r
+\r
+#define DIRECTION_INCREMENTING 1\r
+#define DIRECTION_DECREMENTING 2\r
+\r
+/******************************************************************************\r
+ * Supported ports\r
+ * \r
+ * PORT_HWIndependent\r
+ * A hardware independent fallback option for event timestamping. Provides low \r
+ * resolution timestamps based on the OS tick.\r
+ * This may be used on the Win32 port, but may also be used on embedded hardware \r
+ * platforms. All time durations will be truncated to the OS tick frequency, \r
+ * typically 1 KHz. This means that a task or ISR that executes in less than \r
+ * 1 ms get an execution time of zero.\r
+ *\r
+ * PORT_APPLICATION_DEFINED\r
+ * Allows for defining the port macros in other source code files.\r
+ *\r
+ * PORT_Win32\r
+ * "Accurate" timestamping based on the Windows performance counter for Win32 \r
+ * builds. Note that this gives the host machine time, not the kernel time.\r
+ *\r
+ * Hardware specific ports\r
+ * To get accurate timestamping, a hardware timer is necessary. Below are the \r
+ * available ports. Some of these are "unofficial", meaning that \r
+ * they have not yet been verified by Percepio but have been contributed by \r
+ * external developers. They should work, otherwise let us know by emailing \r
+ * support@percepio.com. Some work on any OS platform, while other are specific \r
+ * to a certain operating system.\r
+ *****************************************************************************/\r
+\r
+/****** Port Name ******************** Code ** Official ** OS Platform *******/\r
+#define PORT_APPLICATION_DEFINED       -2   /* -           -                 */\r
+#define PORT_NOT_SET                   -1   /* -           -                 */\r
+#define PORT_HWIndependent             0    /* Yes         Any               */\r
+#define PORT_Win32                     1    /* Yes         Windows (FreeRTOS)*/\r
+#define PORT_Atmel_AT91SAM7            2    /* No          Any               */\r
+#define PORT_Atmel_UC3A0               3    /* No          Any               */\r
+#define PORT_ARM_CortexM               4    /* Yes         Any               */\r
+#define PORT_Renesas_RX600             5    /* Yes         Any               */\r
+#define PORT_Microchip_dsPIC_AND_PIC24 6    /* Yes         Any               */\r
+#define PORT_TEXAS_INSTRUMENTS_TMS570  7    /* No          Any               */\r
+#define PORT_TEXAS_INSTRUMENTS_MSP430  8    /* No          Any               */\r
+#define PORT_MICROCHIP_PIC32           9    /* No          Any               */\r
+#define PORT_XILINX_PPC405             10   /* No          FreeRTOS          */\r
+#define PORT_XILINX_PPC440             11   /* No          FreeRTOS          */\r
+#define PORT_XILINX_MICROBLAZE         12   /* No          Any               */\r
+#define PORT_NXP_LPC210X               13   /* No          Any               */\r
+\r
+#include "trcConfig.h" // Where SELECTED_PORT is defined\r
+\r
+/*******************************************************************************\r
+ * IRQ_PRIORITY_ORDER\r
+ *\r
+ * Macro which should be defined as an integer of 0 or 1.\r
+ *\r
+ * This should be 0 if lower IRQ priority values implies higher priority \r
+ * levels, such as on ARM Cortex M. If the opposite scheme is used, i.e., \r
+ * if higher IRQ priority values means higher priority, this should be 1.\r
+ *\r
+ * This setting is not critical. It is used only to sort and colorize the \r
+ * interrupts in priority order, in case you record interrupts using\r
+ * the vTraceStoreISRBegin and vTraceStoreISREnd routines.\r
+ *\r
+ ******************************************************************************\r
+ *\r
+ * HWTC Macros \r
+ *\r
+ * These four HWTC macros provides a hardware isolation layer representing a \r
+ * generic hardware timer/counter used for driving the operating system tick, \r
+ * such as the SysTick feature of ARM Cortex M3/M4, or the PIT of the Atmel \r
+ * AT91SAM7X.\r
+ *\r
+ * HWTC_COUNT: The current value of the counter. This is expected to be reset \r
+ * a each tick interrupt. Thus, when the tick handler starts, the counter has \r
+ * already wrapped.\r
+ *\r
+ * HWTC_COUNT_DIRECTION: Should be one of:\r
+ * - DIRECTION_INCREMENTING - for hardware timer/counters of incrementing type\r
+ *   such as the PIT on Atmel AT91SAM7X.\r
+ *   When the counter value reach HWTC_PERIOD, it is reset to zero and the\r
+ *   interrupt is signaled.\r
+ * - DIRECTION_DECREMENTING - for hardware timer/counters of decrementing type\r
+ *   such as the SysTick on ARM Cortex M3/M4 chips.\r
+ *   When the counter value reach 0, it is reset to HWTC_PERIOD and the\r
+ *   interrupt is signaled.\r
+ *\r
+ * HWTC_PERIOD: The number of increments or decrements of HWTC_COUNT between\r
+ * two OS tick interrupts. This should preferably be mapped to the reload\r
+ * register of the hardware timer, to make it more portable between chips in the \r
+ * same family. The macro should in most cases be (reload register + 1).\r
+ * For FreeRTOS, this can in most cases be defined as \r
+ * #define HWTC_PERIOD (configCPU_CLOCK_HZ / configTICK_RATE_HZ)\r
+ *\r
+ * HWTC_DIVISOR: If the timer frequency is very high, like on the Cortex M chips\r
+ * (where the SysTick runs at the core clock frequency), the "differential \r
+ * timestamping" used in the recorder will more frequently insert extra XTS \r
+ * events to store the timestamps, which increases the event buffer usage. \r
+ * In such cases, to reduce the number of XTS events and thereby get longer \r
+ * traces, you use HWTC_DIVISOR to scale down the timestamps and frequency.\r
+ * Assuming a OS tick rate of 1 KHz, it is suggested to keep the effective timer\r
+ * frequency below 65 MHz to avoid an excessive amount of XTS events. Thus, a\r
+ * Cortex M chip running at 72 MHZ should use a HWTC_DIVISOR of 2, while a \r
+ * faster chip require a higher HWTC_DIVISOR value. \r
+ *\r
+ * The HWTC macros and vTracePortGetTimeStamp is the main porting issue\r
+ * or the trace recorder library. Typically you should not need to change\r
+ * the code of vTracePortGetTimeStamp if using the HWTC macros.\r
+ *\r
+ ******************************************************************************/\r
+\r
+#if (SELECTED_PORT == PORT_Win32)\r
+    // This can be used as a template for any free-running 32-bit counter\r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT (ulGetRunTimeCounterValue())\r
+    #define HWTC_PERIOD 0\r
+    #define HWTC_DIVISOR 1\r
+\r
+    // Please update according to your system...\r
+    #define IRQ_PRIORITY_ORDER 1  \r
+    \r
+#elif (SELECTED_PORT == PORT_HWIndependent) \r
+       // OS Tick only (typically 1 ms resolution)    \r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT 0\r
+    #define HWTC_PERIOD 1\r
+    #define HWTC_DIVISOR 1\r
+    \r
+       // Please update according to your system...\r
+    #define IRQ_PRIORITY_ORDER NOT_SET  \r
+\r
+\r
+#elif (SELECTED_PORT == PORT_ARM_CortexM)\r
+\r
+       void prvTraceSetIRQMask(uint32_t priMask);\r
+       uint32_t prvTraceGetIRQMask(void);\r
+       \r
+       void prvTraceEnableIRQ(void);\r
+       void prvTraceDisableIRQ(void);\r
+           \r
+       void prvTraceInitCortexM(void);\r
+               \r
+       #define PORT_SPECIFIC_INIT() prvTraceInitCortexM()      \r
+               \r
+       extern uint32_t DWT_CYCLES_ADDED;               \r
+       #define DWT_CTRL_REG (*((uint32_t*)0xE0001000))\r
+       #define DWT_CYCLE_COUNTER (*((uint32_t*)0xE0001004))\r
+       \r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT (DWT_CYCLE_COUNTER + DWT_CYCLES_ADDED)\r
+    #define HWTC_PERIOD 0\r
+    #define HWTC_DIVISOR 4\r
+\r
+    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_Renesas_RX600)    \r
+\r
+    #include "iodefine.h"\r
+\r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT (CMT0.CMCNT)\r
+    #define HWTC_PERIOD (CMT0.CMCOR + 1)\r
+    #define HWTC_DIVISOR 1\r
+    #define IRQ_PRIORITY_ORDER 1  // higher IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_Microchip_dsPIC_AND_PIC24)\r
+\r
+    /* For Microchip PIC24 and dsPIC (16 bit) */\r
+\r
+    /* Note: The trace library is designed for 32-bit MCUs and is slower than \r
+       intended on 16-bit MCUs. Storing an event on a PIC24 takes about 70 usec. \r
+       In comparison, 32-bit MCUs are often 10-20 times faster. If recording overhead \r
+       becomes a problem on PIC24, use the filters to exclude less interesting tasks \r
+       or system calls. */\r
+\r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT (TMR1)\r
+    #define HWTC_PERIOD (PR1+1)\r
+    #define HWTC_DIVISOR 1\r
+    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_Atmel_AT91SAM7)\r
+\r
+    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+       \r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT ((uint32_t)(AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF))\r
+    #define HWTC_PERIOD ((uint32_t)(AT91C_BASE_PITC->PITC_PIMR + 1))\r
+    #define HWTC_DIVISOR 1\r
+    #define IRQ_PRIORITY_ORDER 1  // higher IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_Atmel_UC3A0)\r
+\r
+    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+    /* For Atmel AVR32 (AT32UC3A).*/\r
+       \r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT ((uint32_t)sysreg_read(AVR32_COUNT))\r
+    #define HWTC_PERIOD ((uint32_t)(sysreg_read(AVR32_COMPARE) + 1))\r
+    #define HWTC_DIVISOR 1\r
+    #define IRQ_PRIORITY_ORDER 1  // higher IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_NXP_LPC210X)\r
+\r
+    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */   \r
+    /* Tested with LPC2106, but should work with most LPC21XX chips. */\r
+       \r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT  *((uint32_t *)0xE0004008 )\r
+    #define HWTC_PERIOD *((uint32_t *)0xE0004018 )\r
+    #define HWTC_DIVISOR 1    \r
+    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_TMS570)\r
\r
+    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+\r
+    #define RTIFRC0 *((uint32_t *)0xFFFFFC10)\r
+    #define RTICOMP0 *((uint32_t *)0xFFFFFC50)\r
+    #define RTIUDCP0 *((uint32_t *)0xFFFFFC54)\r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT (RTIFRC0 - (RTICOMP0 - RTIUDCP0))\r
+    #define HWTC_PERIOD (RTIUDCP0)\r
+    #define HWTC_DIVISOR 1\r
+\r
+    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_MSP430)\r
+\r
+    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+\r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT (TA0R)\r
+    #define HWTC_PERIOD (((uint16_t)TACCR0)+1)\r
+    #define HWTC_DIVISOR 1\r
+    #define IRQ_PRIORITY_ORDER 1  // higher IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_MICROCHIP_PIC32)\r
+\r
+    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+\r
+    #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+    #define HWTC_COUNT (ReadTimer1())     /* Should be available in BSP */\r
+    #define HWTC_PERIOD (ReadPeriod1()+1) /* Should be available in BSP */\r
+    #define HWTC_DIVISOR 1\r
+    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_XILINX_PPC405)\r
+    \r
+    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+\r
+    #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING\r
+    #define HWTC_COUNT  mfspr(0x3db)   \r
+       #if (defined configCPU_CLOCK_HZ && defined configTICK_RATE_HZ) // Check if FreeRTOS\r
+           /* For FreeRTOS only - found no generic OS independent solution for the PPC405 architecture. */\r
+           #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) // Same as in port.c for PPC405\r
+       #else\r
+           /* Not defined for other operating systems yet */\r
+           #error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick.\r
+       #endif  \r
+    #define HWTC_DIVISOR 1\r
+    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_XILINX_PPC440)\r
+    \r
+       /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+    /* This should work with most PowerPC chips */    \r
+    \r
+       #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING\r
+    #define HWTC_COUNT  mfspr(0x016)\r
+       #if (defined configCPU_CLOCK_HZ && defined configTICK_RATE_HZ) // Check if FreeRTOS\r
+               /* For FreeRTOS only - found no generic OS independent solution for the PPC440 architecture. */\r
+               #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) // Same as in port.c for PPC440\r
+       #else\r
+               /* Not defined for other operating systems yet */\r
+               #error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick.\r
+       #endif\r
+    #define HWTC_DIVISOR 1    \r
+    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
+    \r
+#elif (SELECTED_PORT == PORT_XILINX_MICROBLAZE)\r
+\r
+    /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+\r
+    /* This should work with most Microblaze configurations.\r
+     * It uses the AXI Timer 0 - the tick interrupt source.\r
+     * If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required.\r
+     */\r
+    #include "xtmrctr_l.h"\r
+\r
+    #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING\r
+    #define HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 )\r
+       #define HWTC_PERIOD (XTmrCtr_mGetLoadReg( XPAR_TMRCTR_0_BASEADDR,  0) + 1)\r
+    #define HWTC_DIVISOR 16\r
+    #define IRQ_PRIORITY_ORDER 0  // lower IRQ priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_APPLICATION_DEFINED)\r
+\r
+       #if !( defined (HWTC_COUNT_DIRECTION) && defined (HWTC_COUNT) && defined (HWTC_PERIOD) && defined (HWTC_DIVISOR) && defined (IRQ_PRIORITY_ORDER) )\r
+               #error SELECTED_PORT is PORT_APPLICATION_DEFINED but not all of the necessary constants have been defined.\r
+       #endif\r
+\r
+#elif (SELECTED_PORT != PORT_NOT_SET)\r
+\r
+    #error "SELECTED_PORT had unsupported value!"\r
+    #define SELECTED_PORT PORT_NOT_SET\r
+\r
+#endif\r
+\r
+#if (SELECTED_PORT != PORT_NOT_SET)\r
+    \r
+    #ifndef HWTC_COUNT_DIRECTION\r
+    #error "HWTC_COUNT_DIRECTION is not set!"\r
+    #endif \r
+    \r
+    #ifndef HWTC_COUNT\r
+    #error "HWTC_COUNT is not set!"    \r
+    #endif \r
+    \r
+    #ifndef HWTC_PERIOD\r
+    #error "HWTC_PERIOD is not set!"\r
+    #endif \r
+    \r
+    #ifndef HWTC_DIVISOR\r
+    #error "HWTC_DIVISOR is not set!"    \r
+    #endif \r
+    \r
+    #ifndef IRQ_PRIORITY_ORDER\r
+    #error "IRQ_PRIORITY_ORDER is not set!"\r
+    #elif (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1)\r
+    #error "IRQ_PRIORITY_ORDER has bad value!"\r
+    #endif \r
+    \r
+    #if (HWTC_DIVISOR < 1)\r
+    #error "HWTC_DIVISOR must be a non-zero positive value!"\r
+    #endif \r
+       \r
+#endif\r
+/*******************************************************************************\r
+ * vTraceConsoleMessage\r
+ *\r
+ * A wrapper for your system-specific console "printf" console output function.\r
+ * This needs to be correctly defined to see status reports from the trace \r
+ * status monitor task (this is defined in trcUser.c).\r
+ ******************************************************************************/         \r
+#define vTraceConsoleMessage(x)\r
+\r
+/*******************************************************************************\r
+ * vTracePortGetTimeStamp\r
+ *\r
+ * Returns the current time based on the HWTC macros which provide a hardware\r
+ * isolation layer towards the hardware timer/counter.\r
+ *\r
+ * The HWTC macros and vTracePortGetTimeStamp is the main porting issue\r
+ * or the trace recorder library. Typically you should not need to change\r
+ * the code of vTracePortGetTimeStamp if using the HWTC macros.\r
+ *\r
+ ******************************************************************************/\r
+void vTracePortGetTimeStamp(uint32_t *puiTimestamp);\r
+\r
+/*******************************************************************************\r
+ * vTracePortEnd\r
+ * \r
+ * This function is called when the recorder is stopped due to full buffer.\r
+ * Mainly intended to show a message in the console.\r
+ * This is used by the Win32 port to store the trace to a file. The file path is\r
+ * set using vTracePortSetFileName.\r
+ ******************************************************************************/\r
+void vTracePortEnd(void);\r
+\r
+#endif\r
index 4c8bdd509c8760ce74a90efbf14b2ecd77b0a84d..b92afa827ed60c37cb82dd43a18b5c5ac7f6ebb9 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcKernel.h\r
@@ -58,17 +58,17 @@ void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode,
                                                uint32_t param);\r
 \r
 void vTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass,\r
-                                    uint32_t objectNumber, uint8_t param);\r
+                                    uint32_t objectNumber, uint32_t param);\r
 \r
 void vTraceSetTaskInstanceFinished(objectHandleType handle);\r
 \r
-void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value);\r
+void vTraceSetPriorityProperty(uint8_t objectclass, objectHandleType id, uint8_t value);\r
 \r
-uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id);\r
+uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, objectHandleType id);\r
 \r
-void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value);\r
+void vTraceSetObjectState(uint8_t objectclass, objectHandleType id, uint8_t value);\r
 \r
-uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id);\r
+uint8_t uiTraceGetObjectState(uint8_t objectclass, objectHandleType id);\r
 \r
 #if (INCLUDE_OBJECT_DELETE == 1)\r
 \r
index 69431ee95df1b269d65d561d35f3694f7b3fbae6..a029124e4459fb6d82b1aedbd3447d69daed8b09 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
-* Tracealyzer v2.5.0 Recorder Library\r
+* Tracealyzer v2.6.0 Recorder Library\r
 * Percepio AB, www.percepio.com\r
 *\r
 * trcKernelHooks.h\r
@@ -97,7 +97,7 @@
 \r
 /* This macro will create a task in the object table */\r
 #undef trcKERNEL_HOOKS_TASK_CREATE\r
-#define trcKERNEL_HOOKS_TASK_CREATE(SERVICE, pxTCB) \\r
+#define trcKERNEL_HOOKS_TASK_CREATE(SERVICE, CLASS, pxTCB) \\r
        TRACE_SET_TASK_NUMBER(pxTCB) \\r
        vTraceSetObjectName(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_NAME(pxTCB)); \\r
        vTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \\r
 \r
 /* This macro will create a failed create call to create a task */\r
 #undef trcKERNEL_HOOKS_TASK_CREATE_FAILED\r
-#define trcKERNEL_HOOKS_TASK_CREATE_FAILED(SERVICE) \\r
-       vTraceStoreKernelCall(TRACE_GET_TASK_EVENT_CODE(SERVICE, FAILED, CLASS, pxTCB), TRACE_CLASS_TASK, 0);\r
+#define trcKERNEL_HOOKS_TASK_CREATE_FAILED(SERVICE, CLASS) \\r
+       vTraceStoreKernelCall(TRACE_GET_TASK_EVENT_CODE(SERVICE, FAILED, CLASS, 0), TRACE_CLASS_TASK, 0);\r
 \r
 /* This macro will setup a task in the object table */\r
 #undef trcKERNEL_HOOKS_OBJECT_CREATE\r
 \r
 /* This macro will flag a certain task as a finished instance */\r
 #undef trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED\r
-#define trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(CLASS, pxObject) \\r
+#define trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED() \\r
        vTraceSetTaskInstanceFinished(TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()));\r
 \r
 #if INCLUDE_READY_EVENTS == 1\r
 #undef trcKERNEL_HOOKS_TASK_RESUME\r
 #define trcKERNEL_HOOKS_TASK_RESUME(SERVICE, pxTCB) \\r
        vTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));\r
-\r
+       \r
+#undef trcKERNEL_HOOKS_TIMER_EVENT\r
+#define trcKERNEL_HOOKS_TIMER_EVENT(SERVICE, pxTimer) \\r
+       vTraceStoreKernelCall(SERVICE, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer));\r
+\r
+/* This macro will create a timer in the object table and assign the timer a trace handle (timer number).*/\r
+#undef trcKERNEL_HOOKS_TIMER_CREATE\r
+#define trcKERNEL_HOOKS_TIMER_CREATE(SERVICE, pxTimer) \\r
+TRACE_SET_TIMER_NUMBER(pxTimer); \\r
+vTraceSetObjectName(TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_GET_TIMER_NAME(pxTimer)); \\r
+vTraceStoreKernelCall(SERVICE, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer));\r
 #endif\r
 \r
-#endif /* TRCKERNELHOOKS_H */\r
+#undef trcKERNEL_HOOKS_TIMER_DELETE\r
+#define trcKERNEL_HOOKS_TIMER_DELETE(SERVICE, pxTimer) \\r
+vTraceStoreKernelCall(SERVICE, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer)); \\r
+vTraceStoreObjectNameOnCloseEvent(TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_CLASS_TIMER); \\r
+vTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_CLASS_TIMER); \\r
+vTraceFreeObjectHandle(TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer));\r
+\r
+#endif /* TRCKERNELHOOKS_H */
\ No newline at end of file
index 211878a5db21f0960fd817c510c7b480b9473c28..b08a1f13b1ec8635645ec1f2a70acface49c7cd2 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcKernelPort.h\r
@@ -40,6 +40,9 @@
 #define TRCKERNELPORT_H_\r
 \r
 #include "FreeRTOS.h"  // Defines configUSE_TRACE_FACILITY\r
+#include "trcHardwarePort.h"\r
+\r
+extern int uiInEventGroupSetBitsFromISR;\r
 \r
 #define USE_TRACEALYZER_RECORDER configUSE_TRACE_FACILITY\r
 \r
 /* Defines that must be set for the recorder to work properly */\r
 #define TRACE_KERNEL_VERSION 0x1AA1\r
 #define TRACE_TICK_RATE_HZ configTICK_RATE_HZ /* Defined in "FreeRTOS.h" */\r
+#define TRACE_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOSConfig.h" */\r
+\r
+#if ((SELECTED_PORT == PORT_ARM_CortexM) && (USE_PRIMASK_CS == 1))\r
+\r
+#define TRACE_SR_ALLOC_CRITICAL_SECTION() int __irq_status;\r
+\r
+#define TRACE_ENTER_CRITICAL_SECTION() { __irq_status = prvTraceGetIRQMask(); prvTraceDisableIRQ(); }\r
+\r
+#define TRACE_EXIT_CRITICAL_SECTION() { prvTraceSetIRQMask(__irq_status); }\r
+\r
+#define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_BEGIN\r
+#define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_END\r
+\r
+#else\r
+\r
+#define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL()\r
+#define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL()\r
+\r
+#define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY() recorder_busy++;\r
+#define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--;\r
+\r
+#endif\r
 \r
 /************************************************************************/\r
 /* KERNEL SPECIFIC OBJECT CONFIGURATION                                 */\r
 /************************************************************************/\r
-#define TRACE_NCLASSES 5\r
+#define TRACE_NCLASSES 7\r
 #define TRACE_CLASS_QUEUE ((traceObjectClass)0)\r
 #define TRACE_CLASS_SEMAPHORE ((traceObjectClass)1)\r
 #define TRACE_CLASS_MUTEX ((traceObjectClass)2)\r
 #define TRACE_CLASS_TASK ((traceObjectClass)3)\r
 #define TRACE_CLASS_ISR ((traceObjectClass)4)\r
+#define TRACE_CLASS_TIMER ((traceObjectClass)5)\r
+#define TRACE_CLASS_EVENTGROUP ((traceObjectClass)6)\r
 \r
-#define TRACE_KERNEL_OBJECT_COUNT (NQueue + NSemaphore + NMutex + NTask + NISR)\r
+#define TRACE_KERNEL_OBJECT_COUNT (NQueue + NSemaphore + NMutex + NTask + NISR + NTimer + NEventGroup)\r
 \r
 /* The size of the Object Property Table entries, in bytes, per object */\r
 \r
                                        Byte 1: state (if already active) */\r
 #define PropertyTableSizeISR          (NameLenISR + 2)\r
 \r
+/* NTimer properties:                  Byte 0: state (unused for now) */\r
+#define PropertyTableSizeTimer        (NameLenTimer + 1)\r
+\r
+/* NEventGroup properties:            Byte 0-3: state (unused for now)*/\r
+#define PropertyTableSizeEventGroup       (NameLenEventGroup + 4)\r
+\r
+\r
 /* The layout of the byte array representing the Object Property Table */\r
 #define StartIndexQueue            0\r
 #define StartIndexSemaphore        StartIndexQueue     + NQueue * PropertyTableSizeQueue\r
 #define StartIndexMutex            StartIndexSemaphore + NSemaphore * PropertyTableSizeSemaphore\r
 #define StartIndexTask             StartIndexMutex     + NMutex * PropertyTableSizeMutex\r
 #define StartIndexISR              StartIndexTask      + NTask * PropertyTableSizeTask\r
+#define StartIndexTimer            StartIndexISR       + NISR * PropertyTableSizeISR\r
+#define StartIndexEventGroup       StartIndexTimer     + NTimer * PropertyTableSizeTimer\r
 \r
 /* Number of bytes used by the object table */\r
-#define TRACE_OBJECT_TABLE_SIZE    StartIndexISR       + NISR * PropertyTableSizeISR\r
-\r
+#define TRACE_OBJECT_TABLE_SIZE    StartIndexEventGroup       + NEventGroup * PropertyTableSizeEventGroup\r
 \r
 /* Includes */\r
+#include "trcConfig.h" /* Must be first, even before trcTypes.h */\r
+#include "trcHardwarePort.h"\r
 #include "trcTypes.h"\r
-#include "trcConfig.h"\r
 #include "trcKernelHooks.h"\r
-#include "trcHardwarePort.h"\r
 #include "trcBase.h"\r
 #include "trcKernel.h"\r
 #include "trcUser.h"\r
@@ -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\r
  * create operation (task, queue, semaphore, etc).\r
  ******************************************************************************/\r
-#define EVENTGROUP_CREATE_SUCCESS    (EVENTGROUP_OBJCLOSE_PROP + 8)             /*0x18*/\r
+#define EVENTGROUP_CREATE_OBJ_SUCCESS    (EVENTGROUP_OBJCLOSE_PROP + 8)             /*0x18*/\r
 \r
 /*******************************************************************************\r
  * EVENTGROUP_SEND\r
@@ -197,7 +232,7 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
  * object class, i.e., what type of object that is operated on (queue, semaphore \r
  * or mutex).\r
  ******************************************************************************/\r
-#define EVENTGROUP_SEND_SUCCESS      (EVENTGROUP_CREATE_SUCCESS + 8)                    /*0x20*/\r
+#define EVENTGROUP_SEND_SUCCESS      (EVENTGROUP_CREATE_OBJ_SUCCESS + 8)                    /*0x20*/\r
 \r
 /*******************************************************************************\r
  * EVENTGROUP_RECEIVE\r
@@ -219,10 +254,10 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
 #define EVENTGROUP_KSE_FAILED         (EVENTGROUP_RECEIVE_FROM_ISR_SUCCESS + 8) /*0x40*/\r
 \r
 /* Failed create calls - memory allocation failed */\r
-#define EVENTGROUP_CREATE_FAILED                (EVENTGROUP_KSE_FAILED) /*0x40*/\r
+#define EVENTGROUP_CREATE_OBJ_FAILED                (EVENTGROUP_KSE_FAILED) /*0x40*/\r
 \r
 /* Failed send/give - timeout! */\r
-#define EVENTGROUP_SEND_FAILED           (EVENTGROUP_CREATE_FAILED + 8) /*0x48*/\r
+#define EVENTGROUP_SEND_FAILED           (EVENTGROUP_CREATE_OBJ_FAILED + 8) /*0x48*/\r
 \r
 /* Failed receive/take - timeout! */\r
 #define EVENTGROUP_RECEIVE_FAILED          (EVENTGROUP_SEND_FAILED + 8) /*0x50*/\r
@@ -245,10 +280,10 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
 #define EVENTGROUP_PEEK_SUCCESS              (EVENTGROUP_SEND_BLOCK + 8)     /*0x78*/\r
 \r
 /* Events on object delete (vTaskDelete or vQueueDelete) */\r
-#define EVENTGROUP_DELETE_SUCCESS            (EVENTGROUP_PEEK_SUCCESS + 8)              /*0x80*/\r
+#define EVENTGROUP_DELETE_OBJ_SUCCESS            (EVENTGROUP_PEEK_SUCCESS + 8)              /*0x80*/\r
 \r
 /* Other events - object class is implied: TASK */\r
-#define EVENTGROUP_OTHERS            (EVENTGROUP_DELETE_SUCCESS + 8)            /*0x88*/\r
+#define EVENTGROUP_OTHERS            (EVENTGROUP_DELETE_OBJ_SUCCESS + 8)            /*0x88*/\r
 #define TASK_DELAY_UNTIL             (EVENTGROUP_OTHERS + 0)            /*0x88*/\r
 #define TASK_DELAY                   (EVENTGROUP_OTHERS + 1)            /*0x89*/\r
 #define TASK_SUSPEND                 (EVENTGROUP_OTHERS + 2)            /*0x8A*/\r
@@ -258,11 +293,18 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
 #define TASK_PRIORITY_INHERIT        (EVENTGROUP_OTHERS + 6)            /*0x8E*/\r
 #define TASK_PRIORITY_DISINHERIT     (EVENTGROUP_OTHERS + 7)            /*0x8F*/\r
 \r
-/* Not yet used */\r
-#define EVENTGROUP_FTRACE_PLACEHOLDER    (EVENTGROUP_OTHERS + 8)        /*0x90*/\r
+#define EVENTGROUP_MISC_PLACEHOLDER    (EVENTGROUP_OTHERS + 8)                 /*0x90*/\r
+#define PEND_FUNC_CALL (EVENTGROUP_MISC_PLACEHOLDER+0)                                 /*0x90*/\r
+#define PEND_FUNC_CALL_FROM_ISR (EVENTGROUP_MISC_PLACEHOLDER+1)                        /*0x91*/\r
+#define PEND_FUNC_CALL_FAILED (EVENTGROUP_MISC_PLACEHOLDER+2)                  /*0x92*/\r
+#define PEND_FUNC_CALL_FROM_ISR_FAILED (EVENTGROUP_MISC_PLACEHOLDER+3) /*0x93*/\r
+#define MEM_MALLOC_SIZE (EVENTGROUP_MISC_PLACEHOLDER+4)                                        /*0x94*/\r
+#define MEM_MALLOC_ADDR (EVENTGROUP_MISC_PLACEHOLDER+5)                                        /*0x95*/\r
+#define MEM_FREE_SIZE (EVENTGROUP_MISC_PLACEHOLDER+6)                                  /*0x96*/\r
+#define MEM_FREE_ADDR (EVENTGROUP_MISC_PLACEHOLDER+7)                                  /*0x97*/\r
 \r
 /* User events */\r
-#define EVENTGROUP_USEREVENT (EVENTGROUP_FTRACE_PLACEHOLDER + 8)        /*0x98*/\r
+#define EVENTGROUP_USEREVENT (EVENTGROUP_MISC_PLACEHOLDER + 8)        /*0x98*/\r
 #define USER_EVENT (EVENTGROUP_USEREVENT + 0)\r
 \r
 /* Allow for 0-15 arguments (the number of args is added to event code) */\r
@@ -300,7 +342,47 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
 #define LOW_POWER_BEGIN (EVENTGROUP_SYS + 4)                                                   /*0xAC*/\r
 #define LOW_POWER_END (EVENTGROUP_SYS + 5)                                                             /*0xAD*/\r
 \r
-\r
+#define XID (EVENTGROUP_SYS + 6)                                                                               /*0xAE*/\r
+\r
+#define XTS16L (EVENTGROUP_SYS + 7)                                                                            /*0xAF*/\r
+\r
+#define EVENTGROUP_TIMER (EVENTGROUP_SYS + 8)                                                  /*0xB0*/\r
+\r
+#define TIMER_CREATE (EVENTGROUP_TIMER + 0)                                                            /*0xB0*/\r
+#define TIMER_START (EVENTGROUP_TIMER + 1)                                                             /*0xB0*/\r
+#define TIMER_RESET (EVENTGROUP_TIMER + 2)                                                             /*0xB1*/\r
+#define TIMER_STOP (EVENTGROUP_TIMER + 3)                                                              /*0xB2*/\r
+#define TIMER_CHANGE_PERIOD (EVENTGROUP_TIMER + 4)                                             /*0xB3*/\r
+#define TIMER_DELETE (EVENTGROUP_TIMER + 5)                                                            /*0xB4*/\r
+#define TIMER_START_FROM_ISR (EVENTGROUP_TIMER + 6)                                            /*0xB6*/\r
+#define TIMER_RESET_FROM_ISR (EVENTGROUP_TIMER + 7)                                            /*0xB7*/\r
+#define TIMER_STOP_FROM_ISR (EVENTGROUP_TIMER + 8)                                             /*0xB8*/\r
+\r
+#define TIMER_CREATE_FAILED (EVENTGROUP_TIMER + 9)                                             /*0xB9*/\r
+#define TIMER_START_FAILED (EVENTGROUP_TIMER + 10)                                             /*0xBA*/\r
+#define TIMER_RESET_FAILED (EVENTGROUP_TIMER + 11)                                             /*0xBB*/\r
+#define TIMER_STOP_FAILED (EVENTGROUP_TIMER + 12)                                              /*0xBC*/\r
+#define TIMER_CHANGE_PERIOD_FAILED (EVENTGROUP_TIMER + 13)                             /*0xBD*/\r
+#define TIMER_DELETE_FAILED (EVENTGROUP_TIMER + 14)                                            /*0xBE*/\r
+#define TIMER_START_FROM_ISR_FAILED (EVENTGROUP_TIMER + 15)                            /*0xBF*/\r
+#define TIMER_RESET_FROM_ISR_FAILED (EVENTGROUP_TIMER + 16)                            /*0xC0*/\r
+#define TIMER_STOP_FROM_ISR_FAILED (EVENTGROUP_TIMER + 17)                             /*0xC1*/\r
+\r
+#define EVENTGROUP_EG (EVENTGROUP_TIMER + 18)                                                  /*0xC2*/\r
+#define EVENT_GROUP_CREATE (EVENTGROUP_EG + 0)                                                 /*0xC2*/\r
+#define EVENT_GROUP_CREATE_FAILED (EVENTGROUP_EG + 1)                                  /*0xC3*/\r
+#define EVENT_GROUP_SYNC_BLOCK (EVENTGROUP_EG + 2)                                             /*0xC4*/\r
+#define EVENT_GROUP_SYNC_END (EVENTGROUP_EG + 3)                                               /*0xC5*/\r
+#define EVENT_GROUP_WAIT_BITS_BLOCK (EVENTGROUP_EG + 4)                                        /*0xC6*/\r
+#define EVENT_GROUP_WAIT_BITS_END (EVENTGROUP_EG + 5)                                  /*0xC7*/\r
+#define EVENT_GROUP_CLEAR_BITS (EVENTGROUP_EG + 6)                                             /*0xC8*/\r
+#define EVENT_GROUP_CLEAR_BITS_FROM_ISR (EVENTGROUP_EG + 7)                            /*0xC9*/\r
+#define EVENT_GROUP_SET_BITS (EVENTGROUP_EG + 8)                                               /*0xCA*/\r
+#define EVENT_GROUP_DELETE (EVENTGROUP_EG + 9)                                                 /*0xCB*/\r
+#define EVENT_GROUP_SYNC_END_FAILED (EVENTGROUP_EG + 10)                               /*0xCC*/\r
+#define EVENT_GROUP_WAIT_BITS_END_FAILED (EVENTGROUP_EG + 11)                  /*0xCD*/\r
+#define EVENT_GROUP_SET_BITS_FROM_ISR  (EVENTGROUP_EG + 12)             /*0xCE*/\r
+#define EVENT_GROUP_SET_BITS_FROM_ISR_FAILED (EVENTGROUP_EG + 13)              /*0xCF*/\r
 \r
 /************************************************************************/\r
 /* KERNEL SPECIFIC DATA AND FUNCTIONS NEEDED TO PROVIDE THE             */\r
@@ -330,20 +412,18 @@ objectHandleType prvTraceGetTaskNumber(void* handle);
 unsigned char prvTraceIsSchedulerActive(void);\r
 unsigned char prvTraceIsSchedulerSuspended(void);\r
 unsigned char prvTraceIsSchedulerStarted(void);\r
-void prvTraceEnterCritical(void);\r
-void prvTraceExitCritical(void);\r
 void* prvTraceGetCurrentTaskHandle(void);\r
 \r
+#if (configUSE_TIMERS == 1)\r
+#undef INCLUDE_xTimerGetTimerDaemonTaskHandle\r
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1\r
+#endif\r
 \r
 /************************************************************************/\r
 /* KERNEL SPECIFIC MACROS USED BY THE TRACE RECORDER                    */\r
 /************************************************************************/\r
 \r
 #define TRACE_MALLOC(size) pvPortMalloc(size)\r
-\r
-#define TRACE_ENTER_CRITICAL_SECTION() prvTraceEnterCritical();\r
-#define TRACE_EXIT_CRITICAL_SECTION() prvTraceExitCritical();\r
-\r
 #define TRACE_IS_SCHEDULER_ACTIVE() prvTraceIsSchedulerActive()\r
 #define TRACE_IS_SCHEDULER_STARTED() prvTraceIsSchedulerStarted()\r
 #define TRACE_IS_SCHEDULER_SUSPENDED() prvTraceIsSchedulerSuspended()\r
@@ -357,12 +437,20 @@ void* prvTraceGetCurrentTaskHandle(void);
 #define TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass) TraceObjectClassTable[kernelClass]\r
 #define TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject) TRACE_GET_CLASS_TRACE_CLASS(CLASS, prvTraceGetObjectType(pxObject))\r
 \r
+#define TRACE_GET_TIMER_NUMBER(tmr) ( ( objectHandleType ) ((Timer_t*)tmr)->uxTimerNumber )\r
+#define TRACE_SET_TIMER_NUMBER(tmr) ((Timer_t*)tmr)->uxTimerNumber = xTraceGetObjectHandle(TRACE_CLASS_TIMER);\r
+#define TRACE_GET_TIMER_NAME(pxTimer) pxTimer->pcTimerName\r
+#define TRACE_GET_TIMER_PERIOD(pxTimer) pxTimer->xTimerPeriodInTicks\r
+\r
+#define TRACE_GET_EVENTGROUP_NUMBER(eg)  ( ( objectHandleType ) uxEventGroupGetNumber(eg) )\r
+#define TRACE_SET_EVENTGROUP_NUMBER(eg) ((EventGroup_t*)eg)->uxEventGroupNumber = xTraceGetObjectHandle(TRACE_CLASS_EVENTGROUP);\r
+\r
 #define TRACE_GET_OBJECT_NUMBER(CLASS, pxObject) (prvTraceGetObjectNumber(pxObject))\r
 #define TRACE_SET_OBJECT_NUMBER(CLASS, pxObject) pxObject->uxQueueNumber = xTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject));\r
 \r
 #define TRACE_GET_CLASS_EVENT_CODE(SERVICE, RESULT, CLASS, kernelClass) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass))\r
 #define TRACE_GET_OBJECT_EVENT_CODE(SERVICE, RESULT, CLASS, pxObject) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject))\r
-#define TRACE_GET_TASK_EVENT_CODE(SERVICE, RESULT, CLASS, pxTCB) (EVENTGROUP_##SERVICE##_##RESULT + TRACE_CLASS_TASK)\r
+#define TRACE_GET_TASK_EVENT_CODE(SERVICE, RESULT, CLASS, pxTCB) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_CLASS_TASK)\r
 \r
 /************************************************************************/\r
 /* KERNEL SPECIFIC WRAPPERS THAT SHOULD BE CALLED BY THE KERNEL         */\r
@@ -386,17 +474,18 @@ void* prvTraceGetCurrentTaskHandle(void);
                vTraceStoreLowPower(1); \\r
        }\r
 \r
-/* A macro that will update the tick count when returning from tickless idle */\r
-#undef traceINCREASE_TICK_COUNT( xCount )\r
-#define traceINCREASE_TICK_COUNT( xCount ) { extern uint32_t uiTraceTickCount; uiTraceTickCount += xTickCount; }\r
-\r
 #endif\r
 \r
+/* A macro that will update the tick count when returning from tickless idle */\r
+#undef traceINCREASE_TICK_COUNT\r
+/* 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.*/\r
+#define traceINCREASE_TICK_COUNT( xCount ) { DWT_CYCLES_ADDED += (xCount * (TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ)); }\r
+\r
 /* Called for each task that becomes ready */\r
 #undef traceMOVED_TASK_TO_READY_STATE\r
 #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \\r
        trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB);\r
-\r
+       \r
 /* Called on each OS tick. Will call uiPortGetTimestamp to make sure it is called at least once every OS tick. */\r
 #undef traceTASK_INCREMENT_TICK\r
 #define traceTASK_INCREMENT_TICK( xTickCount ) \\r
@@ -411,38 +500,38 @@ void* prvTraceGetCurrentTaskHandle(void);
 /* Called on vTaskSuspend */\r
 #undef traceTASK_SUSPEND\r
 #define traceTASK_SUSPEND( pxTaskToSuspend ) \\r
-       trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend);\r
+       trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend);    \r
 \r
 /* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */\r
 #undef traceTASK_DELAY\r
 #define traceTASK_DELAY() \\r
-       TRACE_ENTER_CRITICAL_SECTION(); \\r
        trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY, pxCurrentTCB, xTicksToDelay); \\r
-       trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(UNUSED,pxCurrentTCB); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();   \r
 \r
 /* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */\r
 #undef traceTASK_DELAY_UNTIL\r
 #define traceTASK_DELAY_UNTIL() \\r
-       TRACE_ENTER_CRITICAL_SECTION(); \\r
        trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \\r
-       trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(UNUSED,pxCurrentTCB); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();\r
 \r
 #if (INCLUDE_OBJECT_DELETE == 1)\r
 /* Called on vTaskDelete */\r
 #undef traceTASK_DELETE\r
 #define traceTASK_DELETE( pxTaskToDelete ) \\r
-       trcKERNEL_HOOKS_TASK_DELETE(DELETE, pxTaskToDelete);\r
+       { TRACE_SR_ALLOC_CRITICAL_SECTION(); \\r
+       TRACE_ENTER_CRITICAL_SECTION(); \\r
+       trcKERNEL_HOOKS_TASK_DELETE(DELETE_OBJ, pxTaskToDelete); \\r
+       TRACE_EXIT_CRITICAL_SECTION(); }\r
 #endif\r
 \r
 #if (INCLUDE_OBJECT_DELETE == 1)\r
 /* Called on vQueueDelete */\r
 #undef traceQUEUE_DELETE\r
 #define traceQUEUE_DELETE( pxQueue ) \\r
+       { TRACE_SR_ALLOC_CRITICAL_SECTION(); \\r
        TRACE_ENTER_CRITICAL_SECTION(); \\r
-       trcKERNEL_HOOKS_OBJECT_DELETE(DELETE, UNUSED, pxQueue); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       trcKERNEL_HOOKS_OBJECT_DELETE(DELETE_OBJ, UNUSED, pxQueue); \\r
+       TRACE_EXIT_CRITICAL_SECTION(); }\r
 #endif\r
 \r
 /* Called on vTaskCreate */\r
@@ -450,94 +539,72 @@ void* prvTraceGetCurrentTaskHandle(void);
 #define traceTASK_CREATE(pxNewTCB) \\r
        if (pxNewTCB != NULL) \\r
        { \\r
-               trcKERNEL_HOOKS_TASK_CREATE(CREATE, pxNewTCB); \\r
+               trcKERNEL_HOOKS_TASK_CREATE(CREATE_OBJ, UNUSED, pxNewTCB); \\r
        }\r
 \r
 /* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */\r
 #undef traceTASK_CREATE_FAILED\r
 #define traceTASK_CREATE_FAILED() \\r
-       TRACE_ENTER_CRITICAL_SECTION(); \\r
-       trcKERNEL_HOOKS_TASK_CREATE_FAILED(CREATE); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       trcKERNEL_HOOKS_TASK_CREATE_FAILED(CREATE_OBJ, UNUSED); \r
 \r
 /* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */\r
 #undef traceQUEUE_CREATE\r
 #define traceQUEUE_CREATE( pxNewQueue )\\r
-       TRACE_ENTER_CRITICAL_SECTION(); \\r
-       trcKERNEL_HOOKS_OBJECT_CREATE(CREATE, UNUSED, pxNewQueue); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       trcKERNEL_HOOKS_OBJECT_CREATE(CREATE_OBJ, UNUSED, pxNewQueue);  \r
 \r
 /* Called in xQueueCreate, if the queue creation fails */\r
 #undef traceQUEUE_CREATE_FAILED\r
 #define traceQUEUE_CREATE_FAILED( queueType ) \\r
-       TRACE_ENTER_CRITICAL_SECTION(); \\r
-       trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE, UNUSED, queueType); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE_OBJ, UNUSED, queueType);\r
 \r
 /* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */\r
 #undef traceCREATE_MUTEX\r
 #define traceCREATE_MUTEX( pxNewQueue ) \\r
-       TRACE_ENTER_CRITICAL_SECTION(); \\r
-       trcKERNEL_HOOKS_OBJECT_CREATE(CREATE, UNUSED, pxNewQueue); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
-\r
+       trcKERNEL_HOOKS_OBJECT_CREATE(CREATE_OBJ, UNUSED, pxNewQueue);\r
+       \r
 /* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */\r
 #undef traceCREATE_MUTEX_FAILED\r
 #define traceCREATE_MUTEX_FAILED() \\r
-       TRACE_ENTER_CRITICAL_SECTION(); \\r
-       trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE, UNUSED, queueQUEUE_TYPE_MUTEX); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE_OBJ, UNUSED, queueQUEUE_TYPE_MUTEX);\r
 \r
 /* Called when the Mutex can not be given, since not holder */\r
 #undef traceGIVE_MUTEX_RECURSIVE_FAILED\r
 #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) \\r
-       TRACE_ENTER_CRITICAL_SECTION(); \\r
-       trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxMutex); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxMutex);\r
 \r
-/* Called when a message is sent to a queue */\r
+/* Called when a message is sent to a queue */   /* CS IS NEW ! */\r
 #undef traceQUEUE_SEND\r
 #define traceQUEUE_SEND( pxQueue ) \\r
        trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, SUCCESS, UNUSED, pxQueue); \\r
-       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 */\r
+       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));\r
 \r
 /* Called when a message failed to be sent to a queue (timeout) */\r
 #undef traceQUEUE_SEND_FAILED\r
 #define traceQUEUE_SEND_FAILED( pxQueue ) \\r
-    TRACE_ENTER_CRITICAL_SECTION();\\r
-    trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxQueue); \\r
-    TRACE_EXIT_CRITICAL_SECTION();\r
+    trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxQueue);\r
 \r
 /* Called when the task is blocked due to a send operation on a full queue */\r
 #undef traceBLOCKING_ON_QUEUE_SEND\r
 #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) \\r
-       TRACE_ENTER_CRITICAL_SECTION();\\r
-       trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, BLOCK, UNUSED, pxQueue); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, BLOCK, UNUSED, pxQueue);\r
 \r
 /* Called when a message is received from a queue */\r
 #undef traceQUEUE_RECEIVE\r
 #define traceQUEUE_RECEIVE( pxQueue ) \\r
        trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, SUCCESS, UNUSED, pxQueue); \\r
-       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 */\r
+       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));\r
 \r
 /* Called when a receive operation on a queue fails (timeout) */\r
 #undef traceQUEUE_RECEIVE_FAILED\r
 #define traceQUEUE_RECEIVE_FAILED( pxQueue ) \\r
-       TRACE_ENTER_CRITICAL_SECTION(); \\r
-       trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, FAILED, UNUSED, pxQueue); \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, FAILED, UNUSED, pxQueue);\r
 \r
 /* Called when the task is blocked due to a receive operation on an empty queue */\r
 #undef traceBLOCKING_ON_QUEUE_RECEIVE\r
 #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \\r
-       TRACE_ENTER_CRITICAL_SECTION(); \\r
        trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, BLOCK, UNUSED, pxQueue); \\r
        if (TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, pxQueue) != TRACE_CLASS_MUTEX) \\r
-       { \\r
-               trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(UNUSED, pxQueue); \\r
-       } \\r
-       TRACE_EXIT_CRITICAL_SECTION();\r
+       {trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();}\r
 \r
 /* Called on xQueuePeek */\r
 #undef traceQUEUE_PEEK\r
@@ -554,43 +621,138 @@ void* prvTraceGetCurrentTaskHandle(void);
 #undef traceQUEUE_SEND_FROM_ISR_FAILED\r
 #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) \\r
        trcKERNEL_HOOKS_KERNEL_SERVICE(SEND_FROM_ISR, FAILED, UNUSED, pxQueue);\r
-\r
+       \r
 /* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */\r
 #undef traceQUEUE_RECEIVE_FROM_ISR\r
 #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \\r
        trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE_FROM_ISR, SUCCESS, UNUSED, pxQueue); \\r
        trcKERNEL_HOOKS_SET_OBJECT_STATE(UNUSED, pxQueue, (uint8_t)(pxQueue->uxMessagesWaiting - 1));\r
-\r
+       \r
 /* Called when a message receive from interrupt context fails (since the queue was empty) */\r
 #undef traceQUEUE_RECEIVE_FROM_ISR_FAILED\r
 #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) \\r
        trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE_FROM_ISR, FAILED, UNUSED, pxQueue);\r
-\r
+       \r
 /* Called in vTaskPrioritySet */\r
 #undef traceTASK_PRIORITY_SET\r
 #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \\r
        trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_SET, pxTask, uxNewPriority);\r
-\r
+       \r
 /* Called in vTaskPriorityInherit, which is called by Mutex operations */\r
 #undef traceTASK_PRIORITY_INHERIT\r
 #define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \\r
        trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_INHERIT, pxTask, uxNewPriority);\r
-\r
+       \r
 /* Called in vTaskPriorityDisinherit, which is called by Mutex operations */\r
 #undef traceTASK_PRIORITY_DISINHERIT\r
 #define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \\r
        trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_DISINHERIT, pxTask, uxNewPriority);\r
-\r
+       \r
 /* Called in vTaskResume */\r
 #undef traceTASK_RESUME\r
 #define traceTASK_RESUME( pxTaskToResume ) \\r
        trcKERNEL_HOOKS_TASK_RESUME(TASK_RESUME, pxTaskToResume);\r
-\r
+       \r
 /* Called in vTaskResumeFromISR */\r
 #undef traceTASK_RESUME_FROM_ISR\r
 #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) \\r
        trcKERNEL_HOOKS_TASK_RESUME(TASK_RESUME_FROM_ISR, pxTaskToResume);\r
+       \r
+\r
+/* Called in timer.c - xTimerCreate */\r
+#undef traceTIMER_CREATE\r
+#define traceTIMER_CREATE(tmr) \\r
+       trcKERNEL_HOOKS_TIMER_CREATE(TIMER_CREATE, tmr);\r
+\r
+#undef traceTIMER_CREATE_FAILED\r
+#define traceTIMER_CREATE_FAILED() \\r
+       trcKERNEL_HOOKS_TIMER_EVENT(TIMER_CREATE_FAILED, 0);\r
+               \r
+/* Note that xCommandID can never be tmrCOMMAND_EXECUTE_CALLBACK (-1) since the trace macro is not called in that case */\r
+#undef traceTIMER_COMMAND_SEND\r
+#define traceTIMER_COMMAND_SEND(tmr, xCommandID, xOptionalValue, xReturn) \\r
+if (xCommandID > tmrCOMMAND_START_DONT_TRACE){\\r
+               if (xCommandID == tmrCOMMAND_CHANGE_PERIOD) vTraceStoreKernelCallWithParam((xReturn == pdPASS) ? TIMER_CHANGE_PERIOD : TIMER_CHANGE_PERIOD_FAILED, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(tmr), xOptionalValue);\\r
+               else if ((xCommandID == tmrCOMMAND_DELETE) && (xReturn == pdPASS)){ trcKERNEL_HOOKS_TIMER_DELETE(TIMER_DELETE, tmr); } \\r
+               else {trcKERNEL_HOOKS_TIMER_EVENT(EVENTGROUP_TIMER + xCommandID + ((xReturn == pdPASS)?0:(TIMER_CREATE_FAILED - TIMER_CREATE)), tmr); }\\r
+}\r
 \r
+#undef tracePEND_FUNC_CALL\r
+#define tracePEND_FUNC_CALL(func, arg1, arg2, ret) \\r
+if (ret == pdPASS) \\r
+       vTraceStoreKernelCall(PEND_FUNC_CALL, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTimerGetTimerDaemonTaskHandle()) ); \\r
+else \\r
+       vTraceStoreKernelCall(PEND_FUNC_CALL_FAILED, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTimerGetTimerDaemonTaskHandle()) );\r
+       \r
+#undef tracePEND_FUNC_CALL_FROM_ISR\r
+#define tracePEND_FUNC_CALL_FROM_ISR(func, arg1, arg2, ret) \\r
+       if (! uiInEventGroupSetBitsFromISR) vTraceStoreKernelCall(PEND_FUNC_CALL_FROM_ISR, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTimerGetTimerDaemonTaskHandle()) ); \\r
+       uiInEventGroupSetBitsFromISR = 0;\r
+\r
+#undef traceEVENT_GROUP_CREATE\r
+#define traceEVENT_GROUP_CREATE(eg) \\r
+       TRACE_SET_EVENTGROUP_NUMBER(eg); \\r
+       vTraceStoreKernelCall(EVENT_GROUP_CREATE, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg));\r
+\r
+#undef traceEVENT_GROUP_DELETE\r
+#define traceEVENT_GROUP_DELETE(eg) \\r
+       vTraceStoreKernelCall(EVENT_GROUP_DELETE, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg)); \\r
+       vTraceStoreObjectNameOnCloseEvent(TRACE_GET_EVENTGROUP_NUMBER(eg), TRACE_CLASS_EVENTGROUP); \\r
+       vTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_EVENTGROUP_NUMBER(eg), TRACE_CLASS_EVENTGROUP); \\r
+       vTraceFreeObjectHandle(TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg));\r
+\r
+#undef traceEVENT_GROUP_CREATE_FAILED\r
+#define traceEVENT_GROUP_CREATE_FAILED() \\r
+       vTraceStoreKernelCall(EVENT_GROUP_CREATE_FAILED, TRACE_CLASS_EVENTGROUP, 0);\r
+\r
+#undef traceEVENT_GROUP_SYNC_BLOCK\r
+#define traceEVENT_GROUP_SYNC_BLOCK(eg, bitsToSet, bitsToWaitFor) \\r
+       vTraceStoreKernelCallWithParam(EVENT_GROUP_SYNC_BLOCK, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor);\r
+\r
+#undef traceEVENT_GROUP_SYNC_END\r
+#define traceEVENT_GROUP_SYNC_END(eg, bitsToSet, bitsToWaitFor, wasTimeout) \\r
+       if (wasTimeout){ vTraceStoreKernelCallWithParam(EVENT_GROUP_SYNC_END_FAILED, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor);} \\r
+       else{ vTraceStoreKernelCallWithParam(EVENT_GROUP_SYNC_END, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); }\r
+\r
+#undef traceEVENT_GROUP_WAIT_BITS_BLOCK\r
+#define traceEVENT_GROUP_WAIT_BITS_BLOCK(eg, bitsToWaitFor) \\r
+       vTraceStoreKernelCallWithParam(EVENT_GROUP_WAIT_BITS_BLOCK, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); \\r
+       trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();\r
+\r
+#undef traceEVENT_GROUP_WAIT_BITS_END\r
+#define traceEVENT_GROUP_WAIT_BITS_END(eg, bitsToWaitFor, wasTimeout) \\r
+       if (wasTimeout){ vTraceStoreKernelCallWithParam(EVENT_GROUP_WAIT_BITS_END_FAILED, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); } \\r
+       else{ vTraceStoreKernelCallWithParam(EVENT_GROUP_WAIT_BITS_END, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); }\r
+       \r
+#undef traceEVENT_GROUP_CLEAR_BITS\r
+#define traceEVENT_GROUP_CLEAR_BITS(eg, bitsToClear) \\r
+       if (bitsToClear) vTraceStoreKernelCallWithParam(EVENT_GROUP_CLEAR_BITS, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToClear);\r
+\r
+#undef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR\r
+#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(eg, bitsToClear) \\r
+       if (bitsToClear) vTraceStoreKernelCallWithParam(EVENT_GROUP_CLEAR_BITS_FROM_ISR, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToClear);\r
+\r
+#undef traceEVENT_GROUP_SET_BITS\r
+#define traceEVENT_GROUP_SET_BITS(eg, bitsToSet) \\r
+       vTraceStoreKernelCallWithParam(EVENT_GROUP_SET_BITS, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToSet);\r
+\r
+#undef traceEVENT_GROUP_SET_BITS_FROM_ISR\r
+#define traceEVENT_GROUP_SET_BITS_FROM_ISR(eg, bitsToSet) \\r
+       vTraceStoreKernelCallWithParam(EVENT_GROUP_SET_BITS_FROM_ISR, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToSet); \\r
+       uiInEventGroupSetBitsFromISR = 1;\r
+       \r
+#if (INCLUDE_MEMMANG_EVENTS == 1)\r
+\r
+extern void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, uint32_t size);\r
+\r
+#undef traceMALLOC\r
+#define traceMALLOC( pvAddress, uiSize ) {vTraceStoreMemMangEvent(MEM_MALLOC_SIZE, ( uint32_t ) pvAddress, uiSize); TRACE_UPDATE_HEAP_USAGE_POSITIVE(uiSize);}\r
+\r
+       \r
+#undef traceFREE\r
+#define traceFREE( pvAddress, uiSize ) {vTraceStoreMemMangEvent(MEM_FREE_SIZE, ( uint32_t ) pvAddress, uiSize); TRACE_UPDATE_HEAP_USAGE_NEGATIVE(uiSize);}\r
+\r
+#endif\r
 \r
 /************************************************************************/\r
 /* KERNEL SPECIFIC MACROS TO EXCLUDE OR INCLUDE THINGS IN TRACE         */\r
@@ -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)\r
 #define TRACE_GET_TASK_FLAG_ISEXCLUDED(taskIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+taskIndex)\r
 \r
+#define TRACE_SET_TIMER_FLAG_ISEXCLUDED(timerIndex) TRACE_SET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+timerIndex)\r
+#define TRACE_CLEAR_TIMER_FLAG_ISEXCLUDED(timerIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+timerIndex)\r
+#define TRACE_GET_TIMER_FLAG_ISEXCLUDED(timerIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+timerIndex)\r
+\r
+#define TRACE_SET_EVENTGROUP_FLAG_ISEXCLUDED(egIndex) TRACE_SET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+NTimer+1+egIndex)\r
+#define TRACE_CLEAR_EVENTGROUP_FLAG_ISEXCLUDED(egIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+NTimer+1+egIndex)\r
+#define TRACE_GET_EVENTGROUP_FLAG_ISEXCLUDED(egIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+NTimer+1+egIndex)\r
+\r
+\r
 #define TRACE_CLEAR_OBJECT_FLAG_ISEXCLUDED(objectclass, handle) \\r
 switch (objectclass) \\r
 { \\r
@@ -630,6 +801,12 @@ case TRACE_CLASS_MUTEX: \
 case TRACE_CLASS_TASK: \\r
        TRACE_CLEAR_TASK_FLAG_ISEXCLUDED(handle); \\r
        break; \\r
+case TRACE_CLASS_TIMER: \\r
+       TRACE_CLEAR_TIMER_FLAG_ISEXCLUDED(handle); \\r
+       break; \\r
+case TRACE_CLASS_EVENTGROUP: \\r
+       TRACE_CLEAR_EVENTGROUP_FLAG_ISEXCLUDED(handle); \\r
+       break; \\r
 }\r
 \r
 #define TRACE_SET_OBJECT_FLAG_ISEXCLUDED(objectclass, handle) \\r
@@ -647,6 +824,12 @@ case TRACE_CLASS_MUTEX: \
 case TRACE_CLASS_TASK: \\r
        TRACE_SET_TASK_FLAG_ISEXCLUDED(handle); \\r
        break; \\r
+case TRACE_CLASS_TIMER: \\r
+       TRACE_SET_TIMER_FLAG_ISEXCLUDED(handle); \\r
+       break; \\r
+case TRACE_CLASS_EVENTGROUP: \\r
+       TRACE_SET_EVENTGROUP_FLAG_ISEXCLUDED(handle); \\r
+       break; \\r
 }\r
 \r
 /* Task */\r
@@ -680,6 +863,20 @@ TRACE_SET_MUTEX_FLAG_ISEXCLUDED(TRACE_GET_OBJECT_NUMBER(UNUSED, handle));
 #define vTraceIncludeMutexInTrace(handle) \\r
 TRACE_CLEAR_QUEUE_FLAG_ISEXCLUDED(TRACE_GET_OBJECT_NUMBER(UNUSED, handle));\r
 \r
+/* Timer */\r
+#define vTraceExcludeTimerFromTrace(handle) \\r
+TRACE_SET_TIMER_FLAG_ISEXCLUDED(TRACE_GET_TIMER_NUMBER(handle));\r
+\r
+#define vTraceIncludeTimerInTrace(handle) \\r
+TRACE_CLEAR_QUEUE_FLAG_ISEXCLUDED(TRACE_GET_TIMER_NUMBER(handle));\r
+\r
+/* Event Group */\r
+#define vTraceExcludeEventGroupFromTrace(handle) \\r
+TRACE_SET_EVENTGROUP_FLAG_ISEXCLUDED(TRACE_GET_EVENTGROUP_NUMBER(handle));\r
+\r
+#define vTraceIncludeEventGroupInTrace(handle) \\r
+TRACE_CLEAR_EVENTGROUP_FLAG_ISEXCLUDED(TRACE_GET_EVENTGROUP_NUMBER(handle));\r
+\r
 \r
 /* Kernel Services */\r
 #define vTraceExcludeKernelServiceDelayFromTrace() \\r
@@ -770,6 +967,11 @@ vTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, object), TRACE_GET_OBJE
 #define vTraceSetMutexName(object, name) \\r
 vTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, object), TRACE_GET_OBJECT_NUMBER(UNUSED, object), name);\r
 \r
+#define vTraceSetEventGroupName(object, name) \\r
+vTraceSetObjectName(TRACE_CLASS_EVENTGROUP, uxEventGroupGetNumber(object), name);\r
+\r
+#undef traceQUEUE_REGISTRY_ADD\r
+#define traceQUEUE_REGISTRY_ADD(object, name) vTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, object), TRACE_GET_OBJECT_NUMBER(UNUSED, object), name);\r
 #endif\r
 \r
 #endif /* TRCKERNELPORT_H_ */
\ No newline at end of file
index e60b34ab9fc4870be8c895c47faebc163efd012e..f1d434a98f49bcf6aac534e6617dd51b28b9a58f 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcTypes.h\r
 #define TRCTYPES_H\r
 \r
 #include <stdint.h>\r
+#include <trcConfig.h>\r
 \r
 typedef uint16_t traceLabel;\r
 \r
 typedef uint8_t UserEventChannel;\r
 \r
+#if (USE_16BIT_OBJECT_HANDLES == 1)\r
+typedef uint16_t objectHandleType;\r
+#else\r
 typedef uint8_t objectHandleType;\r
+#endif\r
 \r
 typedef uint8_t traceObjectClass;\r
 \r
index c6904008b03ae30360b4041dd908219cf5df1358..dba4432e6fecff356240f3ecc7ea09e3b046e57f 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcUser.h\r
@@ -421,6 +421,12 @@ void vTraceChannelUserEvent(UserEventChannel channel);
 #define vTraceSetISRProperties(handle, name, priority)\r
 #define vTraceStoreISRBegin(id)\r
 #define vTraceStoreISREnd()\r
+#define vTraceExcludeTaskFromTrace(handle)\r
+#define vTraceSetQueueName(a, b)\r
+#define vTraceSetMutexName(a, b)\r
+#define vTraceSetSemaphoreName(a, b)\r
+#define vTraceSetEventGroupName(a, b)\r
+\r
 #endif\r
 \r
 #ifdef __cplusplus\r
index f815e8b21858f9885b47ac740e9b0a1e5aa6d361..bb25213fdc6d3f512b318616a5787e0d1f964feb 100644 (file)
@@ -1,7 +1,7 @@
 \r
 Tracealyzer - Uploading the trace data\r
 -----------------------------------------\r
-Percepio AB, Nov. 8, 2012\r
+Percepio AB, Jan. 23, 2014\r
 \r
 This document decribes how to upload the trace data from the target system to\r
 Tracealyzer. \r
@@ -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 \r
 probe on the market.\r
 \r
-If the device has a file system and some possibility of accessing this file \r
-system from the development PC, it is also possible to write the recorder data\r
-to a file, using vTraceGetTraceBuffer() and uiTraceGetTraceBufferSize() \r
-found in trcUser.h/.c.\r
-\r
-Note that hardware-generated trace is not required (or used by) Tracealyzer. \r
-We however plan to add support for that in future versions of Tracealyzer \r
-and other Tracealyzer products.\r
-\r
 Built-in support for Segger J-Link/J-Trace and Atmel SAM-ICE\r
 ------------------------------------------------------------\r
 Tracealyzer v2.3 supports Segger J-Link and J-Link compatible debuggers \r
@@ -27,9 +18,8 @@ directly, without any debugger IDE involved. Using other debug probes is
 also possible, but requires some extra steps, described below.\r
 \r
 If you have a Segger J-Link/J-Trace debug probe or another J-Link compatible \r
-debug probe, just select \r
-\r
-    "File" menu -> "Upload from <debug probe name>". \r
+debug probe, just select "Read Trace" in the "J-Link" menu. Note that this \r
+menu is only available if a compatible debug probe is found.\r
 \r
 This opens a dialog where you get to enter the memory region where\r
 the recorder data structure is located. Normally you select the entire \r
@@ -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 \r
 "RecorderDataPtr" pointer with your debugger.\r
 \r
-Typical values are 0x0, 0x10000000 or 0x20000000 as start address\r
-and 0x10000 or 0x20000 as size (64 KB or 128 KB).\r
-\r
-This makes Tracealyzer reads the chip RAM and locate the trace data. \r
-Note that this option is only available if a compatible debug probe is found.\r
-\r
 J-Link compatible debug probes also include Atmel SAM-ICE and many built-in \r
 debug interfaces on demonstration/evaluation boards (where there is a USB \r
 connection directly to the board). Look for a Segger J-Link label on the board.\r
 \r
 MemoryLogger extension in Atmel Studio 6\r
 ----------------------------------------\r
-Atmel's new MemoryLogger extension provides a superb integration with\r
-Tracealyzer. Look for "MemoryLogger" in Atmel Gallery, available in \r
-Atmel Studio and at the Atmel website.\r
+Atmel's MemoryLogger extension provides a superb integration with FreeRTOS+Trace. \r
+Look for "MemoryLogger" in Atmel Gallery, available in Atmel Studio and at the \r
+Atmel website (http://gallery.atmel.com).\r
 \r
-This extension automatically detects the path to Tracealyzer, if \r
+This extension automatically detects the path to FreeRTOS+Trace, if \r
 installed, and gives you a single-click upload/refresh. You can use it \r
 while debugging and optionally get an automatic refresh eash time the \r
 MCU is halted, e.g., on each breakpoint.\r
index 883f85ebb8916f54da93da12e1f437b3d9749d3e..2c6c551955626362e69aa9c6ce65c06e6c8b4bf4 100644 (file)
@@ -4,38 +4,45 @@ Tracealyzer Trace Recorder Library
 Percepio AB\r
 www.percepio.com\r
 \r
-This directory contains the a generic trace recorder library for Tracealyzer v2.5\r
+This directory contains the a generic trace recorder library for Tracealyzer v2.6\r
 \r
 For information on how to upload the trace data from your target system RAM to \r
 Tracealyzer, see "debugger trace upload.txt"\r
 \r
 Files included\r
 --------------\r
-- trcConfig.h               - The recorder's configuration file, check this!\r
-- trcUser.c / trcUser.h     - The main API towards the application (trcUser.h in the only include necessary).\r
-- trcKernel.c / trcKernel.h - Internal routines for storing kernel events.\r
-- trcBase.c / trcBase.h     - Internal routines for manipulating the data structures and calculating timestamps.\r
-- trcHardwarePort.c / trcHardwarePort.h     - The port layer, abstracting the hardware (mainly the timer used for timestamping).\r
-- trcKernelHooks.h                             - The interface between the Kernel and the recorder, containing trace macro defintions.\r
-- trcKernelPort.h                              - Kernel specific implementations of macros and data.\r
-- trcTypes.h                           - Type definitions used.\r
+- trcConfig.h             - The recorder's configuration file, set your recorder configuration here!\r
+- trcUser.c/.h            - The main API towards the application (trcUser.h in the only include necessary).\r
+- trcKernel.c/.h          - Internal routines for storing kernel events.\r
+- trcBase.c/.h            - Internal routines for manipulating the data structures and calculating timestamps.\r
+- trcHardwarePort.c/.h    - The hardware interface, especially for timestamping.\r
+- trcKernelPort.c/.h      - Kernel specific implementations of macros and data.\r
+- trcKernelHooks.h        - The trace macro defines (OS independent).\r
+- trcTypes.h              - Type definitions used.\r
 \r
 Hardware Timer Ports\r
 --------------------\r
 This release contains hardware timer ports for the following hardware architectures:\r
 \r
-- ARM Cortex M3/M4 (all brands, such as Atmel SAM3/SAM4, NXP 17xx, 18xx, 43xx, STM32, Freescale Kinetis, ...)\r
+- ARM Cortex M3/M4/M0/M0+ (all brands, such as Atmel SAM3x/SAM4x/SAM D20, NXP 17xx, 18xx, 43xx, STM32, Freescale Kinetis, ...)\r
 - Atmel AT91SAM7x\r
 - Atmel AT32UC3 (AVR32)\r
 - Renesas RX600 (e.g., RX62N)\r
 - Microchip dsPIC/PIC24\r
-\r
-These are defined in trcPort.h. This also contains several "unofficial" ports, provided by external contributors.\r
-By unofficial, it means that they are not yet verified by Percepio AB. Please refer to trcPort.h for detailed information. \r
-If you use an unofficial port and beleive it is incorrect, please let us know!\r
+- Microchip PIC32\r
+- NXP LPC2106\r
+- Texas Instruments TMS570 (Cortex-R4)\r
+- Texas Instruments MSP430\r
+- Xilinx PowerPC 405\r
+- Xilinx PowerPC 440\r
+- Xilinx Microblaze\r
+\r
+These are defined in trcHardwarePort.h. Some of these are "unofficial" ports, provided by external contributors.\r
+By unofficial, it means that they are not yet verified by Percepio AB. Please refer to trcHardwarePort.h for detailed information. \r
+If you use an unofficial port and beleive it is incorrect, please let us know! (support@percepio.com)\r
 \r
 In case your MCU is not yet supported directly, developing a new port is quite easy, just a matter of defining a few macros\r
-according to your specific MCU. See trcPort.h for further information.\r
+according to your specific MCU. See trcHardwarePort.h for further information.\r
 \r
 In case you have any questions, do not hesitate to contact support@percepio.com\r
 \r
index bfd6cb28c3eadb77083e5a89eaf30f8b553a8d5e..be5f935308839f458fd6570c9d5988f59d382cd3 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcBase.c\r
@@ -113,6 +113,7 @@ void prvTraceInitTraceData()
        /* DO NOTHING */\r
 #endif\r
 \r
+\r
        TRACE_ASSERT(RecorderDataPtr != NULL, "prvTraceInitTraceData, RecorderDataPtr == NULL", );\r
 \r
     if (! RecorderDataPtr)\r
@@ -120,7 +121,7 @@ void prvTraceInitTraceData()
         vTraceError("No recorder data structure allocated!");\r
         return;\r
     }\r
-\r
+               \r
     (void)memset(RecorderDataPtr, 0, sizeof(RecorderDataType));\r
 \r
     RecorderDataPtr->startmarker0 = 0x00;\r
@@ -145,6 +146,8 @@ void prvTraceInitTraceData()
 \r
     RecorderDataPtr->debugMarker0 = 0xF0F0F0F0;\r
 \r
+       RecorderDataPtr->isUsing16bitHandles = USE_16BIT_OBJECT_HANDLES;\r
+\r
        /* This function is kernel specific */\r
        vTraceInitObjectPropertyTable();\r
 \r
@@ -182,6 +185,10 @@ void prvTraceInitTraceData()
 \r
        /* Fix the start markers of the trace data structure */\r
        vInitStartMarkers();\r
+       \r
+       #ifdef PORT_SPECIFIC_INIT\r
+       PORT_SPECIFIC_INIT();\r
+       #endif\r
 }\r
 \r
 static void vInitStartMarkers()\r
@@ -255,7 +262,7 @@ uint16_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass)
 \r
 objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass)\r
 {\r
-    static objectHandleType handle;\r
+    objectHandleType handle;\r
     static int indexOfHandle;\r
 \r
        TRACE_ASSERT(objectclass < TRACE_NCLASSES, "xTraceGetObjectHandle: Invalid value for objectclass", (objectHandleType)0);\r
@@ -314,7 +321,7 @@ void vTraceFreeObjectHandle(traceObjectClass objectclass, objectHandleType handl
         objectHandleStacks.lowestIndexOfClass[objectclass])\r
     {\r
         /* Error */\r
-        vTraceError("Attempt to free more handles than allocated! (duplicate xTaskDelete or xQueueDelete?)");\r
+        vTraceError("Attempt to free more handles than allocated!");\r
     }\r
     else\r
     {\r
@@ -389,8 +396,11 @@ traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel)
     uint16_t result;\r
     uint8_t len;\r
     uint8_t crc;\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+       \r
     len = 0;\r
     crc = 0;\r
+    \r
 \r
     TRACE_ASSERT(name != NULL, "prvTraceOpenSymbol: name == NULL", (traceLabel)0);\r
 \r
@@ -411,8 +421,6 @@ traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel)
  * Supporting functions\r
  ******************************************************************************/\r
 \r
-extern volatile uint32_t rtest_error_flag;\r
-\r
 /*******************************************************************************\r
  * vTraceError\r
  *\r
@@ -430,8 +438,8 @@ void vTraceError(const char* msg)
        TRACE_ASSERT(msg != NULL, "vTraceError: msg == NULL", );\r
        TRACE_ASSERT(RecorderDataPtr != NULL, "vTraceError: RecorderDataPtr == NULL", );\r
 \r
-       // Stop the recorder. Note: We do not call vTraceStop, since that adds a weird\r
-       // and unnecessary dependency to trcUser.c.\r
+       /* Stop the recorder. Note: We do not call vTraceStop, since that adds a weird\r
+       and unnecessary dependency to trcUser.c */\r
 \r
        RecorderDataPtr->recorderActive = 0;\r
 \r
@@ -503,12 +511,12 @@ void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nofEntriesToCheck)
  * Updates the index of the event buffer.\r
  ******************************************************************************/\r
 void prvTraceUpdateCounters(void)\r
-{\r
-    if (RecorderDataPtr->recorderActive == 0)\r
+{      \r
+       if (RecorderDataPtr->recorderActive == 0)\r
     {\r
         return;\r
     }\r
-\r
+       \r
     RecorderDataPtr->numEvents++;\r
 \r
     RecorderDataPtr->nextFreeIndex++;\r
@@ -556,13 +564,17 @@ uint16_t prvTraceGetDTS(uint16_t param_maxDTS)
 \r
     TRACE_ASSERT(param_maxDTS == 0xFF || param_maxDTS == 0xFFFF, "prvTraceGetDTS: Invalid value for param_maxDTS", 0);\r
 \r
+#if (SELECTED_PORT != PORT_ARM_CortexM)\r
+\r
     if (RecorderDataPtr->frequency == 0 && init_hwtc_count != HWTC_COUNT)\r
     {\r
         /* If HWTC_PERIOD is mapped to the timer reload register,\r
-        such as in the Cortex M port, it might not be initialized\r
-               before the Kernel scheduler has been started has been\r
-               started. We therefore store the frequency of the timer\r
-               once the counter register has changed. */\r
+        it might not be initialized    before the scheduler has been started. \r
+               We therefore store the frequency of the timer when the counter\r
+               register has changed from its initial value. \r
+               (Note that this function is called also by vTraceStart and\r
+               uiTraceStart, which might be called before the scheduler\r
+               has been started.) */\r
 \r
 #if (SELECTED_PORT == PORT_Win32)\r
         RecorderDataPtr->frequency = 100000;\r
@@ -572,15 +584,15 @@ uint16_t prvTraceGetDTS(uint16_t param_maxDTS)
                RecorderDataPtr->frequency = (HWTC_PERIOD * TRACE_TICK_RATE_HZ) / (uint32_t)HWTC_DIVISOR;\r
 #endif\r
     }\r
-\r
+#endif\r
     /**************************************************************************\r
     * The below statements read the timestamp from the timer port module.\r
     * If necessary, whole seconds are extracted using division while the rest\r
     * comes from the modulo operation.\r
     **************************************************************************/\r
-\r
-    vTracePortGetTimeStamp(&timestamp);\r
-\r
+    \r
+    vTracePortGetTimeStamp(&timestamp);    \r
+    \r
     /***************************************************************************\r
     * Since dts is unsigned the result will be correct even if timestamp has\r
        * wrapped around.\r
@@ -770,7 +782,7 @@ uint16_t prvTraceCreateSymbolTableEntry(const char* name,
 void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength)\r
 {\r
    unsigned char c;\r
-   int length = 0;\r
+   int length = 1;\r
    int crc = 0;\r
 \r
    TRACE_ASSERT(pname != NULL, "prvTraceGetChecksum: pname == NULL", );\r
@@ -789,4 +801,52 @@ void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength)
    *plength = (uint8_t)length;\r
 }\r
 \r
-#endif
\ No newline at end of file
+#if (USE_16BIT_OBJECT_HANDLES == 1)\r
+\r
+void prvTraceStoreXID(objectHandleType handle); \r
+\r
+/******************************************************************************\r
+ * prvTraceStoreXID\r
+ *\r
+ * Stores an XID (eXtended IDentifier) event.\r
+ * This is used if an object/task handle is larger than 255.\r
+ * The parameter "handle" is the full (16 bit) handle, assumed to be 256 or \r
+ * larger. Handles below 256 should not use this function.\r
+ *\r
+ * NOTE: this function MUST be called from within a critical section.\r
+ *****************************************************************************/\r
+\r
+void prvTraceStoreXID(objectHandleType handle)\r
+{\r
+       XPSEvent* xid;\r
+\r
+       TRACE_ASSERT(handle >= 256, "prvTraceStoreXID: Handle < 256", );\r
+\r
+       xid = (XPSEvent*)xTraceNextFreeEventBufferSlot();\r
+\r
+       if (xid != NULL)\r
+       {\r
+               xid->type = XID;\r
+\r
+               /* This function is (only) used when objectHandleType is 16 bit... */\r
+               xid->xps_16 = handle;  \r
+\r
+               prvTraceUpdateCounters();\r
+       }\r
+}\r
+\r
+unsigned char prvTraceGet8BitHandle(objectHandleType handle)\r
+{\r
+       if (handle > 255)\r
+       {               \r
+               prvTraceStoreXID(handle);\r
+        /* The full handle (16 bit) is stored in the XID event. \r
+           This code (255) is used instead of zero (which is an error code).*/\r
+               return 255; \r
+       }\r
+       return (unsigned char)(handle & 0xFF);\r
+}\r
+\r
+#endif\r
+\r
+#endif\r
index 6570e3553fcc28182b797cc0b52ebed6f7e1ccc0..ac4a6f263b6159c99edbb8e3897cd8b04fb7a283 100644 (file)
@@ -1,5 +1,5 @@
 /******************************************************************************* \r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcHardwarePort.c\r
@@ -37,6 +37,7 @@
  ******************************************************************************/\r
 \r
 #include "trcHardwarePort.h"\r
+#include "trcKernelPort.h"\r
 \r
 #if (USE_TRACEALYZER_RECORDER == 1)\r
 \r
@@ -55,6 +56,45 @@ uint32_t last_timestamp = 0;
  ******************************************************************************/\r
 uint32_t uiTraceTickCount = 0;\r
 \r
+uint32_t DWT_CYCLES_ADDED = 0;\r
+\r
+#if (SELECTED_PORT == PORT_ARM_CortexM)\r
+\r
+void prvTraceEnableIRQ(void)\r
+{\r
+       asm volatile ("cpsie i");\r
+}\r
+\r
+void prvTraceDisableIRQ(void)\r
+{\r
+       asm volatile ("cpsid i");\r
+}\r
+\r
+void prvTraceSetIRQMask(uint32_t priMask)\r
+{\r
+       asm volatile ("MSR primask, %0" : : "r" (priMask) );\r
+}\r
+\r
+uint32_t prvTraceGetIRQMask(void)\r
+{\r
+       uint32_t result;\r
+       asm volatile ("MRS %0, primask" : "=r" (result) );\r
+       return result;\r
+}\r
+\r
+void prvTraceInitCortexM()\r
+{\r
+       DWT_CTRL_REG |= 1;     /* Enable the cycle counter */\r
+       DWT_CYCLE_COUNTER = 0;\r
+       \r
+       if (RecorderDataPtr->frequency == 0)\r
+       {               \r
+               RecorderDataPtr->frequency = TRACE_CPU_CLOCK_HZ / HWTC_DIVISOR;\r
+       }\r
+}\r
+\r
+#endif\r
+\r
 /******************************************************************************\r
  * vTracePortGetTimeStamp\r
  *\r
index 0b1770867667bb33eb573c34005226064bdb04f8..e79294740e00ee35e7a018ba0dc0521dc0334cd5 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcKernel.c\r
@@ -58,6 +58,7 @@ void vTraceStoreTaskReady(objectHandleType handle)
 {\r
     uint16_t dts3;\r
     TREvent* tr;\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
        \r
        TRACE_ASSERT(handle > 0 && handle <= NTask, "vTraceStoreTaskReady: Invalid value for handle", );\r
 \r
@@ -73,6 +74,7 @@ void vTraceStoreTaskReady(objectHandleType handle)
       return;\r
     }\r
 \r
+       trcCRITICAL_SECTION_BEGIN();\r
     if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
        {\r
                if (!TRACE_GET_TASK_FLAG_ISEXCLUDED(handle))\r
@@ -80,19 +82,22 @@ void vTraceStoreTaskReady(objectHandleType handle)
                        dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
                        if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
                        {\r
+                               uint8_t hnd8 = prvTraceGet8BitHandle(handle);\r
+\r
                                tr = (TREvent*)xTraceNextFreeEventBufferSlot();\r
 \r
                                if (tr != NULL)\r
                                {\r
                                        tr->type = DIV_TASK_READY;\r
                                        tr->dts = dts3;\r
-                                       tr->objHandle = handle;\r
+                                       tr->objHandle = hnd8;\r
 \r
                                        prvTraceUpdateCounters();\r
                                }\r
                        }\r
                }\r
        }\r
+       trcCRITICAL_SECTION_END();\r
 }\r
 #endif\r
 \r
@@ -105,6 +110,7 @@ void vTraceStoreLowPower(uint32_t flag)
 {\r
     uint16_t dts;\r
     LPEvent* lp;\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
        \r
        TRACE_ASSERT(flag <= 1, "vTraceStoreLowPower: Invalid flag value", );\r
 \r
@@ -119,7 +125,8 @@ void vTraceStoreLowPower(uint32_t flag)
                vTraceError("Recorder busy - high priority ISR using syscall? (1)");\r
                return;\r
     }\r
-\r
+       \r
+       trcCRITICAL_SECTION_BEGIN();\r
     if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
        {\r
                dts = (uint16_t)prvTraceGetDTS(0xFFFF);\r
@@ -135,8 +142,72 @@ void vTraceStoreLowPower(uint32_t flag)
                        }\r
                }\r
        }\r
+       trcCRITICAL_SECTION_END();\r
 }\r
 \r
+/*******************************************************************************\r
+ * vTraceStoreMemMangEvent\r
+ *\r
+ * This function stores malloc and free events. Each call requires two records,\r
+ * for size and address respectively. The event code parameter (ecode) is applied \r
+ * to the first record (size) and the following address record gets event \r
+ * code "ecode + 1", so make sure this is respected in the event code table.\r
+ ******************************************************************************/\r
+#if (INCLUDE_MEMMANG_EVENTS == 1)\r
+void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, uint32_t size)\r
+{\r
+       uint8_t dts1;\r
+       MemEventSize * ms;\r
+       MemEventAddr * ma;\r
+       uint16_t size_low;\r
+       uint16_t addr_low;\r
+       uint8_t addr_high;\r
+       \r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+\r
+       trcCRITICAL_SECTION_BEGIN();\r
+       if (RecorderDataPtr->recorderActive)\r
+       {\r
+               /* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */\r
+               if (nISRactive || !inExcludedTask)\r
+               {\r
+                       dts1 = (uint8_t)prvTraceGetDTS(0xFF);\r
+                       \r
+                       size_low = (uint16_t)prvTraceGetParam(0xFFFF, size);\r
+                       \r
+                       ms = (MemEventSize *)xTraceNextFreeEventBufferSlot();\r
+                       if (ms != NULL)\r
+                       {\r
+                               ms->dts = dts1;\r
+                               ms->type = (uint8_t)ecode;\r
+                               ms->size = size_low;\r
+                               prvTraceUpdateCounters();\r
+                               \r
+                               /* Storing a second record with address (signals "failed" if null) */\r
+                               #if (HEAP_SIZE_BELOW_16M)\r
+                                       addr_low = address & 0xFFFF;\r
+                                       addr_high = (address >> 16) & 0xFF;\r
+                               #else\r
+                                       addr_low = (uint16_t)prvTraceGetParam(0xFFFF, address);\r
+                                       addr_high = 0;\r
+                               #endif\r
+                               \r
+                               ma = (MemEventAddr *) xTraceNextFreeEventBufferSlot();\r
+                               \r
+                               if (ma != NULL)\r
+                               {\r
+                                       ma->addr_low = addr_low;\r
+                                       ma->addr_high = addr_high;\r
+                                       ma->type = ( ( uint8_t) ecode ) + 1;  /* Note this! */\r
+                                       prvTraceUpdateCounters();                               \r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       trcCRITICAL_SECTION_END();      \r
+}\r
+#endif\r
+\r
 /*******************************************************************************\r
  * vTraceStoreKernelCall\r
  *\r
@@ -147,7 +218,8 @@ void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_
 {\r
     KernelCall * kse;\r
     uint16_t dts1;\r
-       \r
+    TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+\r
     TRACE_ASSERT(ecode < 0xFF, "vTraceStoreKernelCall: ecode >= 0xFF", );\r
     TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCall: objectClass >= TRACE_NCLASSES", );\r
     TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCall: Invalid value for objectNumber", );\r
@@ -170,96 +242,106 @@ void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_
         return;\r
     }\r
 \r
+       trcCRITICAL_SECTION_BEGIN();\r
     if (RecorderDataPtr->recorderActive)\r
     {\r
-\r
         /* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */\r
         if (nISRactive || !inExcludedTask)\r
         {\r
             /* Check if the referenced object or the event code is excluded */\r
             if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))\r
-            {\r
-                trcCRITICAL_SECTION_BEGIN();\r
+            {                \r
                 dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
 \r
                 if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
                 {\r
+                                       uint8_t hnd8 = prvTraceGet8BitHandle(objectNumber);\r
+\r
                     kse = (KernelCall*) xTraceNextFreeEventBufferSlot();\r
                     if (kse != NULL)\r
                     {\r
                         kse->dts = dts1;\r
                         kse->type = (uint8_t)ecode;\r
-                        kse->objHandle = (uint8_t)objectNumber;\r
+                        kse->objHandle = hnd8;\r
                         prvTraceUpdateCounters();\r
                     }\r
-                }\r
-                trcCRITICAL_SECTION_END();\r
+                }                \r
             }\r
         }\r
     }\r
+       trcCRITICAL_SECTION_END();\r
 }\r
 \r
 /*******************************************************************************\r
  * vTraceStoreKernelCallWithParam\r
  *\r
- * Used for storing kernel calls with a handle and a numeric parameter. This is\r
- * only used for traceTASK_PRIORITY_SET at the moment.\r
+ * Used for storing kernel calls with a handle and a numeric parameter. If the \r
+ * numeric parameter does not fit in one byte, and extra XPS event is inserted\r
+ * before the kernel call event containing the three upper bytes.\r
  ******************************************************************************/\r
 void vTraceStoreKernelCallWithParam(uint32_t evtcode,\r
                                     traceObjectClass objectClass,\r
                                     uint32_t objectNumber,\r
-                                    uint8_t param)\r
+                                    uint32_t param)\r
 {\r
     KernelCallWithParamAndHandle * kse;\r
-    uint8_t dts2;\r
+    uint8_t dts2;      \r
+    TRACE_SR_ALLOC_CRITICAL_SECTION();\r
 \r
        TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCall: evtcode >= 0xFF", );\r
        TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCallWithParam: objectClass >= TRACE_NCLASSES", );\r
        TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCallWithParam: Invalid value for objectNumber", );\r
 \r
+       if (recorder_busy)\r
+    {\r
+        /*************************************************************************\r
+        * This may occur if a high-priority ISR is illegally using a system call,\r
+        * or creates a user event.\r
+        * Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls\r
+        * or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).\r
+        *************************************************************************/\r
+\r
+        vTraceError("Recorder busy - high priority ISR using syscall? (3)");\r
+        return;\r
+    }\r
+\r
+       trcCRITICAL_SECTION_BEGIN();\r
     if (RecorderDataPtr->recorderActive && handle_of_last_logged_task &&\r
         (! inExcludedTask || nISRactive))\r
     {\r
-        if (recorder_busy)\r
-        {\r
-            /*************************************************************************\r
-            * This may occur if a high-priority ISR is illegally using a system call,\r
-            * or creates a user event.\r
-            * Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls\r
-               * or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).\r
-            *************************************************************************/\r
-\r
-            vTraceError("Recorder busy - high priority ISR using syscall? (3)");\r
-            return;\r
-        }\r
-\r
+        \r
         /* Check if the referenced object or the event code is excluded */\r
         if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))\r
-        {\r
-            trcCRITICAL_SECTION_BEGIN();\r
+        {            \r
             dts2 = (uint8_t)prvTraceGetDTS(0xFF);\r
 \r
             if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
             {\r
+                               uint8_t p8 = (uint8_t) prvTraceGetParam(0xFF, param);\r
+                               \r
+                               uint8_t hnd8 = prvTraceGet8BitHandle((objectHandleType)objectNumber);\r
+\r
                 kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot();\r
                 if (kse != NULL)\r
                 {\r
                     kse->dts = dts2;\r
                     kse->type = (uint8_t)evtcode;\r
-                    kse->objHandle = (uint8_t)objectNumber;\r
-                    kse->param = param;\r
+                    kse->objHandle = hnd8; \r
+                    kse->param = p8;\r
                     prvTraceUpdateCounters();\r
                 }\r
-            }\r
-            trcCRITICAL_SECTION_END();\r
+            }            \r
         }\r
     }\r
+       trcCRITICAL_SECTION_END();\r
 }\r
 \r
 /*******************************************************************************\r
  * prvTraceGetParam\r
  *\r
  * Used for storing extra bytes for kernel calls with numeric parameters.\r
+ *\r
+ * May only be called within a critical section!\r
  ******************************************************************************/\r
 static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)\r
 {\r
@@ -296,30 +378,33 @@ void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
 {\r
     KernelCallWithParam16 * kse;\r
     uint8_t dts6;\r
-       uint16_t restParam = 0;\r
+       uint16_t restParam;\r
+    TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+\r
+       restParam = 0;\r
 \r
        TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCallWithNumericParamOnly: Invalid value for evtcode", );\r
        \r
+       if (recorder_busy)\r
+    {\r
+        /*************************************************************************\r
+        * This may occur if a high-priority ISR is illegally using a system call,\r
+        * or creates a user event.\r
+        * Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls\r
+        * or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).\r
+        *************************************************************************/\r
+\r
+        vTraceError("Recorder busy - high priority ISR using syscall? (4)");\r
+        return;\r
+    }\r
+       \r
+       trcCRITICAL_SECTION_BEGIN();\r
     if (RecorderDataPtr->recorderActive && handle_of_last_logged_task\r
         && (! inExcludedTask || nISRactive))\r
     {\r
         /* Check if the event code is excluded */\r
         if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))\r
-        {\r
-            if (recorder_busy)\r
-            {\r
-                /*************************************************************************\r
-                * This may occur if a high-priority ISR is illegally using a system call,\r
-                * or creates a user event.\r
-                * Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls\r
-                * or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).\r
-                *************************************************************************/\r
-\r
-                vTraceError("Recorder busy - high priority ISR using syscall? (4)");\r
-                return;\r
-            }\r
-\r
-            trcCRITICAL_SECTION_BEGIN();\r
+        {            \r
             dts6 = (uint8_t)prvTraceGetDTS(0xFF);\r
 \r
             if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
@@ -337,10 +422,10 @@ void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
                                                prvTraceUpdateCounters();\r
                                        }\r
                                }\r
-            }\r
-            trcCRITICAL_SECTION_END();\r
+            }            \r
         }\r
     }\r
+       trcCRITICAL_SECTION_END();\r
 }\r
 \r
 /*******************************************************************************\r
@@ -352,7 +437,10 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
 {\r
     uint16_t dts3;\r
     TSEvent* ts;\r
-    int8_t skipEvent = 0;\r
+    int8_t skipEvent;\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+               \r
+       skipEvent = 0;\r
 \r
        TRACE_ASSERT(task_handle <= NTask, "vTraceStoreTaskswitch: Invalid value for task_handle", );\r
        \r
@@ -370,8 +458,7 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
     function since critical sections should not be used in the context switch\r
     event...)\r
     ***************************************************************************/\r
-    recorder_busy++;\r
-\r
+    \r
     /* Skip the event if the task has been excluded, using vTraceExcludeTask */\r
     if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle))\r
     {\r
@@ -383,13 +470,14 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
         inExcludedTask = 0;\r
        }\r
 \r
+       trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY();\r
+\r
        /* Skip the event if the same task is scheduled */\r
        if (task_handle == handle_of_last_logged_task)\r
        {\r
                skipEvent = 1;\r
        }\r
-\r
-\r
+       \r
     if (!RecorderDataPtr->recorderActive)\r
     {\r
         skipEvent = 1;\r
@@ -402,7 +490,10 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
 \r
         if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
         {\r
+                       uint8_t hnd8;\r
             handle_of_last_logged_task = task_handle;\r
+                       hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task);\r
+\r
             ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
 \r
             if (ts != NULL)\r
@@ -418,7 +509,7 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
                 }\r
 \r
                 ts->dts = dts3;\r
-                ts->objHandle = handle_of_last_logged_task;\r
+                ts->objHandle = hnd8;\r
 \r
                 vTraceSetObjectState(TRACE_CLASS_TASK,\r
                                      handle_of_last_logged_task,\r
@@ -429,8 +520,7 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
         }\r
     }\r
 \r
-    /* See comment on recorder_busy++ above. */\r
-    recorder_busy--;\r
+       trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY();\r
 }\r
 \r
 /*******************************************************************************\r
@@ -454,6 +544,8 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
 \r
     if (RecorderDataPtr->recorderActive)\r
        {\r
+               uint8_t hnd8 = prvTraceGet8BitHandle(handle);\r
+\r
                name = TRACE_PROPERTY_NAME_GET(objectclass, handle);\r
 \r
                idx = prvTraceOpenSymbol(name, 0);\r
@@ -463,7 +555,7 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
                if (ce != NULL)\r
                {\r
                        ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass;\r
-                       ce->objHandle = handle;\r
+                       ce->objHandle = hnd8; \r
                        ce->symbolIndex = idx;\r
                        prvTraceUpdateCounters();\r
                }\r
@@ -499,7 +591,7 @@ void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
 }\r
 #endif\r
 \r
-void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value)\r
+void vTraceSetPriorityProperty(uint8_t objectclass, objectHandleType id, uint8_t value)\r
 {\r
        TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceSetPriorityProperty: objectclass >= TRACE_NCLASSES", );\r
        TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceSetPriorityProperty: Invalid value for id", );\r
@@ -507,7 +599,7 @@ void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value)
     TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id) = value;\r
 }\r
 \r
-uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id)\r
+uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, objectHandleType id)\r
 {\r
        TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetPriorityProperty: objectclass >= TRACE_NCLASSES", 0);\r
        TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetPriorityProperty: Invalid value for id", 0);\r
@@ -515,7 +607,7 @@ uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id)
     return TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id);\r
 }\r
 \r
-void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value)\r
+void vTraceSetObjectState(uint8_t objectclass, objectHandleType id, uint8_t value)\r
 {\r
        TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceSetObjectState: objectclass >= TRACE_NCLASSES", );\r
        TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceSetObjectState: Invalid value for id", );\r
@@ -523,7 +615,7 @@ void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value)
     TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value;\r
 }\r
 \r
-uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id)\r
+uint8_t uiTraceGetObjectState(uint8_t objectclass, objectHandleType id)\r
 {\r
        TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetObjectState: objectclass >= TRACE_NCLASSES", 0);\r
        TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetObjectState: Invalid value for id", 0);\r
index 91b6a8156af53c8aeae8117de1e6d3ad24164846..166dbcc3460b72e81b0672a65b2d418921622445 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcKernelPort.c\r
@@ -43,6 +43,8 @@
 \r
 #include "task.h"\r
 \r
+/* For classes implemented as FreeRTOS Queues: \r
+This translates queue.type to the corresponding trace object class. */\r
 traceObjectClass TraceObjectClassTable[5] = {\r
        TRACE_CLASS_QUEUE,\r
        TRACE_CLASS_MUTEX,\r
@@ -51,12 +53,14 @@ traceObjectClass TraceObjectClassTable[5] = {
        TRACE_CLASS_MUTEX\r
 };\r
 \r
+int uiInEventGroupSetBitsFromISR = 0;\r
+\r
 extern unsigned char ucQueueGetQueueType(void*);\r
-extern unsigned portBASE_TYPE uxQueueGetQueueNumber(void*);\r
+extern portBASE_TYPE uxQueueGetQueueNumber(void*);\r
 \r
 objectHandleType prvTraceGetObjectNumber(void* handle)\r
 {\r
-       return uxQueueGetQueueNumber(handle);   \r
+       return ( objectHandleType ) uxQueueGetQueueNumber(handle);      \r
 }\r
 \r
 unsigned char prvTraceGetObjectType(void* handle)\r
@@ -69,16 +73,6 @@ objectHandleType prvTraceGetTaskNumber(void* handle)
        return (objectHandleType)uxTaskGetTaskNumber(handle);\r
 }\r
 \r
-void prvTraceEnterCritical()\r
-{\r
-       taskENTER_CRITICAL();\r
-}\r
-\r
-void prvTraceExitCritical()\r
-{\r
-       taskEXIT_CRITICAL();\r
-}\r
-\r
 unsigned char prvTraceIsSchedulerActive()\r
 {\r
        return xTaskGetSchedulerState() == taskSCHEDULER_RUNNING;\r
@@ -108,42 +102,50 @@ void vTraceInitObjectPropertyTable()
        RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = NMutex;\r
        RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = NTask;\r
        RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = NISR;\r
+       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = NTimer;\r
+       RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = NEventGroup;  \r
        RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = NameLenQueue;\r
        RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = NameLenSemaphore;\r
        RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = NameLenMutex;\r
        RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = NameLenTask;\r
        RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = NameLenISR;\r
+       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = NameLenTimer;\r
+       RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = NameLenEventGroup; \r
        RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;\r
        RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;\r
        RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;\r
        RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[3] = PropertyTableSizeTask;\r
        RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;\r
+       RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[5] = PropertyTableSizeTimer;\r
+       RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[6] = PropertyTableSizeEventGroup;\r
        RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;\r
        RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;\r
        RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;\r
        RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[3] = StartIndexTask;\r
        RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;\r
+       RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[5] = StartIndexTimer;\r
+       RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[6] = StartIndexEventGroup;\r
        RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;\r
 }\r
 \r
 /* Initialization of the handle mechanism, see e.g, xTraceGetObjectHandle */\r
 void vTraceInitObjectHandleStack()\r
 {\r
-       objectHandleStacks.indexOfNextAvailableHandle[0] = 0;\r
-       objectHandleStacks.indexOfNextAvailableHandle[1] = NQueue;\r
-       objectHandleStacks.indexOfNextAvailableHandle[2] = NQueue + NSemaphore;\r
-       objectHandleStacks.indexOfNextAvailableHandle[3] = NQueue + NSemaphore + NMutex;\r
-       objectHandleStacks.indexOfNextAvailableHandle[4] = NQueue + NSemaphore + NMutex + NTask;\r
-       objectHandleStacks.lowestIndexOfClass[0] = 0;\r
-       objectHandleStacks.lowestIndexOfClass[1] = NQueue;\r
-       objectHandleStacks.lowestIndexOfClass[2] = NQueue + NSemaphore;\r
-       objectHandleStacks.lowestIndexOfClass[3] = NQueue + NSemaphore + NMutex;\r
-       objectHandleStacks.lowestIndexOfClass[4] = NQueue + NSemaphore + NMutex + NTask;\r
+       objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0;\r
+       objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = NQueue;\r
+       objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = NQueue + NSemaphore;\r
+       objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = NQueue + NSemaphore + NMutex;\r
+       objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = NQueue + NSemaphore + NMutex + NTask;\r
+       objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = NQueue + NSemaphore + NMutex + NTask + NISR;\r
+       objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer;\r
+\r
     objectHandleStacks.highestIndexOfClass[0] = NQueue - 1;\r
        objectHandleStacks.highestIndexOfClass[1] = NQueue + NSemaphore - 1;\r
        objectHandleStacks.highestIndexOfClass[2] = NQueue + NSemaphore + NMutex - 1;\r
        objectHandleStacks.highestIndexOfClass[3] = NQueue + NSemaphore + NMutex + NTask - 1;\r
        objectHandleStacks.highestIndexOfClass[4] = NQueue + NSemaphore + NMutex + NTask + NISR - 1;\r
+       objectHandleStacks.highestIndexOfClass[5] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer - 1;\r
+       objectHandleStacks.highestIndexOfClass[6] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer + NEventGroup - 1;\r
 }\r
        \r
 /* Returns the "Not enough handles" error message for this object class */\r
@@ -161,6 +163,10 @@ const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)
                return "Not enough MUTEX handles - increase NMutex in trcConfig.h";\r
        case TRACE_CLASS_QUEUE:\r
                return "Not enough QUEUE handles - increase NQueue in trcConfig.h";\r
+       case TRACE_CLASS_TIMER:\r
+               return "Not enough TIMER handles - increase NTimer in trcConfig.h";\r
+       case TRACE_CLASS_EVENTGROUP:\r
+               return "Not enough EVENTGROUP handles - increase NEventGroup in trcConfig.h";           \r
        default:\r
                return "pszTraceGetErrorHandles: Invalid objectclass!";\r
        }\r
@@ -182,8 +188,14 @@ uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, objectHandleType h
                return TRACE_GET_MUTEX_FLAG_ISEXCLUDED(handle);\r
        case TRACE_CLASS_QUEUE:\r
                return TRACE_GET_QUEUE_FLAG_ISEXCLUDED(handle);\r
+       case TRACE_CLASS_TIMER:\r
+               return TRACE_GET_TIMER_FLAG_ISEXCLUDED(handle);         \r
+       case TRACE_CLASS_EVENTGROUP:\r
+               return TRACE_GET_EVENTGROUP_FLAG_ISEXCLUDED(handle);                            \r
        }\r
        \r
+       vTraceError("Invalid object class ID in uiTraceIsObjectExcluded!");\r
+       \r
        /* Must never reach */\r
        return 1;\r
 }\r
index 74dc8079e47d0d5bd9e1a631f339ec2d6d9b0d31..5f46a809de9879f9df94da9cc51a464e65888cd1 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Tracealyzer v2.5.0 Recorder Library\r
+ * Tracealyzer v2.6.0 Recorder Library\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcUser.c\r
@@ -34,6 +34,8 @@
  * Copyright Percepio AB, 2013.\r
  * www.percepio.com\r
  ******************************************************************************/\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
 \r
 #include "trcUser.h"\r
 \r
@@ -47,7 +49,7 @@ TRACE_STOP_HOOK vTraceStopHookPtr = (TRACE_STOP_HOOK)0;
 \r
 extern uint8_t inExcludedTask;\r
 extern uint8_t nISRactive;\r
-extern uint8_t handle_of_last_logged_task;\r
+extern objectHandleType handle_of_last_logged_task;\r
 extern uint32_t dts_min;\r
 extern uint32_t hwtc_count_max_after_tick;\r
 extern uint32_t hwtc_count_sum_after_tick;\r
@@ -99,12 +101,15 @@ void vTraceSetRecorderData(void* pRecorderData)
  ******************************************************************************/\r
 void vTraceClear(void)\r
 {\r
+    TRACE_SR_ALLOC_CRITICAL_SECTION();\r
     trcCRITICAL_SECTION_BEGIN();\r
 \r
     RecorderDataPtr->absTimeLastEvent = 0;\r
     RecorderDataPtr->nextFreeIndex = 0;\r
     RecorderDataPtr->numEvents = 0;\r
     RecorderDataPtr->bufferIsFull = 0;\r
+       traceErrorMessage = NULL;\r
+       RecorderDataPtr->internalErrorOccured = 0;\r
 \r
     trcCRITICAL_SECTION_END();\r
 \r
@@ -125,7 +130,10 @@ void vTraceClear(void)
 \r
 uint32_t uiTraceStart(void)\r
 {\r
-       objectHandleType handle = 0;\r
+       objectHandleType handle;\r
+    TRACE_SR_ALLOC_CRITICAL_SECTION();\r
+\r
+       handle = 0;\r
 \r
        if (RecorderDataPtr == NULL)\r
        {\r
@@ -300,6 +308,103 @@ void vTraceSetISRProperties(objectHandleType handle, const char* name, char prio
     vTraceSetPriorityProperty(TRACE_CLASS_ISR, handle, priority);\r
 }\r
 \r
+#if (SELECTED_PORT == PORT_ARM_CortexM)\r
+/******************************************************************************\r
+ * (Advanced...)\r
+ *\r
+ * ISR_TAILCHAINING_THRESHOLD (For Cortex-M devices only)\r
+ *\r
+ * ARM Cortex-M devices may execute ISRs back-to-back (tail-chained) without \r
+ * resuming the previous context in between. Since this is decided in \r
+ * hardware, we can only detect this indirectly, in the following manner:\r
+ *\r
+ * When entering vTraceStoreISRBegin, we check the number of CPU cycles since \r
+ * the last return of vTraceStoreISREnd. If less or equal to the constant\r
+ * ISR_TAILCHAINING_THRESHOLD it is assumed that the ISRs executed back-to-back\r
+ * (tail-chained). In that case, the previously stored RESUME event \r
+ * (pointed to by ptrLastISRExitEvent) is then deleted to avoid showing a \r
+ * fragment of the previous context in between the ISR events. The delete is\r
+ * made by replacing the event code with a XTS16L event, that serves to keep\r
+ * the differential timestamp from the earlier event.\r
+ *\r
+ * The value of ISR_TAILCHAINING_THRESHOLD depends on the interrupt latency of \r
+ * the processor, on the compiler and on the compiler settings, but should be \r
+ * around 70 cycles. The default value is 66 cycles, which should be correct when \r
+ * using GCC with optimizations disabled (-O0) and Cortex-M3/M4.\r
+ *\r
+ * To measure this value, see MEASURE_ISR_TAILCHAINING_THRESHOLD below.\r
+ *\r
+ * If this value set too low, tail-chained ISRs will incorrectly be shown \r
+ * separated, with a short fragment of the previous task or ISR in between.\r
+ * If this value is set too high, you get the opposite effect - separate ISRs \r
+ * will appear to execute tail-chained and will appear to have higher execution \r
+ * time and response time (maximum ISR_TAILCHAINING_THRESHOLD cycles more).\r
+ *****************************************************************************/\r
+#define ISR_TAILCHAINING_THRESHOLD 66\r
+\r
+uint8_t* ptrLastISRExitEvent = NULL;\r
+uint32_t DWTCycleCountAtLastISRExit = 0;\r
+\r
+/******************************************************************************\r
+ * (Advanced...)\r
+ *\r
+ * MEASURE_ISR_TAILCHAINING_THRESHOLD (For Cortex-M devices only)\r
+ *\r
+ * Allows for measuring the value of ISR_TAILCHAINING_THRESHOLD (see above).\r
+ *\r
+ * This is intended to measure the minimum number of clock cycles from the end\r
+ * of vTraceStoreISREnd to the beginning of the following vTraceStoreISRBegin.\r
+ * For this purpose, we assume a test setup using the SysTick interrupt, which \r
+ * is available on most Cortex-M devices and typically used by the RTOS kernel. \r
+ * To do the measurement, follow these steps:\r
+ * \r
+ * 1. Make sure MEASURE_ISR_TAILCHAINING_THRESHOLD is enabled (defined as 1)\r
+ *\r
+ * 2. Temporarily replace your SysTick handler with the following:\r
+ *    \r
+ *    void xPortSysTickHandler( void )\r
+ *    {\r
+ *       vTraceStoreISRBegin(1); \r
+ *       vTraceStoreISREnd();\r
+ *    }\r
+ *\r
+ * 3. To make sure that the ISRs execute back-to-back, increase the OS tick \r
+ *    frequency to a very high level so that the OS tick interrupt execute \r
+ *    continuously with no application tasks in between. A tick frequency of \r
+ *    1 MHz (1.000.000) should be sufficient.\r
+ *\r
+ * 4. Put a breakpoint in the highest priority task and make sure it is not \r
+ *    reached. This means that the SysTick handler is executing at maximum rate\r
+ *    and thereby tail-chained, where the interrupt latency is 6 cycles.\r
+ *\r
+ * 5. Let the system run without breakpoints and inspect the value of \r
+ *    threshold_low_watermark. This is the minimum total latency observed. \r
+ *    The hardware latency is 6 clock cycles due to the tail-chaining, so the \r
+ *    software latency (SL) is then SL = threshold_low_watermark - 6.\r
+ * \r
+ * The threshold value ISR_TAILCHAINING_THRESHOLD should be SL + 2 * HL, where \r
+ * HL is the normal hardware interrupt latency, i.e., the number of CPU \r
+ * cycles to enter or exit the exception handler for an exception in task \r
+ * context. The HL value is 12-16 depending on core, as shown below.\r
+ * \r
+ * Values for ISR_TAILCHAINING_THRESHOLD, assuming SL = 42\r
+ *   Cortex-M3 and M4 (HL = 12):       66 cycles\r
+ *   Cortex-M0 (HL = 16):                      74 cycles\r
+ *   Cortex-M0+ (HL = 15):          72 cycles\r
+ *\r
+ * If the ISR_TAILCHAINING_THRESHOLD value is set too low, some tail-chained\r
+ * ISRs be shown separated, with a short fragment of the previous actor. If \r
+ * the value is set too high, separate ISRs will appear to execute tail-chained\r
+ * and for too long time.\r
+ *****************************************************************************/\r
+#define MEASURE_ISR_TAILCHAINING_THRESHOLD 1\r
+\r
+#if (MEASURE_ISR_TAILCHAINING_THRESHOLD == 1)\r
+volatile uint32_t threshold_low_watermark = 2000000000;\r
+#endif\r
+\r
+#endif\r
+\r
 /*******************************************************************************\r
  * vTraceStoreISRBegin\r
  *\r
@@ -318,34 +423,64 @@ void vTraceSetISRProperties(objectHandleType handle, const char* name, char prio
  *         vTraceStoreISREnd();\r
  *     }\r
  *\r
- * NOTE: You need to make sure that any traced interrupts actually are\r
- * disabled by trcCRITICAL_SECTION_BEGIN().\r
- * If an invalid call to vTraceStoreISRBegin is detected (i.e., that preempted\r
- * a critical section of the recorder) this will generate a recorder error\r
- * using vTraceError.\r
  ******************************************************************************/\r
 void vTraceStoreISRBegin(objectHandleType handle)\r
 {\r
     uint16_t dts4;\r
-    TSEvent* ts = NULL;\r
+       #if (SELECTED_PORT == PORT_ARM_CortexM)\r
+       uint32_t CPUCyclesSinceLastISRExit = DWT_CYCLE_COUNTER - DWTCycleCountAtLastISRExit;\r
+       #endif  \r
+    TSEvent* ts;\r
+    TRACE_SR_ALLOC_CRITICAL_SECTION();\r
 \r
-    TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid value for handle", );\r
+       ts = NULL;\r
 \r
+#if (SELECTED_PORT == PORT_ARM_CortexM)\r
+       if (DWTCycleCountAtLastISRExit > 0)     \r
+       {\r
+               #if (MEASURE_ISR_TAILCHAINING_THRESHOLD == 1)           \r
+               /* Allows for verifying the value of ISR_TAILCHAINING_THRESHOLD */\r
+               if (CPUCyclesSinceLastISRExit < threshold_low_watermark)\r
+               {\r
+                       threshold_low_watermark = CPUCyclesSinceLastISRExit;\r
+               }\r
+               #endif\r
+               \r
+               if (CPUCyclesSinceLastISRExit <= ISR_TAILCHAINING_THRESHOLD)            \r
+               {                       \r
+                       /* This is judged to be a case of ISR tail-chaining since the \r
+                       number of cycles since the last vTraceStoreISREnd is shorter or equal to\r
+                       the threshold (ISR_TAILCHAINING_THRESHOLD) */\r
+                       \r
+                       if (ptrLastISRExitEvent != NULL)\r
+                       {                               \r
+                               /* Overwrite the last ISR exit event with a "neutral" event that only\r
+                   accounts for the time passed */\r
+                               *ptrLastISRExitEvent = XTS16L;                                                  \r
+                       }                       \r
+               }\r
+               \r
+       }\r
+#endif\r
+       \r
     if (recorder_busy)\r
     {\r
       vTraceError("Illegal call to vTraceStoreISRBegin, recorder busy!");\r
       return;\r
     }\r
+       trcCRITICAL_SECTION_BEGIN();\r
     if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
     {\r
-        trcCRITICAL_SECTION_BEGIN();\r
+\r
+           TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid value for handle", );\r
+\r
         dts4 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
 \r
         if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
         {\r
-\r
             if (nISRactive < MAX_ISR_NESTING)\r
             {\r
+                               uint8_t hnd8 = prvTraceGet8BitHandle(handle);\r
                 isrstack[nISRactive] = handle;\r
                 nISRactive++;\r
                 ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
@@ -353,7 +488,7 @@ void vTraceStoreISRBegin(objectHandleType handle)
                 {\r
                     ts->type = TS_ISR_BEGIN;\r
                     ts->dts = dts4;\r
-                    ts->objHandle = handle;\r
+                    ts->objHandle = hnd8;\r
                     prvTraceUpdateCounters();\r
                 }\r
             }\r
@@ -362,40 +497,11 @@ void vTraceStoreISRBegin(objectHandleType handle)
                 /* This should not occur unless something is very wrong */\r
                 vTraceError("Too many nested interrupts!");\r
             }\r
-        }\r
-        trcCRITICAL_SECTION_END();\r
-    }\r
-}\r
-\r
-\r
-#if (SELECTED_PORT == PORT_ARM_CortexM)\r
-\r
-static int tailchain_irq_pending(void);\r
-\r
-/*******************************************************************************\r
- * tailchain_irq_pending\r
- *\r
- * For Cortex-M chips only. Returns 1 if an interrupt is pending, by checking\r
- * the 8 NVIC IRQ pend registers at 0xE000E200 to 0xE000E21C. Returns 0 if no\r
- * interrupt is pending. This is used to predict tailchaining of ISRs.\r
- ******************************************************************************/\r
-static int tailchain_irq_pending(void)\r
-{\r
-  uint32_t* pend_reg = ((uint32_t*)0xE000E200);\r
-  int i;\r
-\r
-  for (i=0; i<8; i++)\r
-  {\r
-    if (pend_reg[i] != 0)\r
-    {\r
-      return 1;\r
+        }        \r
     }\r
-  }\r
-  return 0;\r
+       trcCRITICAL_SECTION_END();\r
 }\r
 \r
-#endif\r
-\r
 /*******************************************************************************\r
  * vTraceStoreISREnd\r
  *\r
@@ -414,63 +520,61 @@ static int tailchain_irq_pending(void)
  *         vTraceStoreISREnd();\r
  *     }\r
  *\r
- * NOTE: You need to make sure that any traced interrupts actually are\r
- * disabled by trcCRITICAL_SECTION_BEGIN().\r
- * If an invalid call to vTraceStoreISREnd is detected (i.e., that preempted\r
- * a critical section of the recorder) this will generate a recorder error\r
- * using vTraceError.\r
  ******************************************************************************/\r
 void vTraceStoreISREnd(void)\r
 {\r
-    TSEvent* ts;\r
-    uint16_t dts5;\r
+       TSEvent* ts;\r
+       uint16_t dts5;\r
+       TRACE_SR_ALLOC_CRITICAL_SECTION();\r
 \r
-    if (recorder_busy)\r
-    {\r
-      vTraceError("Illegal call to vTraceStoreISREnd, recorder busy!");\r
-      return;\r
-    }\r
+       if (recorder_busy)\r
+       {\r
+               vTraceError("Illegal call to vTraceStoreISREnd, recorder busy!");\r
+               return;\r
+       }\r
 \r
-    if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
-    {\r
-        #if (SELECTED_PORT == PORT_ARM_CortexM)\r
-        if (tailchain_irq_pending() > 0)\r
-        {\r
-            nISRactive--; /* If an IRQ strikes exactly here, the resulting\r
-            ISR tailchaining is not detected. The trace instead shows a very\r
-            short fragment of the earlier preempted task/ISR, and then the new\r
-            ISR begins. */\r
-            return;\r
-        }\r
-        #endif\r
+       trcCRITICAL_SECTION_BEGIN();\r
+       if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
+       {               \r
+               dts5 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
 \r
-        trcCRITICAL_SECTION_BEGIN();\r
-        dts5 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
+               if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
+               {\r
+                       uint8_t hnd8, type;\r
 \r
-        if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
-        {\r
-            ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
-            if (ts != NULL)\r
-            {\r
-                if (nISRactive > 1)\r
-                {\r
-                    /* return to another isr */\r
-                    ts->type = TS_ISR_RESUME;\r
-                    ts->objHandle = isrstack[nISRactive];\r
-                }\r
-                else\r
-                {\r
-                    /* return to task */\r
-                    ts->type = TS_TASK_RESUME;\r
-                    ts->objHandle = handle_of_last_logged_task;\r
-                }\r
-                ts->dts = dts5;\r
-                nISRactive--;\r
-                prvTraceUpdateCounters();\r
-            }\r
-        }\r
-        trcCRITICAL_SECTION_END();\r
-    }\r
+                       if (nISRactive > 1)\r
+                       {\r
+                               /* return to another isr */\r
+                               type = TS_ISR_RESUME;\r
+                               hnd8 = prvTraceGet8BitHandle(isrstack[nISRactive]);\r
+                       }\r
+                       else\r
+                       {\r
+                               /* return to task */\r
+                               type = TS_TASK_RESUME;\r
+                               hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task);\r
+                       }\r
+\r
+                       ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
+\r
+                       if (ts != NULL)\r
+                       {\r
+                               ts->type = type;\r
+                               ts->objHandle = hnd8;\r
+                               ts->dts = dts5;\r
+                               nISRactive--;\r
+                               prvTraceUpdateCounters();\r
+                       }\r
+                                               \r
+               }\r
+               \r
+               #if (SELECTED_PORT == PORT_ARM_CortexM)\r
+               /* Remember the last ISR exit event, as the event needs to be modified in case of a following ISR entry (if tail-chained ISRs) */\r
+               ptrLastISRExitEvent = (uint8_t*)ts;\r
+               DWTCycleCountAtLastISRExit = DWT_CYCLE_COUNTER;\r
+               #endif  \r
+       }\r
+       trcCRITICAL_SECTION_END();\r
 }\r
 \r
 #else\r
@@ -605,7 +709,7 @@ static uint8_t writeDouble(void * buffer, uint8_t i, double value)
 {\r
        TRACE_ASSERT(buffer != NULL, "writeDouble: buffer == NULL", 0);\r
 \r
-    uint32_t * dest = buffer;\r
+    uint32_t * dest\r
     uint32_t * src = (void*)&value;\r
     /* The double is written as two 32 bit values, and should begin at an even\r
     4-byte address (to avoid having to align with 8 byte) */\r
@@ -624,9 +728,11 @@ static uint8_t writeDouble(void * buffer, uint8_t i, double value)
     {\r
         return 255;\r
     }\r
+       \r
+       dest = &(((uint32_t *)buffer)[i]);\r
 \r
-    dest[i/4+0] = src[0];\r
-    dest[i/4+1] = src[1];\r
+    dest[0] = src[0];\r
+    dest[1] = src[1];\r
 \r
     return i + 8;\r
 }\r
@@ -1049,6 +1155,7 @@ void vTracePrintF_Helper(traceLabel eventLabel, const char* formatStr, va_list v
        uint32_t noOfSlots;\r
     UserEvent* ue1;\r
     uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];\r
+    TRACE_SR_ALLOC_CRITICAL_SECTION();\r
 \r
     /**************************************************************************\r
     * The array tempDataBuffer is a local buffer used in a two-phase commit of\r
@@ -1063,108 +1170,102 @@ void vTracePrintF_Helper(traceLabel eventLabel, const char* formatStr, va_list v
 \r
        TRACE_ASSERT(formatStr != NULL, "vTracePrintF: formatStr == NULL", );\r
 \r
+       trcCRITICAL_SECTION_BEGIN();\r
+       \r
     if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
     {\r
         /* First, write the "primary" user event entry in the local buffer, but\r
         let the event type be "EVENT_BEING_WRITTEN" for now...*/\r
 \r
         ue1 = (UserEvent*)(&tempDataBuffer[0]);\r
+               \r
         ue1->type = EVENT_BEING_WRITTEN;      /* Update this as the last step */\r
 \r
         noOfSlots = prvTraceUserEventFormat(formatStr, vl, (uint8_t*)tempDataBuffer, 4);\r
 \r
         /* Store the format string, with a reference to the channel symbol */\r
-        ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel);\r
-\r
-        trcCRITICAL_SECTION_BEGIN();\r
+        ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel);                      \r
 \r
         ue1->dts = (uint8_t)prvTraceGetDTS(0xFF);\r
-        if (! RecorderDataPtr->recorderActive)\r
+               \r
+                /* prvTraceGetDTS might stop the recorder in some cases... */\r
+        if (RecorderDataPtr->recorderActive)\r
         {\r
 \r
-            /* Abort, since an XTS event (created by prvTraceGetDTS) filled the\r
-            buffer, and the recorder stopped since not circular buffer. */\r
-            trcCRITICAL_SECTION_END();\r
-\r
-            return;\r
-        }\r
-\r
-        /* If the data does not fit in the remaining main buffer, wrap around to\r
-        0 if allowed, otherwise stop the recorder and quit). */\r
-        if (RecorderDataPtr->nextFreeIndex + noOfSlots > RecorderDataPtr->maxEvents)\r
-        {\r
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
-            (void)memset(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],\r
-                   0,\r
-                   (RecorderDataPtr->maxEvents - RecorderDataPtr->nextFreeIndex)*4);\r
-            RecorderDataPtr->nextFreeIndex = 0;\r
-            RecorderDataPtr->bufferIsFull = 1;\r
-#else\r
-            /* Abort and stop recorder, since the event data will not fit in the\r
-            buffer and not circular buffer in this case... */\r
-            trcCRITICAL_SECTION_END();\r
-            vTraceStop();\r
-\r
-\r
-            return;\r
-#endif\r
-        }\r
-\r
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
-        /* Check that the buffer to be overwritten does not contain any user\r
-        events that would be partially overwritten. If so, they must be "killed"\r
-        by replacing the user event and following data with NULL events (i.e.,\r
-        using a memset to zero).*/\r
-        prvCheckDataToBeOverwrittenForMultiEntryEvents((uint8_t)noOfSlots);\r
-#endif\r
-        /* Copy the local buffer to the main buffer */\r
-        (void)memcpy(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],\r
-               tempDataBuffer,\r
-               noOfSlots * 4);\r
-\r
-        /* Update the event type, i.e., number of data entries following the\r
-        main USER_EVENT entry (Note: important that this is after the memcpy,\r
-        but within the critical section!)*/\r
-        RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4] =\r
-          (uint8_t) ( USER_EVENT + noOfSlots - 1 );\r
-\r
-        /* Update the main buffer event index (already checked that it fits in\r
-        the buffer, so no need to check for wrapping)*/\r
-\r
-        RecorderDataPtr->nextFreeIndex += noOfSlots;\r
-        RecorderDataPtr->numEvents += noOfSlots;\r
-\r
-\r
-\r
-               if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE)\r
-               {\r
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
-                       /* We have reached the end, but this is a ring buffer. Start from the beginning again. */\r
-                       RecorderDataPtr->bufferIsFull = 1;\r
-                       RecorderDataPtr->nextFreeIndex = 0;\r
-#else\r
-                       /* We have reached the end so we stop. */\r
-                       vTraceStop();\r
-#endif\r
-               }\r
-\r
-#if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
-               /* Make sure the next entry is cleared correctly */\r
-               prvCheckDataToBeOverwrittenForMultiEntryEvents(1);\r
-#endif\r
-\r
-#ifdef STOP_AFTER_N_EVENTS\r
-#if (STOP_AFTER_N_EVENTS > -1)\r
-               /* Check if we have reached the desired number of events */\r
-               if (RecorderDataPtr->numEvents >= STOP_AFTER_N_EVENTS)\r
-               {\r
-                       vTraceStop();\r
+                       /* If the data does not fit in the remaining main buffer, wrap around to\r
+                       0 if allowed, otherwise stop the recorder and quit). */\r
+                       if (RecorderDataPtr->nextFreeIndex + noOfSlots > RecorderDataPtr->maxEvents)\r
+                       {\r
+                               #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
+                               (void)memset(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],\r
+                                          0,\r
+                                          (RecorderDataPtr->maxEvents - RecorderDataPtr->nextFreeIndex)*4);\r
+                               RecorderDataPtr->nextFreeIndex = 0;\r
+                               RecorderDataPtr->bufferIsFull = 1;\r
+                               #else\r
+                               \r
+                               /* Stop recorder, since the event data will not fit in the\r
+                               buffer and not circular buffer in this case... */                               \r
+                               vTraceStop();                           \r
+                               #endif\r
+                       }\r
+                       \r
+                       /* Check if recorder has been stopped (i.e., vTraceStop above) */\r
+                       if (RecorderDataPtr->recorderActive)\r
+                       {                               \r
+                               /* Check that the buffer to be overwritten does not contain any user\r
+                               events that would be partially overwritten. If so, they must be "killed"\r
+                               by replacing the user event and following data with NULL events (i.e.,\r
+                               using a memset to zero).*/\r
+                               #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
+                               prvCheckDataToBeOverwrittenForMultiEntryEvents((uint8_t)noOfSlots);\r
+                               #endif\r
+                               /* Copy the local buffer to the main buffer */\r
+                               (void)memcpy(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],\r
+                                          tempDataBuffer,\r
+                                          noOfSlots * 4);\r
+\r
+                               /* Update the event type, i.e., number of data entries following the\r
+                               main USER_EVENT entry (Note: important that this is after the memcpy,\r
+                               but within the critical section!)*/\r
+                               RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4] =\r
+                                 (uint8_t) ( USER_EVENT + noOfSlots - 1 );\r
+\r
+                               /* Update the main buffer event index (already checked that it fits in\r
+                               the buffer, so no need to check for wrapping)*/\r
+\r
+                               RecorderDataPtr->nextFreeIndex += noOfSlots;\r
+                               RecorderDataPtr->numEvents += noOfSlots;\r
+\r
+                               if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE)\r
+                               {\r
+                                       #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
+                                       /* We have reached the end, but this is a ring buffer. Start from the beginning again. */\r
+                                       RecorderDataPtr->bufferIsFull = 1;\r
+                                       RecorderDataPtr->nextFreeIndex = 0;\r
+                                       #else\r
+                                       /* We have reached the end so we stop. */\r
+                                       vTraceStop();\r
+                                       #endif\r
+                               }\r
+                               \r
+                               #if (STOP_AFTER_N_EVENTS > -1)\r
+                               /* Check if we have reached the desired number of events */\r
+                               if (RecorderDataPtr->numEvents >= STOP_AFTER_N_EVENTS)\r
+                               {\r
+                                       vTraceStop();\r
+                               }\r
+                               #endif        \r
+                       }\r
+                       \r
+                       #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)\r
+                       /* Make sure the next entry is cleared correctly */\r
+                       prvCheckDataToBeOverwrittenForMultiEntryEvents(1);\r
+                       #endif\r
+       \r
                }\r
-#endif\r
-#endif\r
-\r
-        trcCRITICAL_SECTION_END();\r
-    }\r
+       }\r
+       trcCRITICAL_SECTION_END();\r
 \r
 #elif (USE_SEPARATE_USER_EVENT_BUFFER == 1)\r
        /* Use the separate user event buffer */\r
@@ -1195,13 +1296,13 @@ void vTraceUserEvent(traceLabel eventLabel)
 #if (USE_SEPARATE_USER_EVENT_BUFFER == 0)\r
     UserEvent* ue;\r
     uint8_t dts1;\r
+    TRACE_SR_ALLOC_CRITICAL_SECTION();\r
 \r
        TRACE_ASSERT(eventLabel > 0, "vTraceUserEvent: Invalid value for eventLabel", );\r
 \r
+       trcCRITICAL_SECTION_BEGIN();    \r
     if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
-    {\r
-        trcCRITICAL_SECTION_BEGIN();\r
-\r
+    {    \r
         dts1 = (uint8_t)prvTraceGetDTS(0xFF);\r
 \r
         if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
@@ -1214,14 +1315,14 @@ void vTraceUserEvent(traceLabel eventLabel)
                 ue->payload = eventLabel;\r
                 prvTraceUpdateCounters();\r
             }\r
-        }\r
-        trcCRITICAL_SECTION_END();\r
+        }        \r
     }\r
+       trcCRITICAL_SECTION_END();\r
+       \r
 #elif (USE_SEPARATE_USER_EVENT_BUFFER == 1)\r
        UserEventChannel channel;\r
        uint32_t noOfSlots = 1;\r
-       uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];\r
-\r
+       uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];        \r
        if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive) && handle_of_last_logged_task)\r
        {\r
                channel = xTraceRegisterChannelFormat(0, eventLabel);\r
@@ -1235,7 +1336,7 @@ void vTraceUserEvent(traceLabel eventLabel)
                }\r
 \r
                prvTraceUserEventHelper2(channel, tempDataBuffer, noOfSlots);\r
-       }\r
+       }       \r
 #endif\r
 }\r
 \r