/* Subtract the performance counter value reading taken when the \r
application started to get a count from that reference point, then\r
scale to (simulated) 1/100ths of a millisecond. */\r
- ulReturn = ( unsigned long ) ( ( liCurrentCount.QuadPart - llInitialRunTimeCounterValue ) / llTicksPerHundedthMillisecond );\r
+ if( llTicksPerHundedthMillisecond == 0 )\r
+ {\r
+ /* The trace macros can call this function before the kernel has been\r
+ started, in which case llTicksPerHundedthMillisecond will not have been\r
+ initialised. */\r
+ ulReturn = 0;\r
+ }\r
+ else\r
+ {\r
+ ulReturn = ( unsigned long ) ( ( liCurrentCount.QuadPart - llInitialRunTimeCounterValue ) / llTicksPerHundedthMillisecond );\r
+ }\r
\r
return ulReturn;\r
}\r
/******************************************************************************* \r
- * FreeRTOS+Trace v2.2.2 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcPort.h\r
*\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
#ifndef TRCPORT_H\r
#define TRCPORT_H\r
\r
-#include "trcBase.h"\r
-\r
/* If FreeRTOS Win32 port */\r
#ifdef WIN32\r
\r
******************************************************************************/\r
#define WIN32_PORT_SAVE_WHEN_STOPPED 1\r
#define WIN32_PORT_EXIT_WHEN_STOPPED 1\r
-\r
+#else\r
+ #define WIN32_PORT_SAVE_WHEN_STOPPED 0\r
+ #define WIN32_PORT_EXIT_WHEN_STOPPED 0\r
#endif\r
\r
#define DIRECTION_INCREMENTING 1\r
* count). The timing of the Win32 FreeRTOS build is not real-time, since it \r
* depends on the scheduling and tick rate of Windows, which is very slow.\r
*\r
- * Officially supported hardware specific ports included are:\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
* - PORT_TEXAS_INSTRUMENTS_TMS570\r
* - PORT_TEXAS_INSTRUMENTS_MSP430\r
* - PORT_MICROCHIP_PIC32\r
- * - PORT_MICROCHIP_dsPIC_AND_PIC24\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
-\r
-/* Officially supported ports */\r
-#define PORT_HWIndependent 0\r
-#define PORT_Win32 1\r
-#define PORT_Atmel_AT91SAM7 2\r
-#define PORT_ARM_CortexM 3\r
-#define PORT_Renesas_RX600 4\r
-\r
-/* Unofficial ports, provided by external developers and not yet verified */\r
-#define PORT_TEXAS_INSTRUMENTS_TMS570 6\r
-#define PORT_TEXAS_INSTRUMENTS_MSP430 7\r
-#define PORT_MICROCHIP_PIC32 8\r
-#define PORT_MICROCHIP_dsPIC_AND_PIC24 9\r
-#define PORT_XILINX_PPC405 10\r
-#define PORT_XILINX_PPC440 11\r
+ *****************************************************************************/\r
+\r
+#define PORT_NOT_SET -1\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_Win32\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
* 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
- * - Renesas RX62N: 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 (ARM Cortex R4F): 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
- * - Freescale ColdFire: 1 (higher irq priority values are more significant)\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.se.\r
- ******************************************************************************/\r
-#define IRQ_PRIORITY_ORDER 0\r
-\r
-/*******************************************************************************\r
- * HWTC macros\r
- * \r
- * These four macros provides a hardware isolation layer, representing a \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
* (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 a longer \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
* or the trace recorder library. Typically you should not need to change\r
* the code of uiTracePortGetTimeStamp if using the HWTC macros.\r
*\r
- * OFFER FROM PERCEPIO:\r
+ * FREE LICENSE OFFER FROM PERCEPIO\r
+ *\r
* For silicon companies and non-corporate FreeRTOS users (researchers, students,\r
- * hobbyists or early-phase startups) we have an attractive offer: \r
- * Provide a hardware timer port and get a FREE single-user licence for\r
- * FreeRTOS+Trace Professional Edition. Read more about this offer at \r
- * www.percepio.se or contact us directly at support@percepio.se.\r
+ * hobbyists or early-phase startups) we have the following offer: \r
+ * Provide a hardware port for our FreeRTOS recorder and get a FREE single-user\r
+ * license for FreeRTOS+Trace Professional Edition. Read more about this offer\r
+ * at www.percepio.com or contact us directly at support@percepio.com.\r
*\r
******************************************************************************/\r
\r
#if (SELECTED_PORT == PORT_Win32)\r
\r
- #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+ #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
#define HWTC_COUNT (ulGetRunTimeCounterValue())\r
#define HWTC_PERIOD 0\r
#define HWTC_DIVISOR 1\r
- \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_DIRECTION DIRECTION_INCREMENTING\r
#define HWTC_COUNT 0\r
#define HWTC_PERIOD 1\r
#define HWTC_DIVISOR 1\r
- \r
+\r
+ #define IRQ_PRIORITY_ORDER 1 // Please update according to your hardware...\r
+\r
#elif (SELECTED_PORT == PORT_Atmel_AT91SAM7)\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
+ 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 2995 \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
+ \r
+ /* For Atmel AVR32 (AT32UC3A) */\r
+ \r
+ #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+ #define HWTC_COUNT sysreg_read(AVR32_COUNT)\r
+ #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ )\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
+ /* 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
+#elif (SELECTED_PORT == PORT_Renesas_RX600) \r
\r
#include "iodefine.h"\r
\r
#define HWTC_PERIOD ((((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/8))\r
#define HWTC_DIVISOR 1\r
\r
-#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_TMS570) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\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 interresting 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
+ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+ \r
+ /* Tested with LPC2106, but should work with most LPC21XX chips.\r
+ Assumption: prescaler is 1:1 (this setting is hardcoded in \r
+ FreeRTOS port for LPC21XX) */\r
+ \r
+ #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+ #define HWTC_COUNT *((uint32_t *)0xE0004008 )\r
+ #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) \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
+ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
\r
#define RTIFRC0 *((uint32_t *)0xFFFFFC10)\r
#define RTICOMP0 *((uint32_t *)0xFFFFFC50)\r
#define HWTC_PERIOD (RTIUDCP0)\r
#define HWTC_DIVISOR 1\r
\r
-#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_MSP430) \r
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+ #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant\r
+\r
+#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_MSP430)\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 configCPU_CLOCKS_PER_TICK \r
#define HWTC_DIVISOR 1\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
+ #define IRQ_PRIORITY_ORDER 1 // higher irq priority values are more significant\r
\r
-#elif (SELECTED_PORT == PORT_MICROCHIP_dsPIC_AND_PIC24) \r
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\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 (PR1)\r
- #define HWTC_PERIOD ((configCPU_CLOCK_HZ/portTIMER_PRESCALE)/configTICK_RATE_HZ)\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
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\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 ( configCPU_CLOCK_HZ / configTICK_RATE_HZ )\r
- #define HWTC_DIVISOR 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_XILINX_PPC440) \r
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
\r
- /* This should work with most PowerPC chips */\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 ( configCPU_CLOCK_HZ / configTICK_RATE_HZ )\r
#define HWTC_DIVISOR 1 \r
\r
-#else\r
- SELECTED_PORT is not set, or had unsupported value!\r
- (This is to intentionally cause a compiler error.) \r
-#endif\r
+ #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant\r
+ \r
+#elif (SELECTED_PORT == PORT_XILINX_MICROBLAZE)\r
+ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+\r
+ /* This should work with most Microblaze configurations\r
+ * This port is based on the official FreeRTOS Microlaze port and example application.\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 ( configCPU_CLOCK_HZ / configTICK_RATE_HZ )\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_NOT_SET)\r
+\r
+ #error "SELECTED_PORT had unsupported value!"\r
+ #define SELECTED_PORT PORT_NOT_SET\r
\r
-#ifndef HWTC_COUNT_DIRECTION\r
- HWTC_COUNT_DIRECTION is not set!\r
- (This is to intentionally cause a compiler error.) \r
-#endif \r
-\r
-#ifndef HWTC_COUNT\r
- HWTC_COUNT is not set!\r
- (This is to intentionally cause a compiler error.) \r
-#endif \r
-\r
-#ifndef HWTC_PERIOD\r
- HWTC_PERIOD is not set!\r
- (This is to intentionally cause a compiler error.) \r
-#endif \r
-\r
-#ifndef HWTC_DIVISOR\r
- HWTC_DIVISOR is not set!\r
- (This is to intentionally cause a compiler error.) \r
-#endif \r
-\r
-#ifndef IRQ_PRIORITY_ORDER\r
- IRQ_PRIORITY_ORDER is not set!\r
- (This is to intentionally cause a compiler error.) \r
-#endif \r
-\r
-#if (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1)\r
- IRQ_PRIORITY_ORDER has bad value!\r
- (This is to intentionally cause a compiler error.) \r
-#endif \r
-\r
-#if (HWTC_DIVISOR < 1)\r
- HWTC_DIVISOR must be a non-zero positive value!\r
- (This is to intentionally cause a compiler error.) \r
-#endif \r
-\r
-#if ((IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1))\r
-IRQ_PRIORITY_ORDER not set!\r
-(This is to intentionally cause a compiler error.)\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
* 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 printf\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
* uiTracePortGetTimeStamp\r
* students, hobbyists or early-phase startups) we have an attractive offer: \r
* Provide a hardware timer port and get a FREE single-user licence for\r
* FreeRTOS+Trace Professional Edition. Read more about this offer at \r
- * www.percepio.se or contact us directly at support@percepio.se.\r
- ******************************************************************************/\r
-uint32_t uiTracePortGetTimeStamp(void);\r
-\r
-/*******************************************************************************\r
- * vTracePortSetFrequency\r
- *\r
- * Registers the frequency of the timer used. This is normally calculated \r
- * automatically from the HWTC macros, but the Win32 port requires a special \r
- * solution where the frequency can be set independently of the HWTC macros.\r
- * This is called from main in the Win32 demo program.\r
+ * www.percepio.com or contact us directly at support@percepio.com.\r
******************************************************************************/\r
-void vTracePortSetFrequency(uint32_t freq);\r
+void uiTracePortGetTimeStamp(uint32_t *puiTimestamp);\r
\r
/*******************************************************************************\r
* vTracePortEnd\r
-FreeRTOS+Trace v2.2.3\r
+FreeRTOS+Trace v2.3.0\r
---------------------\r
\r
This directory contains the recorder files that the typical FreeRTOS+Trace user needs to be aware of.\r
Always remember to check the settings used in trcConfig.h.\r
\r
Percepio AB\r
-www.percepio.se\r
+www.percepio.com\r
/*******************************************************************************\r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcConfig.h\r
*\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
#ifndef TRCCONFIG_H\r
* vTracePrintF may use multiple records depending on the number of data args.\r
******************************************************************************/\r
\r
-#ifdef WIN32\r
- #define EVENT_BUFFER_SIZE 3000\r
-#else\r
- #define EVENT_BUFFER_SIZE 1000 /* Adjust wrt. to available RAM */\r
-#endif\r
+#define EVENT_BUFFER_SIZE 1000 /* Adjust wrt. to available RAM */\r
+\r
+\r
+/*******************************************************************************\r
+ * USE_LINKER_PRAGMA\r
+ *\r
+ * Macro which should be defined as an integer value, default is 0.\r
+ *\r
+ * If this is 1, the header file "recorderdata_linker_pragma.h" is included just\r
+ * before the declaration of RecorderData (in trcBase.c), i.e., the trace data \r
+ * structure. This allows the user to specify a pragma with linker options. \r
+ *\r
+ * Example (for IAR Embedded Workbench and NXP LPC17xx):\r
+ * #pragma location="AHB_RAM_MEMORY"\r
+ * \r
+ * This example instructs the IAR linker to place RecorderData in another RAM \r
+ * bank, the AHB RAM. This can also be used for other compilers with a similar\r
+ * pragmas for linker options.\r
+ * \r
+ * Note that this only applies if using static allocation, see below.\r
+ ******************************************************************************/\r
+\r
+#define USE_LINKER_PRAGMA 0\r
+\r
\r
/*******************************************************************************\r
* SYMBOL_TABLE_SIZE\r
* routine, which makes the error message appear when opening the trace data\r
* in FreeRTOS+Trace. If you are using the recorder status monitor task,\r
* any error messages are displayed in console prints, assuming that the\r
- * print macro has been defined properly (vConsolePrintMessage).\r
- * \r
- * NOTE 2: If you include the monitor task (USE_TRACE_PROGRESS_MONITOR_TASK)\r
- * make sure to dimension NTask with this task accounted for.\r
+ * print macro has been defined properly (vConsolePrintMessage). \r
*\r
- * Also remember to account for all tasks created by FreeRTOS, such as the \r
+ * It can be wise to start with very large values for these constants, \r
+ * unless you are very confident on these numbers. Then do a recording and\r
+ * check the actual usage in FreeRTOS+Trace. This is shown by selecting\r
+ * View -> Trace Details -> Resource Usage -> Object Table\r
+ * \r
+ * NOTE 2: Remember to account for all tasks created by FreeRTOS, such as the \r
* IDLE task, the FreeRTOS timer task, and any tasks created by other 3rd party \r
- * software components, such as communication stacks.\r
- * Moreover, one task slot is used to indicate "(startup)", i.e., a "task" that \r
- * represent the time before the first task starts. NTask should thus be at \r
- * least 2-3 slots larger than your application task count.\r
+ * software components, such as communication stacks. The recorder also has an \r
+ * optional monitor task to account for, if this is used.\r
+ * Moreover, one task slot is used to indicate "(startup)", i.e., a fictive \r
+ * task that represent the time before the FreeRTOS scheduler starts. \r
+ * NTask should thus be at least 2-3 slots larger than your application task count.\r
*\r
* NOTE 3: The FreeRTOS timer task creates a Queue, that should be accounted \r
* for in NQueue.\r
*****************************************************************************/\r
#define INCLUDE_USER_EVENTS 1\r
\r
+/*****************************************************************************\r
+ * INCLUDE_READY_EVENTS\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1). \r
+ * Default is 1.\r
+ *\r
+ * If this is zero (0), the code for recording Ready events is \r
+ * excluded. Note, this will make it impossible to calculate the correct\r
+ * response times.\r
+ *****************************************************************************/\r
+#define INCLUDE_READY_EVENTS 1\r
+\r
/*****************************************************************************\r
* INCLUDE_ISR_TRACING\r
*\r
/******************************************************************************* \r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcPort.h\r
*\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
#ifndef TRCPORT_H\r
#define TRCPORT_H\r
\r
-#include "trcBase.h"\r
-\r
/* If FreeRTOS Win32 port */\r
#ifdef WIN32\r
\r
* count). The timing of the Win32 FreeRTOS build is not real-time, since it \r
* depends on the scheduling and tick rate of Windows, which is very slow.\r
*\r
- * Officially supported hardware specific ports included are:\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
* - PORT_TEXAS_INSTRUMENTS_TMS570\r
* - PORT_TEXAS_INSTRUMENTS_MSP430\r
* - PORT_MICROCHIP_PIC32\r
- * - PORT_MICROCHIP_dsPIC_AND_PIC24\r
* - PORT_XILINX_PPC405\r
* - PORT_XILINX_PPC440\r
+ * - PORT_XILINX_MICROBLAZE\r
+ * - PORT_NXP_LPC210X\r
*\r
- ******************************************************************************/\r
+ *****************************************************************************/\r
\r
#define PORT_NOT_SET -1\r
\r
-/* Officially supported ports */\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_ARM_CortexM 3\r
-#define PORT_Renesas_RX600 4\r
-\r
-/* Unofficial ports, provided by external developers and not yet verified */\r
-#define PORT_TEXAS_INSTRUMENTS_TMS570 5\r
-#define PORT_TEXAS_INSTRUMENTS_MSP430 6\r
-#define PORT_MICROCHIP_PIC32 7\r
-#define PORT_MICROCHIP_dsPIC_AND_PIC24 8\r
-#define PORT_XILINX_PPC405 9\r
-#define PORT_XILINX_PPC440 10\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
* 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
- * - Renesas RX62N: 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 (ARM Cortex R4F): 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
- * - Freescale ColdFire: 1 (higher irq priority values are more significant)\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.se.\r
- ******************************************************************************/\r
-#define IRQ_PRIORITY_ORDER 0\r
-\r
-/*******************************************************************************\r
- * HWTC macros\r
- * \r
- * These four macros provides a hardware isolation layer, representing a \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
* (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 a longer \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
* or the trace recorder library. Typically you should not need to change\r
* the code of uiTracePortGetTimeStamp if using the HWTC macros.\r
*\r
- * OFFER FROM PERCEPIO:\r
+ * FREE LICENSE OFFER FROM PERCEPIO\r
+ *\r
* For silicon companies and non-corporate FreeRTOS users (researchers, students,\r
- * hobbyists or early-phase startups) we have an attractive offer: \r
- * Provide a hardware timer port and get a FREE single-user licence for\r
- * FreeRTOS+Trace Professional Edition. Read more about this offer at \r
- * www.percepio.se or contact us directly at support@percepio.se.\r
+ * hobbyists or early-phase startups) we have the following offer: \r
+ * Provide a hardware port for our FreeRTOS recorder and get a FREE single-user\r
+ * license for FreeRTOS+Trace Professional Edition. Read more about this offer\r
+ * at www.percepio.com or contact us directly at support@percepio.com.\r
*\r
******************************************************************************/\r
\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
+\r
+ #define IRQ_PRIORITY_ORDER 1 // Please update according to your hardware...\r
+\r
#elif (SELECTED_PORT == PORT_Atmel_AT91SAM7)\r
\r
/* HWTC_PERIOD is hardcoded for AT91SAM7X256-EK Board (48 MHz)\r
#define HWTC_PERIOD 2995 \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
+ \r
+ /* For Atmel AVR32 (AT32UC3A) */\r
+ \r
+ #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+ #define HWTC_COUNT sysreg_read(AVR32_COUNT)\r
+ #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ )\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
#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
#define HWTC_PERIOD ((((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/8))\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 interresting 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
+ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
+ \r
+ /* Tested with LPC2106, but should work with most LPC21XX chips.\r
+ Assumption: prescaler is 1:1 (this setting is hardcoded in \r
+ FreeRTOS port for LPC21XX) */\r
+ \r
+ #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
+ #define HWTC_COUNT *((uint32_t *)0xE0004008 )\r
+ #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) \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
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
\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
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
\r
#define HWTC_PERIOD configCPU_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_PERIOD (ReadPeriod1()+1) /* Should be available in BSP */\r
#define HWTC_DIVISOR 1\r
\r
-#elif (SELECTED_PORT == PORT_MICROCHIP_dsPIC_AND_PIC24) \r
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
-\r
- #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING\r
- #define HWTC_COUNT (PR1)\r
- #define HWTC_PERIOD ((configCPU_CLOCK_HZ/portTIMER_PRESCALE)/configTICK_RATE_HZ)\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
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING\r
#define HWTC_COUNT mfspr( 0x3db)\r
#define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ )\r
- #define HWTC_DIVISOR 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_XILINX_PPC440) \r
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
#define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ )\r
#define HWTC_DIVISOR 1 \r
\r
-#else\r
-#error "SELECTED_PORT is not set, or had unsupported value!"\r
-#endif\r
+ #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant\r
+ \r
+#elif (SELECTED_PORT == PORT_XILINX_MICROBLAZE)\r
+ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */\r
\r
-#ifndef HWTC_COUNT_DIRECTION\r
-#error "HWTC_COUNT_DIRECTION is not set!"\r
-#endif \r
+ /* This should work with most Microblaze configurations\r
+ * This port is based on the official FreeRTOS Microlaze port and example application.\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
-#ifndef HWTC_COUNT\r
-#error "HWTC_COUNT is not set!" \r
-#endif \r
+ #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING\r
+ #define HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 )\r
+ #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ )\r
+ #define HWTC_DIVISOR 16\r
\r
-#ifndef HWTC_PERIOD\r
-#error "HWTC_PERIOD is not set!"\r
-#endif \r
+ #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant\r
\r
-#ifndef HWTC_DIVISOR\r
-#error "HWTC_DIVISOR is not set!" \r
-#endif \r
+#elif (SELECTED_PORT != PORT_NOT_SET)\r
\r
-#ifndef IRQ_PRIORITY_ORDER\r
-#error "IRQ_PRIORITY_ORDER is not set!"\r
-#endif \r
+ #error "SELECTED_PORT had unsupported value!"\r
+ #define SELECTED_PORT PORT_NOT_SET\r
\r
-#if (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1)\r
-#error "IRQ_PRIORITY_ORDER has bad value!"\r
-#endif \r
+#endif\r
\r
-#if (HWTC_DIVISOR < 1)\r
-#error "HWTC_DIVISOR must be a non-zero positive value!"\r
-#endif \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
* 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
* students, hobbyists or early-phase startups) we have an attractive offer: \r
* Provide a hardware timer port and get a FREE single-user licence for\r
* FreeRTOS+Trace Professional Edition. Read more about this offer at \r
- * www.percepio.se or contact us directly at support@percepio.se.\r
+ * www.percepio.com or contact us directly at support@percepio.com.\r
******************************************************************************/\r
-uint32_t uiTracePortGetTimeStamp(void);\r
+void uiTracePortGetTimeStamp(uint32_t *puiTimestamp);\r
\r
/*******************************************************************************\r
* vTracePortEnd\r
/*******************************************************************************\r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcBase.h\r
*\r
* \r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
#ifndef TRCBASE_H\r
\r
#include <stdio.h>\r
#include <string.h>\r
-#include <stdint.h>\r
+\r
#include "FreeRTOS.h"\r
#include "trcConfig.h"\r
#include "trcTypes.h"\r
#include "trcPort.h"\r
\r
+extern volatile int recorder_busy;\r
+\r
+#define trcCRITICAL_SECTION_BEGIN() {taskENTER_CRITICAL(); recorder_busy++;}\r
+#define trcCRITICAL_SECTION_END() {recorder_busy--; taskEXIT_CRITICAL();}\r
\r
#define NCLASSES 5\r
#define VERSION 0x1AA1\r
uint8_t type; \r
objectHandleType objHandle;\r
uint16_t dts; /* differential timestamp - time since last event */ \r
-} TSEvent;\r
+} TSEvent, TREvent;\r
\r
typedef struct\r
{\r
uint8_t irq_priority_order;\r
\r
/* sizeof(RecorderDataType) - just for control */\r
- uint32_t filesize; \r
- \r
+ uint32_t filesize;\r
+ \r
/* Current number of events recorded */\r
uint32_t numEvents;\r
- \r
+\r
/* The buffer size, in number of event records */\r
uint32_t maxEvents;\r
\r
\r
extern objectHandleStackType objectHandleStacks;\r
\r
-extern uint8_t taskFlags[NTask];\r
+/* Structures to handle the exclude flags for all objects, tasks and event codes */\r
+#define NEventCodes 0x100\r
+extern uint8_t excludedFlags[(NEventCodes+NQueue+NSemaphore+NMutex+NTask) / 8 + 1];\r
+extern uint8_t ifeFlags[NTask / 8 + 1];\r
\r
/* Internal functions */\r
\r
-uint32_t prvTraceGetDTS(uint32_t param_maxDTS);\r
+uint16_t prvTraceGetDTS(uint16_t param_maxDTS);\r
\r
void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength);\r
\r
\r
void prvTraceUpdateCounters(void);\r
\r
-void prvCheckDataToBeOverwrittenForMultiEntryUserEvents(uint32_t nEntries);\r
+void prvCheckDataToBeOverwrittenForMultiEntryUserEvents(uint8_t nEntries);\r
\r
objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass);\r
\r
\r
void* xTraceNextFreeEventBufferSlot(void);\r
\r
-uint32_t uiIndexOfObject(objectHandleType objecthandle, \r
+uint16_t uiIndexOfObject(objectHandleType objecthandle, \r
uint8_t objectclass);\r
\r
\r
* Called by various parts in the recorder. Stops the recorder and stores a \r
* pointer to an error message, which is printed by the monitor task.\r
******************************************************************************/\r
-void vTraceError(char* msg);\r
+void vTraceError(const char* msg);\r
\r
/*******************************************************************************\r
* xTraceGetLastError\r
[uiIndexOfObject(handle, TRACE_CLASS_TASK) \\r
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[TRACE_CLASS_TASK]+3]\r
\r
-#define TASK_FLAG_BITMASK_ExcludeTaskFromTrace 1\r
-#define TASK_FLAG_BITMASK_MarkNextEventAsTaskInstanceFinish 2\r
+#define SET_FLAG_ISEXCLUDED(bitIndex) excludedFlags[(bitIndex) >> 3] |= (1 << ((bitIndex) & 7))\r
+#define CLEAR_FLAG_ISEXCLUDED(bitIndex) excludedFlags[(bitIndex) >> 3] &= ~(1 << ((bitIndex) & 7))\r
+#define GET_FLAG_ISEXCLUDED(bitIndex) (excludedFlags[(bitIndex) >> 3] & (1 << ((bitIndex) & 7)))\r
+\r
+#define SET_FLAG_MARKIFE(bitIndex) ifeFlags[(bitIndex) >> 3] |= (1 << ((bitIndex) & 7))\r
+#define CLEAR_FLAG_MARKIFE(bitIndex) ifeFlags[(bitIndex) >> 3] &= ~(1 << ((bitIndex) & 7))\r
+#define GET_FLAG_MARKIFE(bitIndex) (ifeFlags[(bitIndex) >> 3] & (1 << ((bitIndex) & 7)))\r
+\r
+#define SET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) SET_FLAG_ISEXCLUDED(eventCode)\r
+#define CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) CLEAR_FLAG_ISEXCLUDED(eventCode)\r
+#define GET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) GET_FLAG_ISEXCLUDED(eventCode)\r
+\r
+#define SET_QUEUE_FLAG_ISEXCLUDED(queueHandle) SET_FLAG_ISEXCLUDED(NEventCodes+queueHandle-1)\r
+#define CLEAR_QUEUE_FLAG_ISEXCLUDED(queueHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+queueHandle-1)\r
+#define GET_QUEUE_FLAG_ISEXCLUDED(queueHandle) GET_FLAG_ISEXCLUDED(NEventCodes+queueHandle-1)\r
+\r
+#define SET_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreHandle) SET_FLAG_ISEXCLUDED(NEventCodes+NQueue+semaphoreHandle-1)\r
+#define CLEAR_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+NQueue+semaphoreHandle-1)\r
+#define GET_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreHandle) GET_FLAG_ISEXCLUDED(NEventCodes+NQueue+semaphoreHandle-1)\r
\r
-#define SET_TASK_FLAG_ISEXCLUDED(taskHandle) taskFlags[taskHandle] |= 0x01\r
-#define CLEAR_TASK_FLAG_ISEXCLUDED(taskHandle) taskFlags[taskHandle] &= 0xFE\r
-#define GET_TASK_FLAG_ISEXCLUDED(taskHandle) (taskFlags[taskHandle] & 0x01)\r
+#define SET_MUTEX_FLAG_ISEXCLUDED(mutexHandle) SET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+mutexHandle-1)\r
+#define CLEAR_MUTEX_FLAG_ISEXCLUDED(mutexHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+mutexHandle-1)\r
+#define GET_MUTEX_FLAG_ISEXCLUDED(mutexHandle) GET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+mutexHandle-1)\r
\r
-#define SET_TASK_FLAG_MARKIFE(taskHandle) taskFlags[taskHandle] |= 0x02\r
-#define CLEAR_TASK_FLAG_MARKIFE(taskHandle) taskFlags[taskHandle] &= 0xFD\r
-#define GET_TASK_FLAG_MARKIFE(taskHandle) (taskFlags[taskHandle] & 0x02)\r
+#define SET_TASK_FLAG_ISEXCLUDED(taskHandle) SET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+NMutex+taskHandle-1)\r
+#define CLEAR_TASK_FLAG_ISEXCLUDED(taskHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+NMutex+taskHandle-1)\r
+#define GET_TASK_FLAG_ISEXCLUDED(taskHandle) GET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+NMutex+taskHandle-1)\r
\r
+#define SET_TASK_FLAG_MARKIFE(bitIndex) SET_FLAG_MARKIFE(bitIndex-1)\r
+#define CLEAR_TASK_FLAG_MARKIFE(bitIndex) CLEAR_FLAG_MARKIFE(bitIndex-1)\r
+#define GET_TASK_FLAG_MARKIFE(bitIndex) GET_FLAG_MARKIFE(bitIndex-1)\r
\r
/* For debug printouts - the names of the object classes */\r
extern char OBJECTCLASSNAME[NCLASSES][10];\r
/*******************************************************************************\r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcHooks.h\r
*\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
#ifndef TRCHOOKS_H\r
#define TRCHOOKS_H\r
\r
-#include "trcKernel.h"\r
-\r
#if (configUSE_TRACE_FACILITY == 1)\r
\r
+ #include "trcUser.h"\r
+ \r
+ #undef INCLUDE_xTaskGetSchedulerState\r
#define INCLUDE_xTaskGetSchedulerState 1\r
+ \r
+ #undef INCLUDE_xTaskGetCurrentTaskHandle\r
#define INCLUDE_xTaskGetCurrentTaskHandle 1\r
-\r
- /* Called on each OS tick */\r
+ \r
+#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1\r
+ /* Called for each task that becomes ready */\r
+ #undef traceMOVED_TASK_TO_READY_STATE\r
+ #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \\r
+ vTraceStoreTaskReady((unsigned char)pxTCB->uxTaskNumber);\r
+#endif\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
- {extern uint32_t uiTraceTickCount; uiTraceTickCount = xTickCount;}\r
+ if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxMissedTicks == 0) {extern uint32_t uiTraceTickCount; uiTraceTickCount++; uiTracePortGetTimeStamp(0);}\r
\r
/* Called on each task-switch */\r
#undef traceTASK_SWITCHED_IN\r
/* Called on vTaskSuspend */\r
#undef traceTASK_SUSPEND\r
#define traceTASK_SUSPEND( pxTaskToSuspend ) \\r
- vTraceStoreKernelCall(TASK_SUSPEND, pxTaskToSuspend->uxTaskNumber); \\r
+ vTraceStoreKernelCall(TASK_SUSPEND, TRACE_CLASS_TASK, pxTaskToSuspend->uxTaskNumber); \\r
vTraceSetTaskInstanceFinished((uint8_t)pxTaskToSuspend->uxTaskNumber);\r
\r
/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */\r
vTraceSetTaskInstanceFinished((uint8_t)pxCurrentTCB->uxTaskNumber); \\r
portEXIT_CRITICAL();\r
\r
+#ifndef INCLUDE_OBJECT_DELETE\r
+#define INCLUDE_OBJECT_DELETE 0\r
+#endif\r
+\r
#if (INCLUDE_OBJECT_DELETE == 1)\r
/* Called on vTaskDelete */\r
#undef traceTASK_DELETE\r
#define traceTASK_DELETE( pxTaskToDelete ) \\r
- vTraceStoreKernelCall(EVENTGROUP_DELETE + TRACE_CLASS_TASK, pxTaskToDelete->uxTaskNumber); \\r
+ trcCRITICAL_SECTION_BEGIN(); \\r
+ vTraceStoreKernelCall(EVENTGROUP_DELETE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, pxTaskToDelete->uxTaskNumber); \\r
vTraceStoreObjectNameOnCloseEvent((objectHandleType)pxTaskToDelete->uxTaskNumber, TRACE_CLASS_TASK); \\r
vTraceStoreObjectPropertiesOnCloseEvent((objectHandleType)pxTaskToDelete->uxTaskNumber, TRACE_CLASS_TASK); \\r
vTraceSetPriorityProperty(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber, (uint8_t)pxTaskToDelete->uxPriority); \\r
vTraceSetObjectState(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber, TASK_STATE_INSTANCE_NOT_ACTIVE); \\r
- vTraceFreeObjectHandle(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber);\r
+ vTraceFreeObjectHandle(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber); \\r
+ trcCRITICAL_SECTION_END();\r
#endif\r
\r
/* Called on vTaskCreate */\r
pxNewTCB->uxTaskNumber = xTraceGetObjectHandle(TRACE_CLASS_TASK); \\r
vTraceSetObjectName(TRACE_CLASS_TASK, (objectHandleType)pxNewTCB->uxTaskNumber, (char*)pxNewTCB->pcTaskName); \\r
vTraceSetPriorityProperty(TRACE_CLASS_TASK, (objectHandleType)pxNewTCB->uxTaskNumber, (uint8_t)pxNewTCB->uxPriority); \\r
- vTraceStoreKernelCall(EVENTGROUP_CREATE + TRACE_CLASS_TASK, (objectHandleType)pxNewTCB->uxTaskNumber);\\r
+ vTraceStoreKernelCall(EVENTGROUP_CREATE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, pxNewTCB->uxTaskNumber);\\r
}\r
\r
- /* Called in vTaskCreate, if it fails (typically if the stack fails can not be allocated) */\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
portENTER_CRITICAL();\\r
- vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK, 0); \\r
+ vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, 0); \\r
portEXIT_CRITICAL();\r
\r
/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */\r
#define traceQUEUE_CREATE( pxNewQueue )\\r
portENTER_CRITICAL(); \\r
pxNewQueue->ucQueueNumber = xTraceGetObjectHandle(TraceObjectClassTable[pxNewQueue->ucQueueType]);\\r
+ vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \\r
vTraceSetObjectState(TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber, 0); \\r
- vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \\r
portEXIT_CRITICAL();\r
\r
/* Called in xQueueCreate, if the queue creation fails */\r
#undef traceQUEUE_CREATE_FAILED\r
#define traceQUEUE_CREATE_FAILED( queueType ) \\r
portENTER_CRITICAL();\\r
- vTraceStoreKernelCall((uint8_t)(EVENTGROUP_FAILED_CREATE + TraceObjectClassTable[queueType]), (objectHandleType)0); \\r
+ vTraceStoreKernelCall((uint8_t)(EVENTGROUP_FAILED_CREATE + TraceObjectClassTable[queueType]), TraceObjectClassTable[queueType], 0); \\r
portEXIT_CRITICAL();\r
\r
/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */\r
#define traceCREATE_MUTEX( pxNewQueue ) \\r
portENTER_CRITICAL();\\r
pxNewQueue->ucQueueNumber = xTraceGetObjectHandle(TRACE_CLASS_MUTEX); \\r
- vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \\r
- vTraceSetObjectState(TRACE_CLASS_MUTEX, pxNewQueue->ucQueueNumber, 0); \\r
+ vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \\r
+ vTraceSetObjectState(TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber, 0); \\r
portEXIT_CRITICAL();\r
\r
/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */\r
#undef traceCREATE_MUTEX_FAILED\r
#define traceCREATE_MUTEX_FAILED() \\r
portENTER_CRITICAL();\\r
- vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_MUTEX, 0);\\r
+ vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_MUTEX, TRACE_CLASS_MUTEX, 0);\\r
portEXIT_CRITICAL();\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
portENTER_CRITICAL();\\r
- vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TRACE_CLASS_MUTEX, pxMutex->ucQueueNumber); \\r
+ vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TRACE_CLASS_MUTEX, TRACE_CLASS_MUTEX, pxMutex->ucQueueNumber); \\r
portEXIT_CRITICAL();\r
\r
/* Called when a message is sent to a queue */\r
#undef traceQUEUE_SEND\r
#define traceQUEUE_SEND( pxQueue ) \\r
- vTraceStoreKernelCall(EVENTGROUP_SEND + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
+ vTraceStoreKernelCall(EVENTGROUP_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){\\r
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (uint8_t)pxQueue->ucQueueNumber, (uint8_t)0); \\r
}else{\\r
#undef traceQUEUE_SEND_FAILED\r
#define traceQUEUE_SEND_FAILED( pxQueue ) \\r
portENTER_CRITICAL();\\r
- vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
+ vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
portEXIT_CRITICAL();\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
portENTER_CRITICAL();\\r
- vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_SEND + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
+ vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
portEXIT_CRITICAL();\r
\r
/* Called when a message is received from a queue */\r
#undef traceQUEUE_RECEIVE\r
#define traceQUEUE_RECEIVE( pxQueue ) \\r
- vTraceStoreKernelCall(EVENTGROUP_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
+ vTraceStoreKernelCall(EVENTGROUP_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){\\r
extern volatile void * volatile pxCurrentTCB; \\r
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxCurrentTCB)); /*For mutex, store the new owner rather than queue length */ \\r
#undef traceBLOCKING_ON_QUEUE_RECEIVE\r
#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \\r
portENTER_CRITICAL(); \\r
- vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
+ vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
if (TraceObjectClassTable[pxQueue->ucQueueType] != TRACE_CLASS_MUTEX){\\r
extern volatile void * volatile pxCurrentTCB; \\r
vTraceSetTaskInstanceFinished((objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxCurrentTCB)); \\r
/* Called on xQueuePeek */\r
#undef traceQUEUE_PEEK\r
#define traceQUEUE_PEEK( pxQueue ) \\r
- vTraceStoreKernelCall(EVENTGROUP_PEEK + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);\r
+ vTraceStoreKernelCall(EVENTGROUP_PEEK + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);\r
\r
/* Called when a receive operation on a queue fails (timeout) */\r
#undef traceQUEUE_RECEIVE_FAILED\r
#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \\r
portENTER_CRITICAL(); \\r
- vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
+ vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
portEXIT_CRITICAL();\r
\r
/* Called when a message is sent from interrupt context, e.g., using xQueueSendFromISR */\r
#undef traceQUEUE_SEND_FROM_ISR\r
#define traceQUEUE_SEND_FROM_ISR( pxQueue ) \\r
- vTraceStoreKernelCall(EVENTGROUP_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
- vTraceSetObjectState(TRACE_CLASS_QUEUE, (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting + 1));\r
+ vTraceStoreKernelCall(EVENTGROUP_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
+ vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting + 1));\r
\r
/* Called when a message send from interrupt context fails (since the queue was full) */\r
#undef traceQUEUE_SEND_FROM_ISR_FAILED\r
#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) \\r
- vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);\r
+ vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);\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
- vTraceStoreKernelCall(EVENTGROUP_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
- vTraceSetObjectState(TRACE_CLASS_QUEUE, (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting - 1));\r
+ vTraceStoreKernelCall(EVENTGROUP_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
+ vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting - 1));\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
- vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);\r
+ vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);\r
\r
#if (INCLUDE_OBJECT_DELETE == 1)\r
/* Called on vQueueDelete */\r
#define traceQUEUE_DELETE( pxQueue ) \\r
{ \\r
portENTER_CRITICAL();\\r
- vTraceStoreKernelCall(EVENTGROUP_DELETE + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
+ vTraceStoreKernelCall(EVENTGROUP_DELETE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \\r
vTraceStoreObjectNameOnCloseEvent((objectHandleType)pxQueue->ucQueueNumber, TraceObjectClassTable[pxQueue->ucQueueType]); \\r
vTraceStoreObjectPropertiesOnCloseEvent((objectHandleType)pxQueue->ucQueueNumber, TraceObjectClassTable[pxQueue->ucQueueType]); \\r
if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){ \\r
/* Called in vTaskPrioritySet */\r
#undef traceTASK_PRIORITY_SET\r
#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \\r
- vTraceStoreKernelCallWithParam(TASK_PRIORITY_SET, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\\r
+ vTraceStoreKernelCallWithParam(TASK_PRIORITY_SET, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\\r
vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority);\r
\r
/* Called in vTaskPriorityInherit, which is called by Mutex operations */\r
#undef traceTASK_PRIORITY_INHERIT\r
#define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \\r
- vTraceStoreKernelCallWithParam(TASK_PRIORITY_INHERIT, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\\r
+ vTraceStoreKernelCallWithParam(TASK_PRIORITY_INHERIT, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\\r
vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority );\r
\r
/* Called in vTaskPriorityDisinherit, which is called by Mutex operations */\r
#undef traceTASK_PRIORITY_DISINHERIT\r
#define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \\r
- vTraceStoreKernelCallWithParam(TASK_PRIORITY_DISINHERIT, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\\r
+ vTraceStoreKernelCallWithParam(TASK_PRIORITY_DISINHERIT, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\\r
vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority );\r
\r
/* Called in vTaskResume */\r
#undef traceTASK_RESUME\r
#define traceTASK_RESUME( pxTaskToResume ) \\r
- vTraceStoreKernelCall(TASK_RESUME, pxTaskToResume->uxTaskNumber);\r
+ vTraceStoreKernelCall(TASK_RESUME, TRACE_CLASS_TASK, pxTaskToResume->uxTaskNumber);\r
\r
/* Called in vTaskResumeFromISR */\r
#undef traceTASK_RESUME_FROM_ISR\r
#define traceTASK_RESUME_FROM_ISR( pxTaskToResume )\\r
- vTraceStoreKernelCall(TASK_RESUME_FROM_ISR, pxTaskToResume->uxTaskNumber);\r
+ vTraceStoreKernelCall(TASK_RESUME_FROM_ISR, TRACE_CLASS_TASK, pxTaskToResume->uxTaskNumber);\r
\r
#endif\r
-#endif
\ No newline at end of file
+#endif\r
/*******************************************************************************\r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcKernel.h\r
*\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
#ifndef TRCKERNEL_H\r
#define TRCKERNEL_H\r
\r
-#include "trcTypes.h"\r
-\r
-#if (configUSE_TRACE_FACILITY == 1)\r
-\r
#include "trcBase.h"\r
\r
/* Internal functions */\r
\r
+\r
+#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1\r
+void vTraceStoreTaskReady(objectHandleType handle);\r
+#endif\r
+\r
void vTraceStoreTaskswitch(void);\r
\r
-void vTraceStoreKernelCall(uint32_t eventcode, uint32_t byteParam); \r
+void vTraceStoreKernelCall(uint32_t eventcode, traceObjectClass objectClass, uint32_t byteParam); \r
\r
void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, \r
uint16_t param);\r
\r
-void vTraceStoreKernelCallWithParam(uint32_t evtcode, uint32_t objectNumber, \r
- uint8_t param);\r
+void vTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass, \r
+ uint32_t objectNumber, uint8_t param);\r
\r
void vTraceSetTaskInstanceFinished(objectHandleType handle);\r
\r
#define TASK_STATE_INSTANCE_ACTIVE 1\r
#define TASK_STATE_INSTANCE_MARKED_FINISHED 2\r
\r
+extern objectHandleType handle_of_running_task;\r
+\r
/* This defines the mapping between FreeRTOS queue types and our internal \r
class IDs */\r
extern traceObjectClass TraceObjectClassTable[5];\r
******************************************************************************/\r
\r
#define NULL_EVENT (0x00) /* Ignored in the analysis*/\r
-#define RECORDING_START (0x01) /* Not yet used */\r
-#define RECORDING_STOP (0x02) /* Not yet used */\r
+\r
+/*******************************************************************************\r
+ * EVENTGROUP_RE\r
+ *\r
+ * Events that indicate that something is ready to execute.\r
+ ******************************************************************************/\r
+#define EVENTGROUP_RE (NULL_EVENT + 2) /*0x02*/\r
+#define TR_TASK_READY (EVENTGROUP_RE + 0) /*0x02*/\r
\r
/*******************************************************************************\r
* EVENTGROUP_TS\r
* Events for storing task-switches and interrupts. The RESUME events are \r
* generated if the task/interrupt is already marked active.\r
******************************************************************************/\r
-#define EVENTGROUP_TS (0x04)\r
-#define TS_ISR_BEGIN (EVENTGROUP_TS + 0) /* 4 */\r
-#define TS_ISR_RESUME (EVENTGROUP_TS + 1) /* 5 */\r
-#define TS_TASK_BEGIN (EVENTGROUP_TS + 2) /* 6 */\r
-#define TS_TASK_RESUME (EVENTGROUP_TS + 3) /* 7 */\r
+#define EVENTGROUP_TS (EVENTGROUP_RE + 2) /*0x04*/\r
+#define TS_ISR_BEGIN (EVENTGROUP_TS + 0) /*0x04*/\r
+#define TS_ISR_RESUME (EVENTGROUP_TS + 1) /*0x05*/\r
+#define TS_TASK_BEGIN (EVENTGROUP_TS + 2) /*0x06*/\r
+#define TS_TASK_RESUME (EVENTGROUP_TS + 3) /*0x07*/\r
\r
/*******************************************************************************\r
* EVENTGROUP_OBJCLOSE_NAME\r
* EVENTGROUP_OBJCLOSE_PROP), containg the handle-name mapping and object \r
* properties valid up to this point.\r
******************************************************************************/\r
-#define EVENTGROUP_OBJCLOSE_NAME (0x08)\r
+#define EVENTGROUP_OBJCLOSE_NAME (EVENTGROUP_TS + 4) /*0x08*/\r
\r
/*******************************************************************************\r
* EVENTGROUP_OBJCLOSE_PROP\r
\r
/* Other events - object class is implied: TASK */\r
#define EVENTGROUP_OTHERS (EVENTGROUP_DELETE + 8) /*0x88*/\r
-#define TASK_DELAY_UNTIL (EVENTGROUP_OTHERS + 0)\r
-#define TASK_DELAY (EVENTGROUP_OTHERS + 1)\r
-#define TASK_SUSPEND (EVENTGROUP_OTHERS + 2)\r
-#define TASK_RESUME (EVENTGROUP_OTHERS + 3)\r
-#define TASK_RESUME_FROM_ISR (EVENTGROUP_OTHERS + 4)\r
-#define TASK_PRIORITY_SET (EVENTGROUP_OTHERS + 5)\r
-#define TASK_PRIORITY_INHERIT (EVENTGROUP_OTHERS + 6)\r
-#define TASK_PRIORITY_DISINHERIT (EVENTGROUP_OTHERS + 7)\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
+#define TASK_RESUME (EVENTGROUP_OTHERS + 3) /*0x8B*/\r
+#define TASK_RESUME_FROM_ISR (EVENTGROUP_OTHERS + 4) /*0x8C*/\r
+#define TASK_PRIORITY_SET (EVENTGROUP_OTHERS + 5) /*0x8D*/\r
+#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 USER_EVENT (EVENTGROUP_USEREVENT + 0)\r
\r
/* Allow for 0-15 arguments (the number of args is added to event code) */\r
-#define USER_EVENT_LAST (EVENTGROUP_USEREVENT + 15)\r
+#define USER_EVENT_LAST (EVENTGROUP_USEREVENT + 15) /*0xA7*/\r
\r
-/******************************************************************************\r
+/*******************************************************************************\r
* XTS Event - eXtended TimeStamp events\r
* The timestamps used in the recorder are "differential timestamps" (DTS), i.e.\r
* the time since the last stored event. The DTS fields are either 1 or 2 bytes \r
#define RESERVED_DUMMY_CODE (EVENTGROUP_SYS + 3) /*0xAB*/\r
\r
#endif\r
-\r
-#endif
\ No newline at end of file
/*******************************************************************************\r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcTypes.h\r
*\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
#ifndef TRCTYPES_H\r
#define TRACE_CLASS_TASK ((traceObjectClass)3)\r
#define TRACE_CLASS_ISR ((traceObjectClass)4)\r
\r
+typedef uint8_t traceKernelService;\r
+\r
+#define TRACE_KERNEL_SERVICE_TASK_CREATE ((traceKernelService)0)\r
+#define TRACE_KERNEL_SERVICE_TASK_DELETE ((traceKernelService)1)\r
+#define TRACE_KERNEL_SERVICE_TASK_DELAY ((traceKernelService)2)\r
+#define TRACE_KERNEL_SERVICE_PRIORITY_SET ((traceKernelService)3)\r
+#define TRACE_KERNEL_SERVICE_TASK_SUSPEND ((traceKernelService)4)\r
+#define TRACE_KERNEL_SERVICE_TASK_RESUME ((traceKernelService)5)\r
+#define TRACE_KERNEL_SERVICE_QUEUE_CREATE ((traceKernelService)6)\r
+#define TRACE_KERNEL_SERVICE_QUEUE_DELETE ((traceKernelService)7)\r
+#define TRACE_KERNEL_SERVICE_QUEUE_SEND ((traceKernelService)8)\r
+#define TRACE_KERNEL_SERVICE_QUEUE_RECEIVE ((traceKernelService)9)\r
+#define TRACE_KERNEL_SERVICE_QUEUE_PEEK ((traceKernelService)10)\r
+#define TRACE_KERNEL_SERVICE_MUTEX_CREATE ((traceKernelService)11)\r
+#define TRACE_KERNEL_SERVICE_MUTEX_DELETE ((traceKernelService)12)\r
+#define TRACE_KERNEL_SERVICE_MUTEX_GIVE ((traceKernelService)13)\r
+#define TRACE_KERNEL_SERVICE_MUTEX_TAKE ((traceKernelService)14)\r
+#define TRACE_KERNEL_SERVICE_SEMAPHORE_CREATE ((traceKernelService)15)\r
+#define TRACE_KERNEL_SERVICE_SEMAPHORE_DELETE ((traceKernelService)16)\r
+#define TRACE_KERNEL_SERVICE_SEMAPHORE_GIVE ((traceKernelService)17)\r
+#define TRACE_KERNEL_SERVICE_SEMAPHORE_TAKE ((traceKernelService)18)\r
+\r
#endif\r
/*******************************************************************************\r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcUser.h\r
* The public API of the trace recorder library.\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
#ifndef TRCUSER_H\r
\r
#include "FreeRTOS.h"\r
\r
-#if (configUSE_TRACE_FACILITY == 1)\r
+#include "trcKernel.h"\r
\r
-#include "trcBase.h"\r
+#if (configUSE_TRACE_FACILITY == 1)\r
\r
#ifdef __cplusplus\r
extern "C" {\r
* portEXIT_CRITICAL();\r
* }\r
******************************************************************************/\r
-void vTraceSetISRProperties(objectHandleType handle, char* name, char priority);\r
+void vTraceSetISRProperties(objectHandleType handle, const char* name, char priority);\r
\r
/*******************************************************************************\r
* vTraceStoreISRBegin\r
* \r
- * Registers the beginning of an Interrupt Service Routine. This must not be\r
- * interrupted by another ISR containing recorder library calls, so if allowing\r
- * nested ISRs this must be called with interrupts disabled.\r
+ * Registers the beginning of an Interrupt Service Routine.\r
+ *\r
+ * Note! This may only be used for interrupts affected by portENTER_CRITICAL.\r
+ * In some FreeRTOS ports, such as ARM Cortex M3, this does not disable all\r
+ * interrupts. Interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY are still \r
+ * enabled, but may not call the FreeRTOS API. Such may not call the recorder \r
+ * API, including this function.\r
+ *\r
+ * See http://www.freertos.org/a00110.html\r
+ * \r
+ * If allowing nested ISRs, this must be called with interrupts disabled. \r
*\r
* Example:\r
* #define ID_ISR_TIMER1 1 // lowest valid ID is 1\r
/*******************************************************************************\r
* vTraceStoreISREnd\r
* \r
- * Registers the end of an Interrupt Service Routine. This must not be\r
- * interrupted by another ISR containing recorder library calls, so if allowing\r
- * nested ISRs this must be called with interrupts disabled.\r
+ * Registers the end of an Interrupt Service Routine.\r
+ *\r
+ * Note! This may only be used for interrupts affected by portENTER_CRITICAL.\r
+ * In some FreeRTOS ports, such as ARM Cortex M3, this does not disable all\r
+ * interrupts. Interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY are still \r
+ * enabled, but may not call the FreeRTOS API. Such may not call the recorder \r
+ * API, including this function.\r
+ *\r
+ * See http://www.freertos.org/a00110.html\r
+ * \r
+ * If allowing nested ISRs, this must be called with interrupts disabled. \r
*\r
* Example:\r
* #define ID_ISR_TIMER1 1 // lowest valid ID is 1\r
void vTraceStoreISREnd(void);\r
\r
#else\r
-\r
/* If not including the ISR recording */\r
\r
- #define vTraceSetISRProperties(handle, name, priority)\r
- #define vTraceStoreISRBegin(id)\r
- #define vTraceStoreISREnd()\r
+void vTraceIncreaseISRActive(void);\r
+\r
+void vTraceDecreaseISRActive(void);\r
+\r
+#define vTraceSetISRProperties(handle, name, priority)\r
+#define vTraceStoreISRBegin(id) vTraceIncreaseISRActive()\r
+#define vTraceStoreISREnd() vTraceDecreaseISRActive()\r
\r
#endif\r
\r
* executed and/or located in time-critical code. The lookup operation is\r
* however fairly fast due to the design of the symbol table.\r
******************************************************************************/\r
-traceLabel xTraceOpenLabel(char* label);\r
+traceLabel xTraceOpenLabel(const char* label);\r
\r
/******************************************************************************\r
* vTraceUserEvent\r
* %hu - 16 bit unsigned integer\r
* %bd - 8 bit signed integer\r
* %bu - 8 bit unsigned integer\r
- * %lf - double-precision float\r
+ * %lf - double-precision float (Note! See below...)\r
* \r
* Up to 15 data arguments are allowed, with a total size of maximum 32 byte.\r
* In case this is exceeded, the user event is changed into an error message.\r
* \r
* The data is stored in trace buffer, and is packed to allow storing multiple \r
* smaller data entries in the same 4-byte record, e.g., four 8-bit values.\r
- * A string requires two bytes, as the symbol table is limited to 64K. Storing a \r
- * double (%lf) uses two records, so this is quite costly. Use float (%f) unless\r
- * the higher precision is really necessary.\r
+ * A string requires two bytes, as the symbol table is limited to 64K. Storing \r
+ * a double (%lf) uses two records, so this is quite costly. Use float (%f) \r
+ * unless the higher precision is really necessary.\r
+ * \r
+ * Note that the double-precision float (%lf) assumes a 64 bit double \r
+ * representation. This does not seem to be the case on e.g. PIC24F. \r
+ * Before using a %lf argument on a 16-bit MCU, please verify that \r
+ * "sizeof(double)" actually gives 8 as expected. If not, use %f instead.\r
******************************************************************************/ \r
void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...);\r
\r
#endif\r
\r
/******************************************************************************\r
- * vTraceExcludeTask\r
+ * vTraceExclude______FromTrace\r
*\r
- * Excludes a task from the recording using a flag in the Object Property Table.\r
+ * Excludes a task or object from the trace.\r
* This can be useful if some irrelevant task is very frequent and is "eating\r
- * up the buffer". This should be called the task has been created, but \r
+ * up the buffer". This should be called after the task has been created, but \r
* before starting the FreeRTOS scheduler.\r
*****************************************************************************/\r
-void vTraceExcludeTaskFromSchedulingTrace(const char* name);\r
+void vTraceExcludeQueueFromTrace(void* handle);\r
+void vTraceExcludeSemaphoreFromTrace(void* handle);\r
+void vTraceExcludeMutexFromTrace(void* handle);\r
+void vTraceExcludeTaskFromTrace(void* handle);\r
+void vTraceExcludeKernelServiceFromTrace(traceKernelService kernelService);\r
+\r
+/******************************************************************************\r
+ * vTraceInclude______InTrace\r
+ *\r
+ * Includes a task, object or kernel service in the trace. This is only\r
+ * necessary if the task or object has been previously exluded.\r
+ *****************************************************************************/\r
+void vTraceIncludeQueueInTrace(void* handle);\r
+void vTraceIncludeSemaphoreInTrace(void* handle);\r
+void vTraceIncludeMutexInTrace(void* handle);\r
+void vTraceIncludeTaskInTrace(void* handle);\r
+void vTraceIncludeKernelServiceInTrace(traceKernelService kernelService);\r
\r
#ifdef __cplusplus\r
}\r
#include "trcPort.h"\r
\r
#define vTraceInit()\r
+#define uiTraceStart() (1)\r
#define vTraceStart()\r
#define vTraceStop()\r
#define vTraceClear()\r
+#define vTraceStartStatusMonitor()\r
+#define vTracePortSetOutFile(f)\r
#define vTraceGetTraceBuffer() ((void*)0)\r
#define uiTraceGetTraceBufferSize() 0\r
#define xTraceOpenLabel(label) 0\r
#define vTracePrintF(eventLabel,formatStr,...)\r
#define vTraceExcludeTaskFromSchedulingTrace(name)\r
#define vTraceSetQueueName(queue, name)\r
+\r
#define vTraceTaskSkipDefaultInstanceFinishedEvents()\r
#define vTraceSetISRProperties(handle, name, priority)\r
#define vTraceStoreISRBegin(id)\r
#define vTraceStoreISREnd()\r
#endif\r
#endif\r
+\r
--- /dev/null
+\r
+FreeRTOS+Trace - Uploading the trace data\r
+-----------------------------------------\r
+Percepio AB, Nov. 8, 2012\r
+\r
+This document decribes how to upload the trace data from the target system to\r
+FreeRTOS+Trace. For information on how to integrate and enable the recorder \r
+library in your FreeRTOS project, see the FreeRTOS+Trace User Manual.\r
+\r
+FreeRTOS+Trace uses your existing debugger to upload the trace data from the \r
+chip RAM. This is a plain RAM dump, that is done whenever you want to look at \r
+the trace buffer contents. This means it works with essentially with any debug \r
+probe on the market.\r
+\r
+Note that hardware-generated trace is not required (or used by) FreeRTOS+Trace. \r
+We however plan to add support for that in future versions of FreeRTOS+Trace \r
+and other Tracealyzer products.\r
+\r
+Built-in support for Segger J-Link/J-Trace and Atmel SAM-ICE\r
+------------------------------------------------------------\r
+FreeRTOS+Trace v2.3 supports Segger J-Link and J-Link compatible debuggers \r
+directly, without any debugger IDE involved. Using other debug probes is \r
+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
+\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
+internal RAM according to the datasheet of your MCU, but the exact address\r
+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 FreeRTOS+Trace 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
+FreeRTOS+Trace. Look for "MemoryLogger" in Atmel Gallery, available in \r
+Atmel Studio and at the Atmel website.\r
+\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
+\r
+Using other development environments and debug probes\r
+-----------------------------------------------------\r
+Most debuggers are able to save the RAM contents to a file. FreeRTOS+Trace \r
+supports the following common formats:\r
+- Binary (.bin), supporting gdb, J-Link and Renesas HEW.\r
+- Intel Hex (.hex), supporting IAR Embedded Workbench and Atmel Studio (atprogram.exe)\r
+- MCH (.mch), supporting Microchip MPLAB.\r
+\r
+When you store the RAM dump, you must also make sure to select the right region, \r
+i.e., start address and size. The recorder data is stored in a single data \r
+block, identified by the pointer RecorderDataPtr. \r
+It is not necessary to match the begin and end of the recorder data, as long as \r
+it is fully included by the dumped memory region. FreeRTOS+Trace automatically \r
+finds the trace data in the RAM dump, thanks to special signatures. For chips \r
+with on-chip RAM only, we therefore recommend to dump the entire RAM. This is \r
+usually very fast.\r
+For chips with larger amounts of (external) RAM, it is typically possible to \r
+dump a limited region where the data is typically found.\r
+\r
+Using IAR Embedded Workbench for ARM, version 6.3\r
+-------------------------------------------------\r
+In the debugger view, when stopped on a breakpoint:\r
+- Select "Debug" menu, "Memory" submenu, "Save..." (keyboard shortcut: ALT,d,y,s)\r
+- In the Save dialog\r
+ - Zone: Memory\r
+ - Start Adress: 10000000 (for NXP LPC1766 in the demo project)\r
+ - End Adress: 1000FFFF (for NXP LPC1766 in the demo project)\r
+ - File format: Intel Extended\r
+ - Filename: <name>.hex\r
+ - Press "Save" button\r
+You can now open <name>.hex in FreeRTOS+Trace.\r
+\r
+To find the right Start and End addresses, check the address of the symbol \r
+"RecorderData". The addresses does not need to match this symbol exactly, as \r
+long as the whole data is included.\r
+\r
+Using Renesas High-performance Embedded Workshop v4.09\r
+------------------------------------------------------\r
+In the debugger view, when stopped on a breakpoint:\r
+- Select "Debug" menu, "Save Memory..." (keyboard shortcut: ALT,d,a)\r
+- In the Save dialog\r
+ - Format: Binary\r
+ - Filename: <name>.bin\r
+ - Start Address: 00000000 (For RX62N in the demo project)\r
+ - End Address: 0000FFFF (For RX62N in the demo project)\r
+ - Access size: 1\r
+ - Press "Save" button and open <name>.bin in FreeRTOS+Trace.\r
+ \r
+Using Microchip MPLAB v8.86\r
+------------------------------------------------------\r
+- Select "View" -> "File Registers". This shows you the memory contents.\r
+- Make sure "Hex" is selected in the bottom left (instead of "Symbolic"). Hex mode seems to be default.\r
+- Right click in the view and select "Export Table...".\r
+- In the dialog ("Export As"), make sure "Single Column Output" is selected (seems to be default).\r
+- Select start address 0x0000 and make sure the end address is beyond the RecorderData structure. \r
+ The default values seems to be the whole RAM, so you probably don't need to change this.\r
+- Save as a .mch file and open this file in FreeRTOS+Trace v2.2.4 or later (support for the .mch format was added in v2.2.4).\r
+\r
+Using STM32 ST-Link\r
+------------------------------------------------------\r
+- Start "ST-Link Utility"\r
+- Connect to the device and view the device memory.\r
+- Set the view to display the entire RAM, or at least the section containing the RecorderData structure.\r
+- Select "Save as" and choose binary (.bin) or Intel Hex (.hex) format.\r
+- Open the resulting file in FreeRTOS+Trace.\r
+\r
+In case you have any question, contact support@percepio.com\r
+\r
+Percepio AB\r
+www.percepio.com\r
-THIS PRODUCT IS UNDER ACTIVE DEVELOPMENT, PLEASE SEE \r
-THE PERCEPIO WEBSITE FOR A COMPLETE LIST OF THE LATEST PORTS\r
\r
-\r
-FreeRTOS+Trace Demo\r
--------------------\r
+FreeRTOS+Trace Trace Recorder Library\r
+-------------------------------------\r
Percepio AB\r
-www.percepio.se\r
+www.percepio.com\r
+\r
+This directory contains the core trace recorder library used by FreeRTOS+Trace v2.3. \r
+\r
+Ready-to-run demonstrations projects are found at www.percepio.com.\r
+\r
+For information on how to integrate the recorder library in your FreeRTOS build, see\r
+the FreeRTOS+Trace User Manual, section 2.\r
+\r
+For information on how to upload the trace data from your target system RAM to \r
+FreeRTOS+Trace, see "debugger trace upload.txt"\r
\r
-This package contains:\r
-/Demo/DemoAppl The demo application used in the included demo projects.\r
-/Demo/Eclipse-AT91SAM7 Demo project for Eclipse/GCC with Atmel AT91SAM7X256 as preconfigured target.\r
-/Demo/IAR - Cortex M3 Demo project for IAR Embedded Workbench for ARM, with NXP LPC1766 as preconfigured target.\r
-/Demo/Renesas RDK HEW - RX600 Demo project for Renesas HEW, with the RX62N as preconfigured target.\r
-/Demo/MSVC Win32 Demo project Microsoft Visual Studio, using the Win32 port of FreeRTOS.\r
-/FreeRTOS-v7.1.1 A subset of FreeRTOS v7.1.1 (the only change is that the Demo directory has been removed - it is quite large!).\r
-/TraceRecorderSrc The trace recorder library for FreeRTOS / FreeRTOS+Trace.\r
+NOTE: This trace recorder library requires FreeRTOS v7.3.0 or later.\r
\r
-Note that the individual Demo project directories are not self-contained.\r
-They refer to the FreeRTOS-v7.1.1, DemoAppl and TraceRecorderSrc directories.\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
+- trcPort.c / trcPort.h - The port layer, abstracting the hardware (mainly the timer used for timestamping).\r
+- trcHooks.h - The interface between FreeRTOS and the recorder, containing trace macro defintions.\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)\r
-- Atmel AT91SAM7X\r
-- Renesas RX600\r
+- ARM Cortex M3/M4 (all brands, such as Atmel SAM3/SAM4, 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
-The package moreover contain several "unofficial" ports, provided by external contributors and not yet verified by Percepio AB.\r
-See trcPort.h for the details. \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
\r
-In case your hardware is not yet directly supported, developing a new port is quite easy. \r
-See trcPort.h for further information.\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
\r
-In case you have any questions, do not hesitate to contact support@percepio.se\r
+In case you have any questions, do not hesitate to contact support@percepio.com\r
\r
Percepio AB\r
Köpmangatan 1A\r
72215 Västerås\r
Sweden\r
\r
-www.percepio.se
\ No newline at end of file
+www.percepio.com
\ No newline at end of file
/*******************************************************************************\r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcBase.c\r
*\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
-#include "FreeRTOS.h"\r
-#include "task.h"\r
-#include "trcBase.h"\r
-#include "trcKernel.h"\r
#include "trcUser.h"\r
+#include "task.h"\r
\r
#if (configUSE_TRACE_FACILITY == 1)\r
\r
* RecorderData\r
*\r
* The main data structure. This is the data read by FreeRTOS+Trace, typically\r
- * through a debugger RAM dump. This is accessed through RecorderDataPtr.\r
+ * through a debugger RAM dump. The recorder access this through the pointer\r
+ * RecorderDataPtr, to allow for dynamic memory allocation as well.\r
*\r
- * On the NXP LPC176x you may use the upper RAM bank (AHB) for this purpose. \r
- * For instance, the LPC1766 has 32 KB AHB RAM which allows for allocating a \r
- * buffer size of 7900 events without affecting the main RAM.\r
- * To place RecorderData in this RAM bank, use the below declaration.\r
+ * On the NXP LPC17xx you may use the secondary RAM bank (AHB RAM) for this\r
+ * purpose. For instance, the LPC1766 has 32 KB AHB RAM which allows for \r
+ * allocating a buffer size of at least 7500 events without affecting the main\r
+ * RAM. To place RecorderData in this RAM bank, use the below declaration.\r
* \r
* #pragma location="AHB_RAM_MEMORY"\r
* RecorderDataType RecorderData = ...\r
* This of course works for other hardware architectures with additional RAM \r
* banks as well, just replace "AHB_RAM_MEMORY" with the name of the right \r
* address section from the linker file.\r
+ *\r
+ * However, to keep trcBase.c portable and still have a preconfigured IAR demo\r
+ * using AHB RAM, we don't add the pragma directly in trcBase.c but in a header \r
+ * included where the pragma should go. This is used depending on the setting\r
+ * USE_LINKER_PRAGMA, defined in trcConfig.h.\r
* \r
- * If using GCC, this is done by adding a "section" attribute:\r
+ * If using GCC, this is instead done by adding a "section" attribute:\r
*\r
* RecorderDataType RecorderData __attribute__ ((section ("name"))) = ...\r
*\r
******************************************************************************/\r
\r
#if (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_STATIC)\r
+#if (USE_LINKER_PRAGMA == 1)\r
+#include "recorderdata_linker_pragma.h"\r
+#endif\r
RecorderDataType RecorderData =\r
{\r
/* start marker, 12 chars */\r
};\r
\r
RecorderDataType* RecorderDataPtr = &RecorderData;\r
-#endif\r
\r
+/* This version of the function does nothing as the trace data is statically allocated */\r
+RecorderDataType* xTraceInitTraceData(void)\r
+{\r
+ return 0;\r
+}\r
\r
-#if (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_DYNAMIC)\r
+#elif (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_DYNAMIC)\r
\r
RecorderDataType* RecorderDataPtr = NULL;\r
\r
+/* This version of the function dynamically allocates the trace data */\r
RecorderDataType* xTraceInitTraceData(void)\r
{\r
RecorderDataType* tmp = (RecorderDataType*)pvPortMalloc(sizeof(RecorderDataType));\r
\r
#endif\r
\r
+volatile int recorder_busy = 0;\r
\r
char sprintfBuffer[150];\r
\r
};\r
\r
\r
-/* Used for internal state flags of tasks */\r
-uint8_t taskFlags[NTask];\r
+/* Used for internal state flags of objects */\r
+uint8_t excludedFlags[(NEventCodes+NQueue+NSemaphore+NMutex+NTask) / 8 + 1];\r
+uint8_t ifeFlags[NTask / 8 + 1];\r
\r
/* Gives the last error message of the recorder. NULL if no error message. */\r
char* traceErrorMessage = NULL;\r
\r
-#if (INCLUDE_EVENT_STATS == 1)\r
-/* Used for an internal reporting mechanism, which displays the count and ratio \r
-of each object type in a console printout generated in vTracePortEnd */\r
-uint16_t eventCount[256];\r
-#endif\r
-\r
void* xTraceNextFreeEventBufferSlot(void)\r
{\r
if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE)\r
eventData[RecorderDataPtr->nextFreeIndex*4]);\r
}\r
\r
-uint32_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass)\r
+uint16_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass)\r
{\r
if ((objectclass < NCLASSES) && (objecthandle > 0) && (objecthandle <= \r
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass]))\r
{\r
- return (uint32_t)(RecorderDataPtr->\r
+ return (uint16_t)(RecorderDataPtr->\r
ObjectPropertyTable.StartIndexOfClass[objectclass] + \r
(RecorderDataPtr->\r
ObjectPropertyTable.TotalPropertyBytesPerClass[objectclass] * \r
objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass)\r
{\r
static objectHandleType handle;\r
- static uint32_t indexOfHandle;\r
+ static int indexOfHandle;\r
\r
indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass];\r
if (objectHandleStacks.objectHandles[indexOfHandle] == 0)\r
/* ERROR */\r
switch(objectclass)\r
{\r
- case TRACE_CLASS_TASK:\r
+ case TRACE_CLASS_TASK:\r
vTraceError("Not enough TASK handles - increase NTask in trcConfig.h"); \r
break;\r
- case TRACE_CLASS_ISR:\r
+ case TRACE_CLASS_ISR:\r
vTraceError("Not enough ISR handles - increase NISR in trcConfig.h"); \r
break;\r
- case TRACE_CLASS_SEMAPHORE:\r
+ case TRACE_CLASS_SEMAPHORE:\r
vTraceError("Not enough SEMAPHORE handles - increase NSemaphore in trcConfig.h"); \r
break;\r
- case TRACE_CLASS_MUTEX:\r
+ case TRACE_CLASS_MUTEX:\r
vTraceError("Not enough MUTEX handles - increase NMutex in trcConfig.h"); \r
break;\r
- case TRACE_CLASS_QUEUE:\r
+ case TRACE_CLASS_QUEUE:\r
vTraceError("Not enough QUEUE handles - increase NQueue in trcConfig.h"); \r
break;\r
+ default:\r
+ vTraceError("Invalid object class.");\r
+ break;\r
}\r
\r
handle = 0; /* an invalid/anonymous handle - but the recorder is stopped now... */\r
}\r
else\r
{\r
- int32_t hndCount;\r
+ int hndCount;\r
objectHandleStacks.indexOfNextAvailableHandle[objectclass]++;\r
\r
hndCount = objectHandleStacks.indexOfNextAvailableHandle[objectclass] - \r
\r
void vTraceFreeObjectHandle(traceObjectClass objectclass, objectHandleType handle)\r
{\r
- uint32_t indexOfHandle;\r
+ int indexOfHandle;\r
\r
/* Check that there is room to push the handle on the stack */\r
if ( (objectHandleStacks.indexOfNextAvailableHandle[objectclass] - 1) < \r
objectHandleType handle, \r
const char* name)\r
{\r
- static uint32_t idx;\r
+ static uint16_t idx;\r
\r
if (handle == 0)\r
{\r
(void)strncpy((char*)&(RecorderDataPtr->ObjectPropertyTable.objbytes[idx]),\r
name,\r
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ objectclass ] );\r
+#ifdef WIN32\r
+ printf("vTraceSetObjectName(%d, %d, %s)\n", objectclass, handle, name);\r
+#endif\r
}\r
}\r
}\r
crc = 0;\r
prvTraceGetChecksum(name, &crc, &len);\r
\r
- taskENTER_CRITICAL();\r
+ trcCRITICAL_SECTION_BEGIN();\r
result = prvTraceLookupSymbolTableEntry(name, crc, len, userEventChannel);\r
if (!result)\r
{\r
result = prvTraceCreateSymbolTableEntry(name, crc, len, userEventChannel);\r
}\r
- taskEXIT_CRITICAL();\r
+ trcCRITICAL_SECTION_END();\r
\r
return result;\r
}\r
* trace start will be aborted. This can occur if any of the Nxxxx constants \r
* (e.g., NTask) in trcConfig.h is too small.\r
******************************************************************************/\r
-void vTraceError(char* msg)\r
+void vTraceError(const char* msg)\r
{\r
vTraceStop();\r
if (traceErrorMessage == NULL)\r
{\r
- traceErrorMessage = msg;\r
+ traceErrorMessage = (char*)msg;\r
(void)strncpy(RecorderDataPtr->systemInfo, \r
traceErrorMessage, \r
TRACE_DESCRIPTION_MAX_LENGTH);\r
*****************************************************************************/\r
\r
void prvCheckDataToBeOverwrittenForMultiEntryUserEvents(\r
- uint32_t nofEntriesToCheck)\r
+ uint8_t nofEntriesToCheck)\r
{\r
- uint32_t i = 0, e = 0;\r
+ /* Generic "int" type is desired - should be 16 bit variable on 16 bit HW */\r
+ unsigned int i = 0; \r
+ unsigned int e = 0;\r
while (i < nofEntriesToCheck)\r
{ \r
e = RecorderDataPtr->nextFreeIndex + i;\r
if ((RecorderDataPtr->eventData[e*4] > USER_EVENT) && \r
(RecorderDataPtr->eventData[e*4] < USER_EVENT + 16))\r
{\r
- uint32_t nDataEvents = (uint32_t)(RecorderDataPtr->eventData[e*4] - USER_EVENT);\r
- if (e + nDataEvents < RecorderDataPtr->maxEvents)\r
+ uint8_t nDataEvents = (uint8_t)(RecorderDataPtr->eventData[e*4] - USER_EVENT);\r
+ if ((e + nDataEvents) < RecorderDataPtr->maxEvents)\r
{\r
(void)memset(& RecorderDataPtr->eventData[e*4], 0, 4 + 4 * nDataEvents);\r
}\r
{\r
return;\r
}\r
-\r
-#if (INCLUDE_EVENT_STATS == 1)\r
- eventCount[RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex*4]]++;\r
-#endif\r
-\r
+ \r
RecorderDataPtr->numEvents++;\r
\r
RecorderDataPtr->nextFreeIndex++;\r
* The parameter param_maxDTS should be 0xFF for 8-bit dts or 0xFFFF for\r
* events with 16-bit dts fields.\r
*****************************************************************************/\r
-uint32_t prvTraceGetDTS(uint32_t param_maxDTS)\r
+uint16_t prvTraceGetDTS(uint16_t param_maxDTS)\r
{\r
- XTSEvent* xts; \r
- int32_t dts = 0;\r
- uint32_t old_ts = RecorderDataPtr->absTimeLastEvent;\r
+ static uint32_t old_timestamp = 0;\r
+ XTSEvent* xts = 0;\r
+ uint32_t dts = 0;\r
+ uint32_t timestamp = 0;\r
\r
if (RecorderDataPtr->frequency == 0)\r
{\r
if (xTaskGetSchedulerState() != 0) /* Has the scheduler started? */\r
{ \r
RecorderDataPtr->frequency = \r
- HWTC_PERIOD * configTICK_RATE_HZ / HWTC_DIVISOR; \r
+ (uint32_t)HWTC_PERIOD * (uint32_t)configTICK_RATE_HZ / (uint32_t)HWTC_DIVISOR; \r
}\r
#endif\r
}\r
\r
/**************************************************************************\r
- * The below statement reads the timestamp from the timer port module. Note \r
- * the modulo operation on RecorderDataPtr->frequency, which makes the overflow \r
- * case (if (dts < 0)) occur every 1 sec.\r
- * This is to make it easier to test. The overflow will happen sooner\r
- * or later anyway.\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
- if (RecorderDataPtr->frequency > 0)\r
- {\r
- RecorderDataPtr->absTimeLastEvent = \r
- uiTracePortGetTimeStamp() % RecorderDataPtr->frequency;\r
- }\r
- else\r
+ \r
+ uiTracePortGetTimeStamp(×tamp);\r
+\r
+ /***************************************************************************\r
+ * This condition is only for the Win32 port, since it does not use the tick\r
+ * count but instead only HWTC_COUNT (from the performance counter).\r
+ * Without this condition, you sometimes get a negative dts value (converted\r
+ * into a very large unsiged value) when the performance counter wraps \r
+ * around. In other "normal" ports also using the FreeRTOS tick counter, this \r
+ * condition can not occur and therefore has no impact.\r
+ ***************************************************************************/\r
+ if (timestamp < old_timestamp)\r
{\r
- /* Special case if the recorder has not yet started (frequency may be uninitialized, i.e., zero)\r
- The modulo operation is not necessary on the first events, since it is surely much less than \r
- one second since startup. */\r
- RecorderDataPtr->absTimeLastEvent = uiTracePortGetTimeStamp(); \r
+ timestamp += RecorderDataPtr->frequency;\r
}\r
\r
- dts = (int32_t)(RecorderDataPtr->absTimeLastEvent - old_ts);\r
\r
- if (dts < 0) /* when the modulo operation wraps around (after 1 second) */\r
+ dts = timestamp - old_timestamp;\r
+ old_timestamp = timestamp;\r
+ \r
+ if (RecorderDataPtr->frequency > 0)\r
{\r
- if (RecorderDataPtr->frequency == 0)\r
+ /* Check if dts > 1 second */\r
+ if (dts > RecorderDataPtr->frequency)\r
{\r
- /* Frequency should normally be initialized on the first logged event after\r
- the FreeRTOS scheduler has started. In this case, it has not yet been \r
- initialized (frequency is 0) and the dts (time since last event) was \r
- negative. This is an illegal combination that indicates a problem in \r
- uiTracePortGetTimeStamp, probably due to incorrect HWTC macros in trcPort.h.\r
-\r
- The dts variable normally becomes negative when the modulo operation wraps\r
- around, but since the modulo operation is not used in this case (only used \r
- if frequency has been set), dts only becomes negative if\r
- uiTracePortGetTimeStamp returned a smaller value than last time.\r
- This is an error. The values returned by uiTracePortGetTimeStamp should be\r
- monotonically incresing (since it is a timestamp). */\r
-\r
- vTraceError("Timestamping error, see comment in prvTraceGetDTS (trcBase.c)");\r
- return 0;\r
+ /* More than 1 second has passed */\r
+ RecorderDataPtr->absTimeLastEventSecond += dts / RecorderDataPtr->frequency;\r
+ /* The part that is not an entire second is added to absTimeLastEvent */\r
+ RecorderDataPtr->absTimeLastEvent += dts % RecorderDataPtr->frequency;\r
+ }\r
+ else\r
+ RecorderDataPtr->absTimeLastEvent += dts;\r
+ \r
+ /* Check if absTimeLastEvent >= 1 second */\r
+ if (RecorderDataPtr->absTimeLastEvent >= RecorderDataPtr->frequency)\r
+ {\r
+ /* RecorderDataPtr->absTimeLastEvent is more than or equal to 1 second, but always less than 2 seconds */\r
+ RecorderDataPtr->absTimeLastEventSecond++;\r
+ RecorderDataPtr->absTimeLastEvent -= RecorderDataPtr->frequency;\r
+ /* RecorderDataPtr->absTimeLastEvent is now less than 1 second */\r
}\r
- dts = (int32_t)(RecorderDataPtr->frequency - old_ts + RecorderDataPtr->absTimeLastEvent);\r
-\r
- /* This is good for 136 years (incremented every 1 second) */\r
- RecorderDataPtr->absTimeLastEventSecond++; \r
+ }\r
+ else\r
+ {\r
+ /* Special case if the recorder has not yet started (frequency may be uninitialized, i.e., zero) */\r
+ RecorderDataPtr->absTimeLastEvent = timestamp;\r
}\r
\r
/* If the dts (time since last event) does not fit in event->dts (only 8 or 16 bits) */\r
- if (dts > (int32_t)param_maxDTS)\r
+ if (dts > param_maxDTS)\r
{\r
/* Create an XTS event (eXtended TimeStamp) containing the higher dts bits*/\r
xts = (XTSEvent*) xTraceNextFreeEventBufferSlot();\r
}\r
}\r
\r
- return dts % (param_maxDTS + 1);\r
+ return (uint16_t)(dts % (param_maxDTS + 1));\r
}\r
\r
-\r
/*******************************************************************************\r
* prvTraceLookupSymbolTableEntry\r
*\r
******************************************************************************/\r
void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength)\r
{\r
- char c;\r
- int32_t length = 0;\r
- int32_t crc = 0;\r
+ unsigned char c;\r
+ int length = 0;\r
+ int crc = 0;\r
if ( pname != (const char *) 0 )\r
{\r
for ( ; (c = *pname++) != '\0'; )\r
{\r
- crc += (int32_t)c;\r
+ crc += c;\r
length++;\r
}\r
}\r
*plength = (uint8_t)length;\r
}\r
\r
-#endif
\ No newline at end of file
+#endif\r
/*******************************************************************************\r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcKernel.c\r
*\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
-#include "FreeRTOS.h"\r
+#include "trcUser.h"\r
#include "task.h"\r
-#include "trcKernel.h"\r
\r
#if (configUSE_TRACE_FACILITY == 1)\r
\r
+\r
+\r
/******************************************************************************\r
* TraceObjectClassTable\r
* Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).\r
objectHandleType handle_of_last_logged_task = 0;\r
uint8_t inExcludedTask = 0;\r
\r
+static uint8_t prvTraceIsObjectExcluded(traceObjectClass, uint32_t);\r
+\r
+/*******************************************************************************\r
+ * prvTraceIsObjectExcluded\r
+ *\r
+ * Private function that accepts an object class and an object number and uses\r
+ * that to determine if the object has been flagged as excluded.\r
+ ******************************************************************************/\r
+static uint8_t prvTraceIsObjectExcluded(traceObjectClass objectClass, uint32_t objectNumber)\r
+{\r
+ switch(objectClass)\r
+ {\r
+ case TRACE_CLASS_QUEUE:\r
+ return GET_QUEUE_FLAG_ISEXCLUDED(objectNumber);\r
+ break;\r
+ case TRACE_CLASS_SEMAPHORE:\r
+ return GET_SEMAPHORE_FLAG_ISEXCLUDED(objectNumber);\r
+ break;\r
+ case TRACE_CLASS_MUTEX:\r
+ return GET_MUTEX_FLAG_ISEXCLUDED(objectNumber);\r
+ break;\r
+ case TRACE_CLASS_TASK:\r
+ return GET_TASK_FLAG_ISEXCLUDED(objectNumber);\r
+ break;\r
+ }\r
+ return 0;\r
+}\r
+\r
+#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1\r
+/*******************************************************************************\r
+ * vTraceStoreTaskReady\r
+ *\r
+ * This function stores a ready state for the task handle sent in as parameter.\r
+ ******************************************************************************/\r
+void vTraceStoreTaskReady(objectHandleType handle)\r
+{\r
+ uint16_t dts3;\r
+ TREvent* tr;\r
+\r
+ if (!GET_TASK_FLAG_ISEXCLUDED(handle))\r
+ {\r
+ dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
+ if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
+ {\r
+ tr = (TREvent*)xTraceNextFreeEventBufferSlot();\r
+\r
+ if (tr != NULL)\r
+ {\r
+ tr->type = TR_TASK_READY;\r
+ tr->dts = dts3;\r
+ tr->objHandle = handle;\r
+\r
+ prvTraceUpdateCounters(); \r
+ }\r
+ }\r
+ }\r
+}\r
+#endif\r
+\r
/*******************************************************************************\r
* vTraceStoreKernelCall\r
*\r
* This is the main integration point for storing FreeRTOS kernel calls, and\r
* is called by the hooks in FreeRTOS.h (see trcKernel.h for event codes).\r
******************************************************************************/\r
-void vTraceStoreKernelCall(uint32_t ecode, uint32_t objectNumber)\r
+void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber)\r
{\r
KernelCall * kse;\r
uint16_t dts1;\r
{\r
return;\r
}\r
-\r
- /* This checks if this is the first kernel call after a call to\r
- vTraceTaskInstanceIsFinished. In that case, calls to this kernel service \r
- with this specific kernel object become the "instance finish event"\r
- (IFE) of the calling task.*/\r
- if (GET_TASK_FLAG_MARKIFE(handle_of_last_logged_task))\r
- {\r
- /* Reset the flag - this has been handled now */\r
- CLEAR_TASK_FLAG_MARKIFE(handle_of_last_logged_task);\r
-\r
- /* Store the kernel service tagged as instance finished event */\r
- PROPERTY_TASK_IFE_SERVICECODE(handle_of_last_logged_task) = \r
- (uint8_t)ecode; \r
-\r
- /* Store the handle of the specific kernel object */\r
- PROPERTY_TASK_IFE_OBJHANDLE(handle_of_last_logged_task) =\r
- (objectHandleType)objectNumber; \r
- }\r
\r
- if (RecorderDataPtr->recorderActive && (!inExcludedTask || nISRactive))\r
+ if (RecorderDataPtr->recorderActive)\r
{\r
- dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);\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
+ /* Make sure ISRs never change the IFE flags of tasks */\r
+ if (!nISRactive)\r
+ {\r
+ /* This checks if this is the first kernel call after a call to\r
+ vTraceTaskInstanceIsFinished. In that case, calls to this kernel service \r
+ with this specific kernel object become the "instance finish event"\r
+ (IFE) of the calling task.*/\r
+ if (GET_TASK_FLAG_MARKIFE(handle_of_last_logged_task))\r
+ {\r
+ /* Reset the flag - this has been handled now */\r
+ CLEAR_TASK_FLAG_MARKIFE(handle_of_last_logged_task);\r
\r
- if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
- { \r
- kse = (KernelCall*) xTraceNextFreeEventBufferSlot();\r
- if (kse != NULL)\r
+ /* Store the kernel service tagged as instance finished event */\r
+ PROPERTY_TASK_IFE_SERVICECODE(handle_of_last_logged_task) = \r
+ (uint8_t)ecode; \r
+\r
+ /* Store the handle of the specific kernel object */\r
+ PROPERTY_TASK_IFE_OBJHANDLE(handle_of_last_logged_task) =\r
+ (objectHandleType)objectNumber; \r
+ }\r
+ }\r
+ \r
+ /* Check if the referenced object or the event code is excluded */\r
+ if (!prvTraceIsObjectExcluded(objectClass, objectNumber) && !GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))\r
{\r
- kse->dts = dts1;\r
- kse->type = (uint8_t)ecode;\r
- kse->objHandle = (uint8_t)objectNumber;\r
- prvTraceUpdateCounters();\r
+ trcCRITICAL_SECTION_BEGIN();\r
+ dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
+\r
+ if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\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
+ prvTraceUpdateCounters();\r
+ }\r
+ }\r
+ trcCRITICAL_SECTION_END();\r
}\r
}\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
******************************************************************************/\r
-void vTraceStoreKernelCallWithParam(uint32_t evtcode, \r
- uint32_t objectNumber, \r
+void vTraceStoreKernelCallWithParam(uint32_t evtcode,\r
+ traceObjectClass objectClass,\r
+ uint32_t objectNumber,\r
uint8_t param)\r
{\r
KernelCallWithParamAndHandle * kse;\r
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && \r
(! inExcludedTask || nISRactive))\r
{\r
- dts2 = (uint8_t)prvTraceGetDTS(0xFF);\r
+ /* Check if the referenced object or the event code is excluded */\r
+ if (!prvTraceIsObjectExcluded(objectClass, objectNumber) && !GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))\r
+ {\r
+ trcCRITICAL_SECTION_BEGIN();\r
+ dts2 = (uint8_t)prvTraceGetDTS(0xFF);\r
\r
- if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\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
- prvTraceUpdateCounters(); \r
+ if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\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
+ prvTraceUpdateCounters(); \r
+ }\r
}\r
+ trcCRITICAL_SECTION_END();\r
}\r
}\r
}\r
\r
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task \r
&& (! inExcludedTask || nISRactive))\r
- { \r
- dts6 = (uint8_t)prvTraceGetDTS(0xFF);\r
+ {\r
+ /* Check if the event code is excluded */\r
+ if (!GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))\r
+ {\r
+ trcCRITICAL_SECTION_BEGIN();\r
+ dts6 = (uint8_t)prvTraceGetDTS(0xFF);\r
\r
- if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
- { \r
- kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot();\r
- if (kse != NULL)\r
- {\r
- kse->dts = dts6;\r
- kse->type = (uint8_t)evtcode;\r
- kse->param = param;\r
- prvTraceUpdateCounters(); \r
+ if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
+ { \r
+ kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot();\r
+ if (kse != NULL)\r
+ {\r
+ kse->dts = dts6;\r
+ kse->type = (uint8_t)evtcode;\r
+ kse->param = param;\r
+ prvTraceUpdateCounters(); \r
+ }\r
}\r
+ trcCRITICAL_SECTION_END();\r
}\r
}\r
}\r
\r
+objectHandleType handle_of_running_task = 0;\r
+\r
/*******************************************************************************\r
* vTraceStoreTaskswitch\r
- * Called by the scheduler, from the SWITCHED_OUT hook.\r
- * At this point interrupts are disabled, so no need to disable interrupts.\r
+ * Called by the scheduler from the SWITCHED_OUT hook, and by uiTraceStart.\r
+ * At this point interrupts are assumed to be disabled!\r
******************************************************************************/\r
void vTraceStoreTaskswitch(void)\r
{\r
uint16_t dts3;\r
- TSEvent* ts;\r
- static objectHandleType handle_of_running_task = 0;\r
+ TSEvent* ts; \r
int8_t skipEvent = 0;\r
+ uint32_t schedulerState = 0;\r
+ \r
+ /*************************************************************************** \r
+ This is used to detect if a high-priority ISRs is illegally using the \r
+ recorder ISR trace functions (vTraceStoreISRBegin and ...End) while the \r
+ recorder is busy with a task-level event or lower priority ISR event.\r
+ \r
+ If this is detected, it triggers a call to vTraceError with the error \r
+ "Illegal call to vTraceStoreISRBegin/End". If you get this error, it means\r
+ that the macro taskENTER_CRITICAL does not disable this ISR, as required.\r
+ You can solve this by adjusting the value of the FreeRTOS constant\r
+ configMAX_SYSCALL_INTERRUPT_PRIORITY, which is defined in FreeRTOSConfig.h\r
+\r
+ Note: Setting recorder_busy is normally handled in our macros\r
+ trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this \r
+ function since critical sections should not be used in the context switch \r
+ event...) \r
+ ***************************************************************************/\r
+ recorder_busy++; \r
\r
- if (xTaskGetSchedulerState() == 0)\r
+ schedulerState = xTaskGetSchedulerState();\r
+\r
+ if (schedulerState == 0)\r
{\r
/* This occurs on the very first taskswitch event, generated by \r
vTraceStart and uiTraceStart if the scheduler is not yet started.\r
This creates a dummy "(startup)" task entry internally in the\r
recorder */\r
+ if (handle_of_running_task == 0)\r
+ {\r
+ handle_of_running_task = xTraceGetObjectHandle(TRACE_CLASS_TASK);\r
\r
- handle_of_running_task = xTraceGetObjectHandle(TRACE_CLASS_TASK);\r
- vTraceSetObjectName(TRACE_CLASS_TASK, \r
- handle_of_running_task,\r
- "(startup)");\r
- vTraceSetPriorityProperty(TRACE_CLASS_TASK,\r
- handle_of_running_task,\r
- 0);\r
+ vTraceSetObjectName(TRACE_CLASS_TASK, \r
+ handle_of_running_task,\r
+ "(startup)");\r
+\r
+ vTraceSetPriorityProperty(TRACE_CLASS_TASK,\r
+ handle_of_running_task,\r
+ 0);\r
+ } \r
}\r
else\r
{ \r
handle_of_running_task = \r
(objectHandleType)uxTaskGetTaskNumber(xTaskGetCurrentTaskHandle());\r
}\r
-\r
+ \r
/* Skip the event if the task has been excluded, using vTraceExcludeTask */\r
if (GET_TASK_FLAG_ISEXCLUDED(handle_of_running_task))\r
{ \r
skipEvent = 1;\r
inExcludedTask = 1; \r
- } \r
+ }\r
+ else\r
+ inExcludedTask = 0;\r
+ \r
\r
/* Skip the event if the same task is scheduled */\r
if (handle_of_running_task == handle_of_last_logged_task)\r
{\r
skipEvent = 1;\r
}\r
- \r
- \r
+ \r
if (! RecorderDataPtr->recorderActive)\r
{\r
skipEvent = 1;\r
\r
/* If this event should be logged, log it! */\r
if (skipEvent == 0) \r
- {\r
+ { \r
dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
\r
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */\r
- { \r
- inExcludedTask = 0;\r
-\r
- handle_of_last_logged_task = handle_of_running_task;\r
- \r
+ {\r
+ handle_of_last_logged_task = handle_of_running_task; \r
ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
\r
if (ts != NULL)\r
prvTraceUpdateCounters(); \r
}\r
}\r
- }\r
- \r
+ } \r
+\r
+ /* See comment on recorder_busy++ above. */\r
+ recorder_busy--; \r
}\r
\r
/*******************************************************************************\r
name = PROPERTY_NAME_GET(objectclass, handle);\r
\r
idx = prvTraceOpenSymbol(name, 0);\r
-\r
- ce = (ObjCloseNameEvent*) xTraceNextFreeEventBufferSlot();\r
+ \r
+ // Interrupt disable not necessary, already done in trcHooks.h macro\r
+ ce = (ObjCloseNameEvent*) xTraceNextFreeEventBufferSlot(); \r
if (ce != NULL)\r
{\r
ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass;\r
ce->symbolIndex = idx;\r
prvTraceUpdateCounters();\r
}\r
+ \r
}\r
\r
void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle, \r
return;\r
}\r
\r
+ // Interrupt disable not necessary, already done in trcHooks.h macro\r
pe = (ObjClosePropEvent*) xTraceNextFreeEventBufferSlot();\r
if (pe != NULL)\r
{\r
return PROPERTY_OBJECT_STATE(objectclass, id);\r
}\r
\r
-\r
-#endif
\ No newline at end of file
+#endif\r
/*******************************************************************************\r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcPort.c\r
*\r
* , hobbyists or early-phase startups) we have an attractive offer: \r
* Provide a hardware timer port and get a FREE single-user licence for\r
* FreeRTOS+Trace Professional Edition. Read more about this offer at \r
- * www.percepio.se or contact us directly at support@percepio.se.\r
+ * www.percepio.com or contact us directly at support@percepio.com.\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
-#include "FreeRTOS.h"\r
-#include "trcPort.h"\r
+\r
#include "trcUser.h"\r
\r
#if (configUSE_TRACE_FACILITY == 1)\r
static char* prvFileName = NULL;\r
#endif\r
\r
+\r
/*******************************************************************************\r
* uiTraceTickCount\r
*\r
* OFFER FROM PERCEPIO:\r
* For silicon companies and non-corporate FreeRTOS users (researchers, students\r
* , hobbyists or early-phase startups) we have an attractive offer: \r
- * Provide a hardware timer port and get a FREE single-user licence for\r
+ * Provide a hardware timer port and get a FREE single-user license for\r
* FreeRTOS+Trace Professional Edition. Read more about this offer at \r
- * www.percepio.se or contact us directly at support@percepio.se.\r
+ * www.percepio.com or contact us directly at support@percepio.com.\r
******************************************************************************/\r
-uint32_t uiTracePortGetTimeStamp()\r
+void uiTracePortGetTimeStamp(uint32_t *pTimestamp)\r
{\r
- /* Keep these static to avoid using more stack than necessary */\r
- static uint32_t last_timestamp = 0;\r
- static uint32_t timestamp;\r
-\r
+ static uint32_t last_traceTickCount = 0;\r
+ static uint32_t last_hwtc_count = 0;\r
+ uint32_t traceTickCount = 0;\r
+ uint32_t hwtc_count = 0;\r
+ \r
+ /* Retrieve HWTC_COUNT only once since the same value should be used all throughout this function. */\r
#if (HWTC_COUNT_DIRECTION == DIRECTION_INCREMENTING)\r
- timestamp = ((uiTraceTickCount * HWTC_PERIOD) + HWTC_COUNT) / HWTC_DIVISOR;\r
-#else\r
-#if (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING)\r
- timestamp = ((uiTraceTickCount * HWTC_PERIOD) + (HWTC_PERIOD - HWTC_COUNT)) / HWTC_DIVISOR;\r
+ hwtc_count = HWTC_COUNT;\r
+#elif (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING)\r
+ hwtc_count = HWTC_PERIOD - HWTC_COUNT;\r
#else\r
Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly!\r
Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING\r
#endif\r
-#endif\r
+ \r
+ if (last_traceTickCount - uiTraceTickCount - 1 < 0x80000000)\r
+ {\r
+ /* This means last_traceTickCount is higher than uiTraceTickCount,\r
+ so we have previously compensated for a missed tick.\r
+ Therefore we use the last stored value because that is more accurate. */\r
+ traceTickCount = last_traceTickCount;\r
+ }\r
+ else\r
+ {\r
+ /* Business as usual */\r
+ traceTickCount = uiTraceTickCount;\r
+ }\r
\r
- /* May occur due to overflow, if the update of uiTraceTickCount has been \r
+ /* Check for overflow. May occur if the update of uiTraceTickCount has been \r
delayed due to disabled interrupts. */\r
- if (timestamp < last_timestamp)\r
+ if (traceTickCount == last_traceTickCount && hwtc_count < last_hwtc_count)\r
{\r
- timestamp += (HWTC_PERIOD / HWTC_DIVISOR);\r
+ /* A trace tick has occurred but not been executed by the kernel, so we compensate manually. */\r
+ traceTickCount++;\r
}\r
-\r
- last_timestamp = timestamp;\r
-\r
- return timestamp;\r
+ \r
+ /* Check if the return address is OK, then we perform the calculation. */\r
+ if (pTimestamp)\r
+ {\r
+ /* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */\r
+ *pTimestamp = traceTickCount * (HWTC_PERIOD / HWTC_DIVISOR);\r
+ /* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / HWTC_DIVISOR. */\r
+ *pTimestamp += (hwtc_count + traceTickCount * (HWTC_PERIOD % HWTC_DIVISOR)) / HWTC_DIVISOR;\r
+ }\r
+ \r
+ /* Store the previous values. */\r
+ last_traceTickCount = traceTickCount;\r
+ last_hwtc_count = hwtc_count;\r
}\r
\r
/*******************************************************************************\r
/*******************************************************************************\r
- * FreeRTOS+Trace v2.2.3 Recorder Library\r
- * Percepio AB, www.percepio.se\r
+ * FreeRTOS+Trace v2.3.0 Recorder Library\r
+ * Percepio AB, www.percepio.com\r
*\r
* trcUser.c\r
*\r
*\r
* FreeRTOS+Trace is available as Free Edition and in two premium editions.\r
* You may use the premium features during 30 days for evaluation.\r
- * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads\r
+ * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/\r
*\r
* Copyright Percepio AB, 2012.\r
- * www.percepio.se\r
+ * www.percepio.com\r
******************************************************************************/\r
\r
-#include "FreeRTOS.h"\r
+#include <string.h>\r
+#include <stdarg.h>\r
+\r
+#include "trcUser.h"\r
#include "task.h"\r
-#include "queue.h"\r
+#include "semphr.h"\r
\r
#if (configUSE_TRACE_FACILITY == 1)\r
\r
-#include "string.h"\r
-#include "stdarg.h"\r
-#include "trcUser.h"\r
-#include "trcKernel.h"\r
-\r
extern uint8_t inExcludedTask;\r
extern uint8_t nISRactive;\r
extern uint8_t handle_of_last_logged_task;\r
extern unsigned char ucQueueGetQueueType(void*);\r
extern unsigned char ucQueueGetQueueNumber(void*);\r
extern char* traceErrorMessage;\r
-\r
static void vTraceMonitorTask(void);\r
+static void prvTraceExcludeOrIncludeKernelServiceFromTrace(traceKernelService, uint8_t);\r
\r
/*******************************************************************************\r
* vTraceMonitorTask\r
{\r
sprintf(localsprintbuffer, \r
"\n\r[FreeRTOS+Trace] Event count: %d, Duration: %d ms. [%d ticks]\n\r", \r
- RecorderDataPtr->numEvents, \r
- RecorderDataPtr->absTimeLastEventSecond*1000 + (RecorderDataPtr->absTimeLastEvent*1000)/ RecorderDataPtr->frequency, xTaskGetTickCount());\r
+ (int)RecorderDataPtr->numEvents, \r
+ (int)(RecorderDataPtr->absTimeLastEventSecond*1000 + (RecorderDataPtr->absTimeLastEvent*1000)/ RecorderDataPtr->frequency), (int)xTaskGetTickCount());\r
vTraceConsoleMessage(localsprintbuffer);\r
}\r
\r
******************************************************************************/\r
void vTraceClear(void)\r
{\r
- taskENTER_CRITICAL();\r
-\r
+ trcCRITICAL_SECTION_BEGIN();\r
+ \r
RecorderDataPtr->absTimeLastEvent = 0;\r
RecorderDataPtr->nextFreeIndex = 0;\r
RecorderDataPtr->numEvents = 0;\r
RecorderDataPtr->bufferIsFull = 0;\r
\r
- taskEXIT_CRITICAL();\r
+ trcCRITICAL_SECTION_END();\r
+ \r
}\r
\r
/*******************************************************************************\r
* vTraceStartStatusMonitor\r
*\r
- * This starts a task to monitor the state of the recorder. \r
+ * This starts a task to monitor the state of½ the recorder. \r
* This task periodically prints a line to the console window, which shows the \r
* number of events recorded and the latest timestamp. This task\r
* calls vTracePortEnd when the recorder has been stopped, where custom\r
* Any error message is also presented when opening a trace file in \r
* FreeRTOS+Trace v2.2.2 or later.\r
******************************************************************************/\r
+\r
uint32_t uiTraceStart(void)\r
{ \r
if (traceErrorMessage == NULL)\r
{\r
+ trcCRITICAL_SECTION_BEGIN();\r
RecorderDataPtr->recorderActive = 1;\r
vTraceStoreTaskswitch(); /* Register the currently running task */\r
+ trcCRITICAL_SECTION_END();\r
}\r
\r
return RecorderDataPtr->recorderActive;\r
}\r
\r
/*******************************************************************************\r
- * vTraceExcludeTask\r
- * Excludes a task from the recording using a flag in the Object Property Table.\r
- * This can be useful if some irrelevant task is very frequent and is "eating\r
- * up the buffer". This should be called after the task has been created, but \r
- * preferably before starting the FreeRTOS scheduler.\r
+ * prvTraceExcludeOrIncludeKernelServiceFromTrace\r
+ * \r
+ * Includes or excludes all events that is related to the kernel service.\r
******************************************************************************/\r
-void vTraceExcludeTaskFromSchedulingTrace(const char* name)\r
+static void prvTraceExcludeOrIncludeKernelServiceFromTrace(traceKernelService kernelService, uint8_t flag)\r
{\r
- objectHandleType i;\r
- int32_t found = 0;\r
- for (i = 1; i < RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_TASK]; i++)\r
+ switch(kernelService)\r
{\r
- if (strncmp(name, \r
- PROPERTY_NAME_GET(TRACE_CLASS_TASK, i), \r
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[TRACE_CLASS_TASK]) == 0)\r
+ case TRACE_KERNEL_SERVICE_TASK_CREATE:\r
+ if (flag)\r
{\r
- found = 1;\r
- SET_TASK_FLAG_ISEXCLUDED(i);\r
- break;\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_TASK);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK);\r
}\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_TASK);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_TASK_DELETE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_TASK);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_TASK);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_TASK_DELAY:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY_UNTIL);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY_UNTIL);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_PRIORITY_SET:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_PRIORITY_SET);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_PRIORITY_SET);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_TASK_SUSPEND:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_SUSPEND);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_SUSPEND);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_TASK_RESUME:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_RESUME);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_RESUME_FROM_ISR);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_RESUME);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_RESUME_FROM_ISR);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_QUEUE_CREATE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_QUEUE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_QUEUE);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_QUEUE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_QUEUE);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_QUEUE_DELETE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_QUEUE);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_QUEUE);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_QUEUE_SEND:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_QUEUE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_QUEUE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_QUEUE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_QUEUE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_QUEUE);\r
+ \r
+ \r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_QUEUE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_QUEUE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_QUEUE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_QUEUE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_QUEUE);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_QUEUE_RECEIVE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_QUEUE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_QUEUE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_QUEUE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_QUEUE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_QUEUE);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_QUEUE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_QUEUE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_QUEUE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_QUEUE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_QUEUE);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_QUEUE_PEEK:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_QUEUE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_SEMAPHORE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_MUTEX);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_QUEUE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_SEMAPHORE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_MUTEX);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_MUTEX_CREATE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_MUTEX);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_MUTEX);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_MUTEX);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_MUTEX);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_MUTEX_DELETE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_MUTEX);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_MUTEX);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_MUTEX_GIVE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_MUTEX);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_MUTEX);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_MUTEX);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_MUTEX);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_MUTEX);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_MUTEX);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_MUTEX);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_MUTEX);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_MUTEX);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_MUTEX);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_MUTEX_TAKE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_MUTEX);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_MUTEX);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_MUTEX);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_MUTEX);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_MUTEX);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_MUTEX);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_MUTEX);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_MUTEX);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_MUTEX);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_MUTEX);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_SEMAPHORE_CREATE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_SEMAPHORE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_SEMAPHORE);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_SEMAPHORE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_SEMAPHORE);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_SEMAPHORE_DELETE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_SEMAPHORE);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_SEMAPHORE);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_SEMAPHORE_GIVE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_SEMAPHORE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_SEMAPHORE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_SEMAPHORE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_SEMAPHORE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_SEMAPHORE);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_SEMAPHORE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_SEMAPHORE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_SEMAPHORE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_SEMAPHORE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_SEMAPHORE);\r
+ }\r
+ break;\r
+ case TRACE_KERNEL_SERVICE_SEMAPHORE_TAKE:\r
+ if (flag)\r
+ {\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_SEMAPHORE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_SEMAPHORE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_SEMAPHORE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_SEMAPHORE);\r
+ SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_SEMAPHORE);\r
+ }\r
+ else\r
+ {\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_SEMAPHORE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_SEMAPHORE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_SEMAPHORE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_SEMAPHORE);\r
+ CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_SEMAPHORE);\r
+ }\r
+ break;\r
}\r
- if (!found)\r
- {\r
- vTraceError("Could not find task to exclude!");\r
- }\r
+}\r
+\r
+/******************************************************************************\r
+ * vTraceExclude______FromTrace\r
+ *\r
+ * Excludes a task or object from the trace.\r
+ * This can be useful if some irrelevant task is very frequent and is "eating\r
+ * up the buffer". This should be called after the task has been created, but \r
+ * before starting the FreeRTOS scheduler.\r
+ *****************************************************************************/\r
+void vTraceExcludeQueueFromTrace(void* handle)\r
+{\r
+ SET_QUEUE_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle));\r
+}\r
+\r
+void vTraceExcludeSemaphoreFromTrace(void* handle)\r
+{\r
+ SET_SEMAPHORE_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle));\r
+}\r
+\r
+void vTraceExcludeMutexFromTrace(void* handle)\r
+{\r
+ SET_MUTEX_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle));\r
+}\r
+\r
+void vTraceExcludeTaskFromTrace(void* handle)\r
+{\r
+ SET_TASK_FLAG_ISEXCLUDED(uxTaskGetTaskNumber(handle));\r
+}\r
+\r
+void vTraceExcludeKernelServiceFromTrace(traceKernelService kernelService)\r
+{\r
+ prvTraceExcludeOrIncludeKernelServiceFromTrace(kernelService, 1);\r
+}\r
+\r
+/******************************************************************************\r
+ * vTraceInclude______InTrace\r
+ *\r
+ * Includes a task, object or kernel service in the trace. This is only\r
+ * necessary if the task or object has been previously exluded.\r
+ *****************************************************************************/\r
+void vTraceIncludeQueueInTrace(void* handle)\r
+{\r
+ CLEAR_QUEUE_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle));\r
+}\r
+\r
+void vTraceIncludeSemaphoreInTrace(void* handle)\r
+{\r
+ CLEAR_SEMAPHORE_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle));\r
+}\r
+\r
+void vTraceIncludeMutexInTrace(void* handle)\r
+{\r
+ CLEAR_MUTEX_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle));\r
+}\r
+\r
+void vTraceIncludeTaskInTrace(void* handle)\r
+{\r
+ CLEAR_TASK_FLAG_ISEXCLUDED(uxTaskGetTaskNumber(handle));\r
+}\r
+\r
+void vTraceIncludeKernelServiceInTrace(traceKernelService kernelService)\r
+{\r
+ prvTraceExcludeOrIncludeKernelServiceFromTrace(kernelService, 0);\r
}\r
\r
/*******************************************************************************\r
* ...\r
* void ISR_handler()\r
* {\r
- * portENTER_CRITICAL(); // Required if nested ISRs are allowed\r
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1);\r
- * portEXIT_CRITICAL();\r
* ...\r
- * portENTER_CRITICAL(); // Required if nested ISRs are allowed\r
* vTraceStoreISREnd();\r
- * portEXIT_CRITICAL();\r
* }\r
+ *\r
+ * NOTE: To safely record ISRs, you need to make sure that all traced \r
+ * interrupts actually are disabled by trcCRITICAL_SECTION_BEGIN(), which \r
+ * typically is mapped to portENTER_CRITICAL(), which uses the macro \r
+ * portDISABLE_INTERRUPTS. However, in some ports of FreeRTOS and depending on \r
+ * FreeRTOS configuration, this does not disable high priority interrupts!\r
+ * If an ISR calls vTraceStoreISRBegin while the recorder is busy, it will\r
+ * stop the recording and give an error message.\r
******************************************************************************/\r
-void vTraceSetISRProperties(objectHandleType handle, char* name, char priority)\r
+void vTraceSetISRProperties(objectHandleType handle, const char* name, char priority)\r
{\r
vTraceSetObjectName(TRACE_CLASS_ISR, handle, name);\r
vTraceSetPriorityProperty(TRACE_CLASS_ISR, handle, priority);\r
/*******************************************************************************\r
* vTraceStoreISRBegin\r
* \r
- * Registers the beginning of an Interrupt Service Routine. This must not be\r
- * interrupted by another ISR containing recorder library calls, so if allowing\r
- * nested ISRs this must be called with interrupts disabled.\r
+ * Registers the beginning of an Interrupt Service Routine.\r
*\r
* Example:\r
* #define ID_ISR_TIMER1 1 // lowest valid ID is 1\r
* ...\r
* void ISR_handler()\r
* {\r
- * portENTER_CRITICAL(); // Required if nested ISRs are allowed\r
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1);\r
- * portEXIT_CRITICAL();\r
* ...\r
- * portENTER_CRITICAL(); // Required if nested ISRs are allowed\r
* vTraceStoreISREnd();\r
- * portEXIT_CRITICAL();\r
* }\r
+ *\r
+ * NOTE: You need to make sure that any traced interrupts actually are \r
+ * disabled by trcCRITICAL_SECTION_BEGIN(), i.e., taskENTER_CRITICAL() which\r
+ * uses portDISABLE_INTERRUPTS(). \r
+ * In some ports of FreeRTOS, this does not disable high-priority interrupts,\r
+ * i.e., with priorities above configMAX_SYSCALL_INTERRUPT_PRIORITY.\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
\r
+ if (recorder_busy)\r
+ {\r
+ vTraceError("Illegal call to vTraceStoreISRBegin/End");\r
+ return;\r
+ }\r
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
{ \r
+ trcCRITICAL_SECTION_BEGIN();\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
isrstack[nISRactive] = handle;\r
{ \r
/* This should not occur unless something is very wrong */ \r
vTraceError("Too many nested interrupts!");\r
- }\r
+ } \r
}\r
+ trcCRITICAL_SECTION_END(); \r
+ }\r
+}\r
+\r
+\r
+#if (SELECTED_PORT == PORT_ARM_CortexM)\r
+\r
+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
+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
+ return 0; \r
}\r
\r
+#endif\r
+\r
/*******************************************************************************\r
* vTraceStoreISREnd\r
* \r
- * Registers the end of an Interrupt Service Routine. This must not be\r
- * interrupted by another ISR containing recorder library calls, so if allowing\r
- * nested ISRs this must be called with interrupts disabled.\r
+ * Registers the end of an Interrupt Service Routine. \r
*\r
* Example:\r
* #define ID_ISR_TIMER1 1 // lowest valid ID is 1\r
* ...\r
* void ISR_handler()\r
* {\r
- * portENTER_CRITICAL(); // Required if nested ISRs are allowed\r
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1);\r
- * portEXIT_CRITICAL();\r
* ...\r
- * portENTER_CRITICAL(); // Required if nested ISRs are allowed\r
* vTraceStoreISREnd();\r
- * portEXIT_CRITICAL();\r
* }\r
+ *\r
+ * NOTE: You need to make sure that any traced interrupts actually are \r
+ * disabled by trcCRITICAL_SECTION_BEGIN(), i.e., taskENTER_CRITICAL() which\r
+ * uses portDISABLE_INTERRUPTS(). \r
+ * In some ports of FreeRTOS, this does not disable high-priority interrupts,\r
+ * i.e., with priorities above configMAX_SYSCALL_INTERRUPT_PRIORITY.\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
\r
+ if (recorder_busy)\r
+ {\r
+ vTraceError("Illegal call to vTraceStoreISRBegin/End");\r
+ return;\r
+ }\r
+ \r
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
- { \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
+ \r
+ trcCRITICAL_SECTION_BEGIN();\r
dts5 = (uint16_t)prvTraceGetDTS(0xFFFF);\r
\r
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ \r
- { \r
+ { \r
ts = (TSEvent*)xTraceNextFreeEventBufferSlot();\r
if (ts != NULL)\r
{\r
prvTraceUpdateCounters();\r
}\r
}\r
+ trcCRITICAL_SECTION_END(); \r
}\r
}\r
\r
+#else\r
+\r
+/* ISR tracing is turned off */\r
+void vTraceIncreaseISRActive(void)\r
+{\r
+ if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
+ nISRactive++;\r
+}\r
+\r
+void vTraceDecreaseISRActive(objectHandleType handle)\r
+{\r
+ if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)\r
+ nISRactive--;\r
+}\r
#endif\r
\r
\r
UserEvent* ue;\r
uint8_t dts1;\r
\r
- if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive ) && handle_of_last_logged_task) \r
- { \r
- taskENTER_CRITICAL();\r
+ if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive ) && handle_of_last_logged_task)\r
+ {\r
+ trcCRITICAL_SECTION_BEGIN();\r
\r
dts1 = (uint8_t)prvTraceGetDTS(0xFF);\r
\r
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ \r
- { \r
+ { \r
ue = (UserEvent*) xTraceNextFreeEventBufferSlot();\r
if (ue != NULL)\r
{\r
prvTraceUpdateCounters();\r
}\r
}\r
- taskEXIT_CRITICAL();\r
+ trcCRITICAL_SECTION_END(); \r
}\r
}\r
\r
(8*32 bit = 32 byte) available for argument data */\r
#define MAX_ARG_SIZE (4+32) \r
\r
-static uint8_t writeInt8(void * buffer, uint8_t index, uint8_t value);\r
-static uint8_t writeInt16(void * buffer, uint8_t index, uint16_t value);\r
-static uint8_t writeInt32(void * buffer, uint8_t index, uint32_t value);\r
+static uint8_t writeInt8(void * buffer, uint8_t i, uint8_t value);\r
+static uint8_t writeInt16(void * buffer, uint8_t i, uint16_t value);\r
+static uint8_t writeInt32(void * buffer, uint8_t i, uint32_t value);\r
\r
#if (INCLUDE_FLOAT_SUPPORT)\r
-static uint8_t writeFloat(void * buffer, uint8_t index, float value);\r
-static uint8_t writeDouble(void * buffer, uint8_t index, double value);\r
+static uint8_t writeFloat(void * buffer, uint8_t i, float value);\r
+static uint8_t writeDouble(void * buffer, uint8_t i, double value);\r
#endif\r
\r
/*** Locally used in vTracePrintF ***/\r
-static uint8_t writeInt8(void * buffer, uint8_t index, uint8_t value)\r
+static uint8_t writeInt8(void * buffer, uint8_t i, uint8_t value)\r
{ \r
\r
- if (index + 1 > MAX_ARG_SIZE)\r
+ if (i >= MAX_ARG_SIZE)\r
{\r
return 255;\r
}\r
\r
- ((uint8_t*)buffer)[index] = value;\r
+ ((uint8_t*)buffer)[i] = value;\r
+\r
+ if (i + 1 > MAX_ARG_SIZE)\r
+ {\r
+ return 255;\r
+ }\r
\r
- return index + 1;\r
+ return i + 1;\r
}\r
\r
/*** Locally used in vTracePrintF ***/\r
-static uint8_t writeInt16(void * buffer, uint8_t index, uint16_t value)\r
-{\r
+static uint8_t writeInt16(void * buffer, uint8_t i, uint16_t value)\r
+{ \r
/* Align to multiple of 2 */\r
- while ((index % 2) != 0)\r
- { \r
- ((uint8_t*)buffer)[index] = 0;\r
- index++; \r
+ while ((i % 2) != 0)\r
+ {\r
+ if (i >= MAX_ARG_SIZE)\r
+ {\r
+ return 255;\r
+ }\r
+ \r
+ ((uint8_t*)buffer)[i] = 0;\r
+ i++; \r
}\r
\r
- if (index + 2 > MAX_ARG_SIZE)\r
+ if (i + 2 > MAX_ARG_SIZE)\r
{\r
return 255;\r
}\r
\r
- ((uint16_t*)buffer)[index/2] = value;\r
+ ((uint16_t*)buffer)[i/2] = value;\r
\r
- return index + 2;\r
+ return i + 2;\r
}\r
\r
/*** Locally used in vTracePrintF ***/\r
-static uint8_t writeInt32(void * buffer, uint8_t index, uint32_t value)\r
+static uint8_t writeInt32(void * buffer, uint8_t i, uint32_t value)\r
{\r
\r
/* A 32 bit value should begin at an even 4-byte address */\r
- while ((index % 4) != 0)\r
+ while ((i % 4) != 0)\r
{\r
- ((uint8_t*)buffer)[index] = 0;\r
- index++;\r
+ if (i >= MAX_ARG_SIZE)\r
+ {\r
+ return 255;\r
+ }\r
+ \r
+ ((uint8_t*)buffer)[i] = 0;\r
+ i++;\r
}\r
\r
- if (index + 4 > MAX_ARG_SIZE)\r
+ if (i + 4 > MAX_ARG_SIZE)\r
{\r
return 255;\r
} \r
\r
- ((uint32_t*)buffer)[index/4] = value;\r
+ ((uint32_t*)buffer)[i/4] = value;\r
\r
- return index + 4;\r
+ return i + 4;\r
}\r
\r
#if (INCLUDE_FLOAT_SUPPORT)\r
\r
/*** Locally used in vTracePrintF ***/\r
-static uint8_t writeFloat(void * buffer, uint8_t index, float value)\r
+static uint8_t writeFloat(void * buffer, uint8_t i, float value)\r
{\r
/* A 32 bit value should begin at an even 4-byte address */\r
- while ((index % 4) != 0)\r
+ while ((i % 4) != 0)\r
{\r
- ((uint8_t*)buffer)[index] = 0;\r
- index++;\r
+ if (i >= MAX_ARG_SIZE)\r
+ {\r
+ return 255;\r
+ }\r
+\r
+ ((uint8_t*)buffer)[i] = 0;\r
+ i++;\r
}\r
\r
- if (index + 4 > MAX_ARG_SIZE)\r
+ if (i + 4 > MAX_ARG_SIZE)\r
{\r
return 255;\r
} \r
\r
- ((float*)buffer)[index/4] = value;\r
+ ((float*)buffer)[i/4] = value;\r
\r
- return index + 4;\r
+ return i + 4;\r
}\r
\r
/*** Locally used in vTracePrintF ***/\r
-static uint8_t writeDouble(void * buffer, uint8_t index, double value)\r
+static uint8_t writeDouble(void * buffer, uint8_t i, double value)\r
{\r
+ uint32_t * dest = buffer;\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
- while (index % 4 != 0)\r
+ while (i % 4 != 0)\r
{\r
- ((uint8_t*)buffer)[index] = 0;\r
- index++; \r
+ if (i >= MAX_ARG_SIZE)\r
+ {\r
+ return 255;\r
+ }\r
+\r
+ ((uint8_t*)buffer)[i] = 0;\r
+ i++; \r
}\r
\r
- if (index + 8 > MAX_ARG_SIZE)\r
+ if (i + 8 > MAX_ARG_SIZE)\r
{\r
return 255;\r
} \r
\r
- ((uint32_t*)buffer)[index/4+0] = ((uint32_t*)&value)[0];\r
- ((uint32_t*)buffer)[index/4+1] = ((uint32_t*)&value)[1];\r
-\r
- return index + 8;\r
+ dest[i/4+0] = src[0];\r
+ dest[i/4+1] = src[1];\r
+ \r
+ return i + 8;\r
}\r
\r
#endif\r
UserEvent* ue1;\r
va_list vl;\r
uint8_t argCounter = 0;\r
- uint8_t index = 0;\r
+ uint8_t i = 0;\r
uint8_t nofEventEntries = 0;\r
uint16_t formatStrIndex = 0; \r
\r
* from different tasks overlaps (interrupts are only disabled in a small \r
* part of this function, otherwise enabled)\r
***************************************************************************/\r
- uint32_t dummy = 0; /* for the alignment of tempDataBuffer*/\r
- uint8_t tempDataBuffer[MAX_ARG_SIZE]; \r
- dummy = dummy; /* to eliminate compiler warnings*/\r
-\r
+ \r
+ uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4]; \r
+ \r
+ \r
if ((inExcludedTask == 0) &&\r
(nISRactive == 0) &&\r
(RecorderDataPtr->recorderActive == 1) &&\r
ue1 = (UserEvent*)(&tempDataBuffer[0]); \r
ue1->type = EVENT_BEING_WRITTEN; /* Update this as the last step */\r
\r
- index = 4;\r
+ i = 4;\r
formatStrIndex = 0;\r
va_start(vl, formatStr); /* Begin reading the arguments list */\r
\r
vTraceError("vTracePrintF - Too many arguments, max 15 allowed!");\r
va_end(vl); \r
formatStr = "[vTracePrintF error] Too many arguments, max 15 allowed!";\r
- index = 4;\r
+ i = 4;\r
break; \r
}\r
\r
formatStrIndex++;\r
switch (formatStr[formatStrIndex])\r
{\r
- case 'd': index = writeInt32(tempDataBuffer, \r
- index, \r
+ case 'd': i = writeInt32((uint8_t*)tempDataBuffer, \r
+ i, \r
(uint32_t)va_arg(vl, uint32_t)); \r
break;\r
- case 'u': index = writeInt32(tempDataBuffer, \r
- index, \r
+ case 'u': i = writeInt32((uint8_t*)tempDataBuffer, \r
+ i, \r
(uint32_t)va_arg(vl, uint32_t)); \r
break;\r
- case 's': index = writeInt16(tempDataBuffer, \r
- index, \r
- (uint16_t)xTraceOpenLabel((char*)va_arg(vl, uint32_t))); \r
+ case 's': i = writeInt16((uint8_t*)tempDataBuffer, \r
+ i, \r
+ (uint16_t)xTraceOpenLabel((char*)va_arg(vl, char*))); \r
break;\r
\r
#if (INCLUDE_FLOAT_SUPPORT)\r
/* Yes, "double" as type also in the float \r
case. This since "float" is promoted into "double" \r
by the va_arg stuff. */\r
- case 'f': index = writeFloat(tempDataBuffer, \r
- index, \r
+ case 'f': i = writeFloat((uint8_t*)tempDataBuffer, \r
+ i, \r
(float)va_arg(vl, double)); \r
break; \r
#else\r
/* No support for floats, but attempt to store a float user event\r
avoid a possible crash due to float reference. Instead store the \r
data on uint_32 format (will not be displayed anyway). This is just\r
-to keep va_arg and index consistent. */\r
+to keep va_arg and i consistent. */\r
\r
- case 'f': index = writeInt32(tempDataBuffer,\r
- index, \r
+ case 'f': i = writeInt32((uint8_t*)tempDataBuffer,\r
+ i, \r
(uint32_t)va_arg(vl, double)); \r
#endif\r
case 'l':\r
switch (formatStr[formatStrIndex])\r
{\r
#if (INCLUDE_FLOAT_SUPPORT)\r
- case 'f': index = writeDouble(tempDataBuffer, \r
- index, \r
+ case 'f': i = writeDouble((uint8_t*)tempDataBuffer, \r
+ i, \r
(double)va_arg(vl, double)); \r
break;\r
#else\r
/* No support for floats, but attempt to store a float user event\r
avoid a possible crash due to float reference. Instead store the \r
data on uint_32 format (will not be displayed anyway). This is just\r
-to keep va_arg and index consistent. */\r
- case 'f': index = writeInt32(tempDataBuffer, /* In this case, the value will not be shown anyway */\r
- index, \r
+to keep va_arg and i consistent. */\r
+ case 'f': i = writeInt32((uint8_t*)tempDataBuffer, /* In this case, the value will not be shown anyway */\r
+ i, \r
(uint32_t)va_arg(vl, double)); \r
- index = writeInt32(tempDataBuffer, /* Do it twice, to write in total 8 bytes */\r
- index, \r
+ i = writeInt32((uint8_t*)tempDataBuffer, /* Do it twice, to write in total 8 bytes */\r
+ i, \r
(uint32_t)va_arg(vl, double)); \r
#endif\r
\r
formatStrIndex++;\r
switch (formatStr[formatStrIndex])\r
{\r
- case 'd': index = writeInt16(tempDataBuffer, \r
- index, \r
+ case 'd': i = writeInt16((uint8_t*)tempDataBuffer, \r
+ i, \r
(uint16_t)va_arg(vl, uint32_t)); \r
break;\r
- case 'u': index = writeInt16(tempDataBuffer, \r
- index, \r
+ case 'u': i = writeInt16((uint8_t*)tempDataBuffer, \r
+ i, \r
(uint16_t)va_arg(vl, uint32_t)); \r
break;\r
}\r
formatStrIndex++;\r
switch (formatStr[formatStrIndex])\r
{\r
- case 'd': index = writeInt8(tempDataBuffer, \r
- index, \r
+ case 'd': i = writeInt8((uint8_t*)tempDataBuffer, \r
+ i, \r
(uint8_t)va_arg(vl, uint32_t)); \r
break;\r
- case 'u': index = writeInt8(tempDataBuffer, \r
- index, \r
+ case 'u': i = writeInt8((uint8_t*)tempDataBuffer, \r
+ i, \r
(uint8_t)va_arg(vl, uint32_t)); \r
break;\r
}\r
}\r
} \r
formatStrIndex++; \r
- if (index == 255)\r
+ if (i == 255)\r
{\r
va_end(vl);\r
- vTraceError("vTracePrintF - Too large arguments, max 32 byte allowed!");\r
+ //vTraceError("vTracePrintF - Too large arguments, max 32 byte allowed!");\r
formatStr = "[vTracePrintF error] Too large arguments, max 32 byte allowed!";\r
- index = 4;\r
+ i = 4;\r
break;\r
}\r
}\r
\r
va_end(vl);\r
-\r
+ \r
/* Store the format string, with a reference to the channel symbol */\r
ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel); \r
\r
- taskENTER_CRITICAL(); \r
+ trcCRITICAL_SECTION_BEGIN(); \r
\r
ue1->dts = (uint8_t)prvTraceGetDTS(0xFF);\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
- taskEXIT_CRITICAL(); \r
+ trcCRITICAL_SECTION_END();\r
+ \r
return;\r
}\r
\r
- nofEventEntries = (index+3)/4;\r
+ nofEventEntries = (i+3)/4;\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
#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
- taskEXIT_CRITICAL();\r
+ trcCRITICAL_SECTION_END();\r
vTraceStop();\r
+\r
+ \r
return;\r
#endif\r
}\r
/* Copy the local buffer to the main buffer */\r
(void)memcpy(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4], \r
tempDataBuffer, \r
- index);\r
+ i);\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
#endif\r
}\r
\r
- taskEXIT_CRITICAL();\r
- }\r
+ trcCRITICAL_SECTION_END();\r
+ } \r
}\r
\r
/*******************************************************************************\r
* \r
* xTraceOpenLabel()\r
*\r
- * whihc adds the string to the symbol table (if not already present)\r
+ * which adds the string to the symbol table (if not already present)\r
* and returns the corresponding handle.\r
*\r
* This can be used in two ways:\r
* executed and/or located in time-critical code. The lookup operation is\r
* however fairly fast due to the design of the symbol table.\r
******************************************************************************/\r
-traceLabel xTraceOpenLabel(char* label)\r
+traceLabel xTraceOpenLabel(const char* label)\r
{\r
return prvTraceOpenSymbol(label, 0);\r
}\r