From: richardbarry Date: Sun, 10 Feb 2013 19:33:28 +0000 (+0000) Subject: Update the FreeRTOS+Trace recorder and Win32 demo app. X-Git-Tag: V7.4.0~10 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=322840c102dcc38ef0ce11849e36c3152e195906;p=freertos Update the FreeRTOS+Trace recorder and Win32 demo app. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1821 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/FreeRTOS_Plus_CLI_with_Trace.suo b/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/FreeRTOS_Plus_CLI_with_Trace.suo index 63f5b08c2..f3d0ab628 100644 Binary files a/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/FreeRTOS_Plus_CLI_with_Trace.suo and b/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/FreeRTOS_Plus_CLI_with_Trace.suo differ diff --git a/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/Run-time-stats-utils.c b/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/Run-time-stats-utils.c index 44e1b5f78..ea243d328 100644 --- a/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/Run-time-stats-utils.c +++ b/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/Run-time-stats-utils.c @@ -125,7 +125,17 @@ unsigned long ulReturn; /* Subtract the performance counter value reading taken when the application started to get a count from that reference point, then scale to (simulated) 1/100ths of a millisecond. */ - ulReturn = ( unsigned long ) ( ( liCurrentCount.QuadPart - llInitialRunTimeCounterValue ) / llTicksPerHundedthMillisecond ); + if( llTicksPerHundedthMillisecond == 0 ) + { + /* The trace macros can call this function before the kernel has been + started, in which case llTicksPerHundedthMillisecond will not have been + initialised. */ + ulReturn = 0; + } + else + { + ulReturn = ( unsigned long ) ( ( liCurrentCount.QuadPart - llInitialRunTimeCounterValue ) / llTicksPerHundedthMillisecond ); + } return ulReturn; } diff --git a/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/Trace_Recorder_Configuration/trcPort.h b/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/Trace_Recorder_Configuration/trcPort.h index 828699eb4..91f9a9503 100644 --- a/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/Trace_Recorder_Configuration/trcPort.h +++ b/FreeRTOS-Plus/Demo_Projects_Using_FreeRTOS_Simulator/FreeRTOS_Plus_CLI_with_Trace/Trace_Recorder_Configuration/trcPort.h @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.2 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcPort.h * @@ -34,17 +34,15 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ #ifndef TRCPORT_H #define TRCPORT_H -#include "trcBase.h" - /* If FreeRTOS Win32 port */ #ifdef WIN32 @@ -63,7 +61,9 @@ ******************************************************************************/ #define WIN32_PORT_SAVE_WHEN_STOPPED 1 #define WIN32_PORT_EXIT_WHEN_STOPPED 1 - +#else + #define WIN32_PORT_SAVE_WHEN_STOPPED 0 + #define WIN32_PORT_EXIT_WHEN_STOPPED 0 #endif #define DIRECTION_INCREMENTING 1 @@ -87,10 +87,12 @@ * count). The timing of the Win32 FreeRTOS build is not real-time, since it * depends on the scheduling and tick rate of Windows, which is very slow. * - * Officially supported hardware specific ports included are: + * Officially supported hardware timer ports: * - PORT_Atmel_AT91SAM7 + * - PORT_Atmel_UC3A0 * - PORT_ARM_CortexM * - PORT_Renesas_RX600 + * - PORT_Microchip_dsPIC_AND_PIC24 * * We also provide several "unofficial" hardware-specific ports. There have * been developed by external contributors, and have not yet been verified @@ -100,33 +102,41 @@ * - PORT_TEXAS_INSTRUMENTS_TMS570 * - PORT_TEXAS_INSTRUMENTS_MSP430 * - PORT_MICROCHIP_PIC32 - * - PORT_MICROCHIP_dsPIC_AND_PIC24 * - PORT_XILINX_PPC405 * - PORT_XILINX_PPC440 + * - PORT_XILINX_MICROBLAZE + * - PORT_NXP_LPC210X * - ******************************************************************************/ - -#define PORT_NOT_SET -1 - -/* Officially supported ports */ -#define PORT_HWIndependent 0 -#define PORT_Win32 1 -#define PORT_Atmel_AT91SAM7 2 -#define PORT_ARM_CortexM 3 -#define PORT_Renesas_RX600 4 - -/* Unofficial ports, provided by external developers and not yet verified */ -#define PORT_TEXAS_INSTRUMENTS_TMS570 6 -#define PORT_TEXAS_INSTRUMENTS_MSP430 7 -#define PORT_MICROCHIP_PIC32 8 -#define PORT_MICROCHIP_dsPIC_AND_PIC24 9 -#define PORT_XILINX_PPC405 10 -#define PORT_XILINX_PPC440 11 + *****************************************************************************/ + +#define PORT_NOT_SET -1 + +/*** Officially supported hardware timer ports *******************************/ +#define PORT_HWIndependent 0 +#define PORT_Win32 1 +#define PORT_Atmel_AT91SAM7 2 +#define PORT_Atmel_UC3A0 3 +#define PORT_ARM_CortexM 4 +#define PORT_Renesas_RX600 5 +#define PORT_Microchip_dsPIC_AND_PIC24 6 + +/*** Unofficial ports, provided by external developers, not yet verified *****/ +#define PORT_TEXAS_INSTRUMENTS_TMS570 7 +#define PORT_TEXAS_INSTRUMENTS_MSP430 8 +#define PORT_MICROCHIP_PIC32 9 +#define PORT_XILINX_PPC405 10 +#define PORT_XILINX_PPC440 11 +#define PORT_XILINX_MICROBLAZE 12 +#define PORT_NXP_LPC210X 13 /*** Select your port here! **************************************************/ #define SELECTED_PORT PORT_Win32 /*****************************************************************************/ +#if (SELECTED_PORT == PORT_NOT_SET) +#error "You need to define SELECTED_PORT here!" +#endif + /******************************************************************************* * IRQ_PRIORITY_ORDER * @@ -141,25 +151,29 @@ * the vTraceStoreISRBegin and vTraceStoreISREnd routines. * * We provide this setting for some hardware architectures below: - * - ARM Cortex M: 0 (lower irq priority values are more significant) - * - Atmel AT91SAM7x: 1 (higher irq priority values are more significant) - * - Renesas RX62N: 1 (higher irq priority values are more significant) - * - Microchip PIC24: 0 (lower irq priority values are more significant) - * - Microchip dsPIC: 0 (lower irq priority values are more significant) - * - TI TMS570 (ARM Cortex R4F): 0 (lower irq priority values are more significant) - * - Freescale HCS08: 0 (lower irq priority values are more significant) - * - Freescale HCS12: 0 (lower irq priority values are more significant) - * - Freescale ColdFire: 1 (higher irq priority values are more significant) + * - ARM Cortex M: 0 (lower irq priority values are more significant) + * - Atmel AT91SAM7x: 1 (higher irq priority values are more significant) + * - Atmel AVR32: 1 (higher irq priority values are more significant) + * - Renesas RX600: 1 (higher irq priority values are more significant) + * - Microchip PIC24: 0 (lower irq priority values are more significant) + * - Microchip dsPIC: 0 (lower irq priority values are more significant) + * - TI TMS570: 0 (lower irq priority values are more significant) + * - Freescale HCS08: 0 (lower irq priority values are more significant) + * - Freescale HCS12: 0 (lower irq priority values are more significant) + * - PowerPC 405: 0 (lower irq priority values are more significant) + * - PowerPC 440: 0 (lower irq priority values are more significant) + * - Freescale ColdFire: 1 (higher irq priority values are more significant) + * - NXP LPC210x: 0 (lower irq priority values are more significant) + * - MicroBlaze: 0 (lower irq priority values are more significant) * * If your chip is not on the above list, and you perhaps know this detail by - * heart, please inform us by e-mail to support@percepio.se. - ******************************************************************************/ -#define IRQ_PRIORITY_ORDER 0 - -/******************************************************************************* - * HWTC macros - * - * These four macros provides a hardware isolation layer, representing a + * heart, please inform us by e-mail to support@percepio.com. + * + ****************************************************************************** + * + * HWTC Macros + * + * These four HWTC macros provides a hardware isolation layer representing a * generic hardware timer/counter used for driving the operating system tick, * such as the SysTick feature of ARM Cortex M3/M4, or the PIT of the Atmel * AT91SAM7X. @@ -187,7 +201,7 @@ * (where the SysTick runs at the core clock frequency), the "differential * timestamping" used in the recorder will more frequently insert extra XTS * events to store the timestamps, which increases the event buffer usage. - * In such cases, to reduce the number of XTS events and thereby get a longer + * In such cases, to reduce the number of XTS events and thereby get longer * traces, you use HWTC_DIVISOR to scale down the timestamps and frequency. * Assuming a OS tick rate of 1 KHz, it is suggested to keep the effective timer * frequency below 65 MHz to avoid an excessive amount of XTS events. Thus, a @@ -198,49 +212,69 @@ * or the trace recorder library. Typically you should not need to change * the code of uiTracePortGetTimeStamp if using the HWTC macros. * - * OFFER FROM PERCEPIO: + * FREE LICENSE OFFER FROM PERCEPIO + * * For silicon companies and non-corporate FreeRTOS users (researchers, students, - * hobbyists or early-phase startups) we have an attractive offer: - * Provide a hardware timer port and get a FREE single-user licence for - * FreeRTOS+Trace Professional Edition. Read more about this offer at - * www.percepio.se or contact us directly at support@percepio.se. + * hobbyists or early-phase startups) we have the following offer: + * Provide a hardware port for our FreeRTOS recorder and get a FREE single-user + * license for FreeRTOS+Trace Professional Edition. Read more about this offer + * at www.percepio.com or contact us directly at support@percepio.com. * ******************************************************************************/ #if (SELECTED_PORT == PORT_Win32) - #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING + #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT (ulGetRunTimeCounterValue()) #define HWTC_PERIOD 0 #define HWTC_DIVISOR 1 - + + #define IRQ_PRIORITY_ORDER 1 // Please update according to your hardware... + #elif (SELECTED_PORT == PORT_HWIndependent) - #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING + #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT 0 #define HWTC_PERIOD 1 #define HWTC_DIVISOR 1 - + + #define IRQ_PRIORITY_ORDER 1 // Please update according to your hardware... + #elif (SELECTED_PORT == PORT_Atmel_AT91SAM7) /* HWTC_PERIOD is hardcoded for AT91SAM7X256-EK Board (48 MHz) - A more generic solution is to get the period from pxPIT->PITC_PIMR */ - + A more generic solution is to get the period from pxPIT->PITC_PIMR */ + #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT (AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF) #define HWTC_PERIOD 2995 #define HWTC_DIVISOR 1 + #define IRQ_PRIORITY_ORDER 1 // higher irq priority values are more significant + +#elif (SELECTED_PORT == PORT_Atmel_UC3A0) + + /* For Atmel AVR32 (AT32UC3A) */ + + #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING + #define HWTC_COUNT sysreg_read(AVR32_COUNT) + #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) + #define HWTC_DIVISOR 1 + + #define IRQ_PRIORITY_ORDER 1 // higher irq priority values are more significant + #elif (SELECTED_PORT == PORT_ARM_CortexM) - /* For all chips using ARM Cortex M cores */ + /* For all chips using ARM Cortex M cores */ #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING #define HWTC_COUNT (*((uint32_t*)0xE000E018)) #define HWTC_PERIOD ((*(uint32_t*)0xE000E014) + 1) #define HWTC_DIVISOR 2 + + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant -#elif (SELECTED_PORT == PORT_Renesas_RX600) +#elif (SELECTED_PORT == PORT_Renesas_RX600) #include "iodefine.h" @@ -249,7 +283,41 @@ #define HWTC_PERIOD ((((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/8)) #define HWTC_DIVISOR 1 -#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_TMS570) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + #define IRQ_PRIORITY_ORDER 1 // higher irq priority values are more significant + +#elif (SELECTED_PORT == PORT_Microchip_dsPIC_AND_PIC24) + + /* For Microchip PIC24 and dsPIC (16 bit) */ + + /* Note: The trace library was originally designed for 32-bit MCUs, and is slower + than intended on 16-bit MCUs. Storing an event on a PIC24 takes about 70 µs. + In comparison, 32-bit MCUs are often 10-20 times faster. If recording overhead + becomes a problem on PIC24, use the filters to exclude less interresting tasks + or system calls. */ + + #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING + #define HWTC_COUNT (TMR1) + #define HWTC_PERIOD (PR1+1) + #define HWTC_DIVISOR 1 + + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant + +#elif (SELECTED_PORT == PORT_NXP_LPC210X) + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + + /* Tested with LPC2106, but should work with most LPC21XX chips. + Assumption: prescaler is 1:1 (this setting is hardcoded in + FreeRTOS port for LPC21XX) */ + + #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING + #define HWTC_COUNT *((uint32_t *)0xE0004008 ) + #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) + #define HWTC_DIVISOR 1 + + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant + +#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_TMS570) + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ #define RTIFRC0 *((uint32_t *)0xFFFFFC10) #define RTICOMP0 *((uint32_t *)0xFFFFFC50) @@ -259,93 +327,103 @@ #define HWTC_PERIOD (RTIUDCP0) #define HWTC_DIVISOR 1 -#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_MSP430) - /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant + +#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_MSP430) + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT (TA0R) #define HWTC_PERIOD configCPU_CLOCKS_PER_TICK #define HWTC_DIVISOR 1 -#elif (SELECTED_PORT == PORT_MICROCHIP_PIC32) - /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ - - #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING - #define HWTC_COUNT (ReadTimer1()) /* Should be available in BSP */ - #define HWTC_PERIOD (ReadPeriod1()+1) /* Should be available in BSP */ - #define HWTC_DIVISOR 1 + #define IRQ_PRIORITY_ORDER 1 // higher irq priority values are more significant -#elif (SELECTED_PORT == PORT_MICROCHIP_dsPIC_AND_PIC24) - /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ +#elif (SELECTED_PORT == PORT_MICROCHIP_PIC32) + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING - #define HWTC_COUNT (PR1) - #define HWTC_PERIOD ((configCPU_CLOCK_HZ/portTIMER_PRESCALE)/configTICK_RATE_HZ) + #define HWTC_COUNT (ReadTimer1()) /* Should be available in BSP */ + #define HWTC_PERIOD (ReadPeriod1()+1) /* Should be available in BSP */ #define HWTC_DIVISOR 1 + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant + #elif (SELECTED_PORT == PORT_XILINX_PPC405) - /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING #define HWTC_COUNT mfspr( 0x3db) #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - #define HWTC_DIVISOR 1 + #define HWTC_DIVISOR 1 + + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant #elif (SELECTED_PORT == PORT_XILINX_PPC440) - /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ - /* This should work with most PowerPC chips */ - + /* This should work with most PowerPC chips */ + #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING #define HWTC_COUNT mfspr( 0x016 ) #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) #define HWTC_DIVISOR 1 -#else - SELECTED_PORT is not set, or had unsupported value! - (This is to intentionally cause a compiler error.) -#endif + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant + +#elif (SELECTED_PORT == PORT_XILINX_MICROBLAZE) + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + + /* This should work with most Microblaze configurations + * This port is based on the official FreeRTOS Microlaze port and example application. + * It uses the AXI Timer 0 - the tick interrupt source. + * If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required. + */ + #include "xtmrctr_l.h" + + #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING + #define HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 ) + #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) + #define HWTC_DIVISOR 16 + + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant + +#elif (SELECTED_PORT != PORT_NOT_SET) + + #error "SELECTED_PORT had unsupported value!" + #define SELECTED_PORT PORT_NOT_SET -#ifndef HWTC_COUNT_DIRECTION - HWTC_COUNT_DIRECTION is not set! - (This is to intentionally cause a compiler error.) -#endif - -#ifndef HWTC_COUNT - HWTC_COUNT is not set! - (This is to intentionally cause a compiler error.) -#endif - -#ifndef HWTC_PERIOD - HWTC_PERIOD is not set! - (This is to intentionally cause a compiler error.) -#endif - -#ifndef HWTC_DIVISOR - HWTC_DIVISOR is not set! - (This is to intentionally cause a compiler error.) -#endif - -#ifndef IRQ_PRIORITY_ORDER - IRQ_PRIORITY_ORDER is not set! - (This is to intentionally cause a compiler error.) -#endif - -#if (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1) - IRQ_PRIORITY_ORDER has bad value! - (This is to intentionally cause a compiler error.) -#endif - -#if (HWTC_DIVISOR < 1) - HWTC_DIVISOR must be a non-zero positive value! - (This is to intentionally cause a compiler error.) -#endif - -#if ((IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1)) -IRQ_PRIORITY_ORDER not set! -(This is to intentionally cause a compiler error.) #endif +#if (SELECTED_PORT != PORT_NOT_SET) + + #ifndef HWTC_COUNT_DIRECTION + #error "HWTC_COUNT_DIRECTION is not set!" + #endif + + #ifndef HWTC_COUNT + #error "HWTC_COUNT is not set!" + #endif + + #ifndef HWTC_PERIOD + #error "HWTC_PERIOD is not set!" + #endif + + #ifndef HWTC_DIVISOR + #error "HWTC_DIVISOR is not set!" + #endif + + #ifndef IRQ_PRIORITY_ORDER + #error "IRQ_PRIORITY_ORDER is not set!" + #elif (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1) + #error "IRQ_PRIORITY_ORDER has bad value!" + #endif + + #if (HWTC_DIVISOR < 1) + #error "HWTC_DIVISOR must be a non-zero positive value!" + #endif + +#endif /******************************************************************************* * vTraceConsoleMessage * @@ -353,7 +431,12 @@ IRQ_PRIORITY_ORDER not set! * This needs to be correctly defined to see status reports from the trace * status monitor task (this is defined in trcUser.c). ******************************************************************************/ -#define vTraceConsoleMessage printf +#if (SELECTED_PORT == PORT_Atmel_AT91SAM7) +/* Port specific includes */ +#include "console.h" +#endif + +#define vTraceConsoleMessage(x) /******************************************************************************* * uiTracePortGetTimeStamp @@ -370,19 +453,9 @@ IRQ_PRIORITY_ORDER not set! * students, hobbyists or early-phase startups) we have an attractive offer: * Provide a hardware timer port and get a FREE single-user licence for * FreeRTOS+Trace Professional Edition. Read more about this offer at - * www.percepio.se or contact us directly at support@percepio.se. - ******************************************************************************/ -uint32_t uiTracePortGetTimeStamp(void); - -/******************************************************************************* - * vTracePortSetFrequency - * - * Registers the frequency of the timer used. This is normally calculated - * automatically from the HWTC macros, but the Win32 port requires a special - * solution where the frequency can be set independently of the HWTC macros. - * This is called from main in the Win32 demo program. + * www.percepio.com or contact us directly at support@percepio.com. ******************************************************************************/ -void vTracePortSetFrequency(uint32_t freq); +void uiTracePortGetTimeStamp(uint32_t *puiTimestamp); /******************************************************************************* * vTracePortEnd diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/Readme Config.txt b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/Readme Config.txt index bf184a25f..8883a59aa 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/Readme Config.txt +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/Readme Config.txt @@ -1,4 +1,4 @@ -FreeRTOS+Trace v2.2.3 +FreeRTOS+Trace v2.3.0 --------------------- This directory contains the recorder files that the typical FreeRTOS+Trace user needs to be aware of. @@ -19,4 +19,4 @@ If you use this template, you will need to update the following macro definition Always remember to check the settings used in trcConfig.h. Percepio AB -www.percepio.se +www.percepio.com diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/trcConfig.h b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/trcConfig.h index 35129bebc..1ffa3efec 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/trcConfig.h +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/trcConfig.h @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcConfig.h * @@ -38,10 +38,10 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ #ifndef TRCCONFIG_H @@ -61,11 +61,30 @@ * vTracePrintF may use multiple records depending on the number of data args. ******************************************************************************/ -#ifdef WIN32 - #define EVENT_BUFFER_SIZE 3000 -#else - #define EVENT_BUFFER_SIZE 1000 /* Adjust wrt. to available RAM */ -#endif +#define EVENT_BUFFER_SIZE 1000 /* Adjust wrt. to available RAM */ + + +/******************************************************************************* + * USE_LINKER_PRAGMA + * + * Macro which should be defined as an integer value, default is 0. + * + * If this is 1, the header file "recorderdata_linker_pragma.h" is included just + * before the declaration of RecorderData (in trcBase.c), i.e., the trace data + * structure. This allows the user to specify a pragma with linker options. + * + * Example (for IAR Embedded Workbench and NXP LPC17xx): + * #pragma location="AHB_RAM_MEMORY" + * + * This example instructs the IAR linker to place RecorderData in another RAM + * bank, the AHB RAM. This can also be used for other compilers with a similar + * pragmas for linker options. + * + * Note that this only applies if using static allocation, see below. + ******************************************************************************/ + +#define USE_LINKER_PRAGMA 0 + /******************************************************************************* * SYMBOL_TABLE_SIZE @@ -97,17 +116,20 @@ * routine, which makes the error message appear when opening the trace data * in FreeRTOS+Trace. If you are using the recorder status monitor task, * any error messages are displayed in console prints, assuming that the - * print macro has been defined properly (vConsolePrintMessage). - * - * NOTE 2: If you include the monitor task (USE_TRACE_PROGRESS_MONITOR_TASK) - * make sure to dimension NTask with this task accounted for. + * print macro has been defined properly (vConsolePrintMessage). * - * Also remember to account for all tasks created by FreeRTOS, such as the + * It can be wise to start with very large values for these constants, + * unless you are very confident on these numbers. Then do a recording and + * check the actual usage in FreeRTOS+Trace. This is shown by selecting + * View -> Trace Details -> Resource Usage -> Object Table + * + * NOTE 2: Remember to account for all tasks created by FreeRTOS, such as the * IDLE task, the FreeRTOS timer task, and any tasks created by other 3rd party - * software components, such as communication stacks. - * Moreover, one task slot is used to indicate "(startup)", i.e., a "task" that - * represent the time before the first task starts. NTask should thus be at - * least 2-3 slots larger than your application task count. + * software components, such as communication stacks. The recorder also has an + * optional monitor task to account for, if this is used. + * Moreover, one task slot is used to indicate "(startup)", i.e., a fictive + * task that represent the time before the FreeRTOS scheduler starts. + * NTask should thus be at least 2-3 slots larger than your application task count. * * NOTE 3: The FreeRTOS timer task creates a Queue, that should be accounted * for in NQueue. @@ -206,6 +228,18 @@ *****************************************************************************/ #define INCLUDE_USER_EVENTS 1 +/***************************************************************************** + * INCLUDE_READY_EVENTS + * + * Macro which should be defined as either zero (0) or one (1). + * Default is 1. + * + * If this is zero (0), the code for recording Ready events is + * excluded. Note, this will make it impossible to calculate the correct + * response times. + *****************************************************************************/ +#define INCLUDE_READY_EVENTS 1 + /***************************************************************************** * INCLUDE_ISR_TRACING * diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/trcPort.h b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/trcPort.h index 3d70ef5b8..a2d4bf1a4 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/trcPort.h +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Configuration - template/trcPort.h @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcPort.h * @@ -34,17 +34,15 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ #ifndef TRCPORT_H #define TRCPORT_H -#include "trcBase.h" - /* If FreeRTOS Win32 port */ #ifdef WIN32 @@ -87,10 +85,12 @@ * count). The timing of the Win32 FreeRTOS build is not real-time, since it * depends on the scheduling and tick rate of Windows, which is very slow. * - * Officially supported hardware specific ports included are: + * Officially supported hardware timer ports: * - PORT_Atmel_AT91SAM7 + * - PORT_Atmel_UC3A0 * - PORT_ARM_CortexM * - PORT_Renesas_RX600 + * - PORT_Microchip_dsPIC_AND_PIC24 * * We also provide several "unofficial" hardware-specific ports. There have * been developed by external contributors, and have not yet been verified @@ -100,33 +100,41 @@ * - PORT_TEXAS_INSTRUMENTS_TMS570 * - PORT_TEXAS_INSTRUMENTS_MSP430 * - PORT_MICROCHIP_PIC32 - * - PORT_MICROCHIP_dsPIC_AND_PIC24 * - PORT_XILINX_PPC405 * - PORT_XILINX_PPC440 + * - PORT_XILINX_MICROBLAZE + * - PORT_NXP_LPC210X * - ******************************************************************************/ + *****************************************************************************/ #define PORT_NOT_SET -1 -/* Officially supported ports */ +/*** Officially supported hardware timer ports *******************************/ #define PORT_HWIndependent 0 #define PORT_Win32 1 #define PORT_Atmel_AT91SAM7 2 -#define PORT_ARM_CortexM 3 -#define PORT_Renesas_RX600 4 - -/* Unofficial ports, provided by external developers and not yet verified */ -#define PORT_TEXAS_INSTRUMENTS_TMS570 5 -#define PORT_TEXAS_INSTRUMENTS_MSP430 6 -#define PORT_MICROCHIP_PIC32 7 -#define PORT_MICROCHIP_dsPIC_AND_PIC24 8 -#define PORT_XILINX_PPC405 9 -#define PORT_XILINX_PPC440 10 +#define PORT_Atmel_UC3A0 3 +#define PORT_ARM_CortexM 4 +#define PORT_Renesas_RX600 5 +#define PORT_Microchip_dsPIC_AND_PIC24 6 + +/*** Unofficial ports, provided by external developers, not yet verified *****/ +#define PORT_TEXAS_INSTRUMENTS_TMS570 7 +#define PORT_TEXAS_INSTRUMENTS_MSP430 8 +#define PORT_MICROCHIP_PIC32 9 +#define PORT_XILINX_PPC405 10 +#define PORT_XILINX_PPC440 11 +#define PORT_XILINX_MICROBLAZE 12 +#define PORT_NXP_LPC210X 13 /*** Select your port here! **************************************************/ #define SELECTED_PORT PORT_NOT_SET /*****************************************************************************/ +#if (SELECTED_PORT == PORT_NOT_SET) +#error "You need to define SELECTED_PORT here!" +#endif + /******************************************************************************* * IRQ_PRIORITY_ORDER * @@ -141,25 +149,29 @@ * the vTraceStoreISRBegin and vTraceStoreISREnd routines. * * We provide this setting for some hardware architectures below: - * - ARM Cortex M: 0 (lower irq priority values are more significant) - * - Atmel AT91SAM7x: 1 (higher irq priority values are more significant) - * - Renesas RX62N: 1 (higher irq priority values are more significant) - * - Microchip PIC24: 0 (lower irq priority values are more significant) - * - Microchip dsPIC: 0 (lower irq priority values are more significant) - * - TI TMS570 (ARM Cortex R4F): 0 (lower irq priority values are more significant) - * - Freescale HCS08: 0 (lower irq priority values are more significant) - * - Freescale HCS12: 0 (lower irq priority values are more significant) - * - Freescale ColdFire: 1 (higher irq priority values are more significant) + * - ARM Cortex M: 0 (lower irq priority values are more significant) + * - Atmel AT91SAM7x: 1 (higher irq priority values are more significant) + * - Atmel AVR32: 1 (higher irq priority values are more significant) + * - Renesas RX600: 1 (higher irq priority values are more significant) + * - Microchip PIC24: 0 (lower irq priority values are more significant) + * - Microchip dsPIC: 0 (lower irq priority values are more significant) + * - TI TMS570: 0 (lower irq priority values are more significant) + * - Freescale HCS08: 0 (lower irq priority values are more significant) + * - Freescale HCS12: 0 (lower irq priority values are more significant) + * - PowerPC 405: 0 (lower irq priority values are more significant) + * - PowerPC 440: 0 (lower irq priority values are more significant) + * - Freescale ColdFire: 1 (higher irq priority values are more significant) + * - NXP LPC210x: 0 (lower irq priority values are more significant) + * - MicroBlaze: 0 (lower irq priority values are more significant) * * If your chip is not on the above list, and you perhaps know this detail by - * heart, please inform us by e-mail to support@percepio.se. - ******************************************************************************/ -#define IRQ_PRIORITY_ORDER 0 - -/******************************************************************************* - * HWTC macros - * - * These four macros provides a hardware isolation layer, representing a + * heart, please inform us by e-mail to support@percepio.com. + * + ****************************************************************************** + * + * HWTC Macros + * + * These four HWTC macros provides a hardware isolation layer representing a * generic hardware timer/counter used for driving the operating system tick, * such as the SysTick feature of ARM Cortex M3/M4, or the PIT of the Atmel * AT91SAM7X. @@ -187,7 +199,7 @@ * (where the SysTick runs at the core clock frequency), the "differential * timestamping" used in the recorder will more frequently insert extra XTS * events to store the timestamps, which increases the event buffer usage. - * In such cases, to reduce the number of XTS events and thereby get a longer + * In such cases, to reduce the number of XTS events and thereby get longer * traces, you use HWTC_DIVISOR to scale down the timestamps and frequency. * Assuming a OS tick rate of 1 KHz, it is suggested to keep the effective timer * frequency below 65 MHz to avoid an excessive amount of XTS events. Thus, a @@ -198,12 +210,13 @@ * or the trace recorder library. Typically you should not need to change * the code of uiTracePortGetTimeStamp if using the HWTC macros. * - * OFFER FROM PERCEPIO: + * FREE LICENSE OFFER FROM PERCEPIO + * * For silicon companies and non-corporate FreeRTOS users (researchers, students, - * hobbyists or early-phase startups) we have an attractive offer: - * Provide a hardware timer port and get a FREE single-user licence for - * FreeRTOS+Trace Professional Edition. Read more about this offer at - * www.percepio.se or contact us directly at support@percepio.se. + * hobbyists or early-phase startups) we have the following offer: + * Provide a hardware port for our FreeRTOS recorder and get a FREE single-user + * license for FreeRTOS+Trace Professional Edition. Read more about this offer + * at www.percepio.com or contact us directly at support@percepio.com. * ******************************************************************************/ @@ -214,13 +227,17 @@ #define HWTC_PERIOD 0 #define HWTC_DIVISOR 1 + #define IRQ_PRIORITY_ORDER 1 // Please update according to your hardware... + #elif (SELECTED_PORT == PORT_HWIndependent) #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT 0 #define HWTC_PERIOD 1 #define HWTC_DIVISOR 1 - + + #define IRQ_PRIORITY_ORDER 1 // Please update according to your hardware... + #elif (SELECTED_PORT == PORT_Atmel_AT91SAM7) /* HWTC_PERIOD is hardcoded for AT91SAM7X256-EK Board (48 MHz) @@ -231,6 +248,19 @@ #define HWTC_PERIOD 2995 #define HWTC_DIVISOR 1 + #define IRQ_PRIORITY_ORDER 1 // higher irq priority values are more significant + +#elif (SELECTED_PORT == PORT_Atmel_UC3A0) + + /* For Atmel AVR32 (AT32UC3A) */ + + #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING + #define HWTC_COUNT sysreg_read(AVR32_COUNT) + #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) + #define HWTC_DIVISOR 1 + + #define IRQ_PRIORITY_ORDER 1 // higher irq priority values are more significant + #elif (SELECTED_PORT == PORT_ARM_CortexM) /* For all chips using ARM Cortex M cores */ @@ -239,6 +269,8 @@ #define HWTC_COUNT (*((uint32_t*)0xE000E018)) #define HWTC_PERIOD ((*(uint32_t*)0xE000E014) + 1) #define HWTC_DIVISOR 2 + + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant #elif (SELECTED_PORT == PORT_Renesas_RX600) @@ -249,6 +281,39 @@ #define HWTC_PERIOD ((((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/8)) #define HWTC_DIVISOR 1 + #define IRQ_PRIORITY_ORDER 1 // higher irq priority values are more significant + +#elif (SELECTED_PORT == PORT_MICROCHIP_dsPIC_AND_PIC24) + + /* For Microchip PIC24 and dsPIC (16 bit) */ + + /* Note: The trace library was originally designed for 32-bit MCUs, and is slower + than intended on 16-bit MCUs. Storing an event on a PIC24 takes about 70 µs. + In comparison, 32-bit MCUs are often 10-20 times faster. If recording overhead + becomes a problem on PIC24, use the filters to exclude less interresting tasks + or system calls. */ + + #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING + #define HWTC_COUNT (TMR1) + #define HWTC_PERIOD (PR1+1) + #define HWTC_DIVISOR 1 + + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant + +#elif (SELECTED_PORT == PORT_NXP_LPC210X) + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + + /* Tested with LPC2106, but should work with most LPC21XX chips. + Assumption: prescaler is 1:1 (this setting is hardcoded in + FreeRTOS port for LPC21XX) */ + + #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING + #define HWTC_COUNT *((uint32_t *)0xE0004008 ) + #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) + #define HWTC_DIVISOR 1 + + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant + #elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_TMS570) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ @@ -260,6 +325,8 @@ #define HWTC_PERIOD (RTIUDCP0) #define HWTC_DIVISOR 1 + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant + #elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_MSP430) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ @@ -268,6 +335,8 @@ #define HWTC_PERIOD configCPU_CLOCKS_PER_TICK #define HWTC_DIVISOR 1 + #define IRQ_PRIORITY_ORDER 1 // higher irq priority values are more significant + #elif (SELECTED_PORT == PORT_MICROCHIP_PIC32) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ @@ -276,13 +345,7 @@ #define HWTC_PERIOD (ReadPeriod1()+1) /* Should be available in BSP */ #define HWTC_DIVISOR 1 -#elif (SELECTED_PORT == PORT_MICROCHIP_dsPIC_AND_PIC24) - /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ - - #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING - #define HWTC_COUNT (PR1) - #define HWTC_PERIOD ((configCPU_CLOCK_HZ/portTIMER_PRESCALE)/configTICK_RATE_HZ) - #define HWTC_DIVISOR 1 + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant #elif (SELECTED_PORT == PORT_XILINX_PPC405) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ @@ -290,7 +353,9 @@ #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING #define HWTC_COUNT mfspr( 0x3db) #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - #define HWTC_DIVISOR 1 + #define HWTC_DIVISOR 1 + + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant #elif (SELECTED_PORT == PORT_XILINX_PPC440) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ @@ -302,38 +367,61 @@ #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) #define HWTC_DIVISOR 1 -#else -#error "SELECTED_PORT is not set, or had unsupported value!" -#endif + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant + +#elif (SELECTED_PORT == PORT_XILINX_MICROBLAZE) + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ -#ifndef HWTC_COUNT_DIRECTION -#error "HWTC_COUNT_DIRECTION is not set!" -#endif + /* This should work with most Microblaze configurations + * This port is based on the official FreeRTOS Microlaze port and example application. + * It uses the AXI Timer 0 - the tick interrupt source. + * If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required. + */ + #include "xtmrctr_l.h" -#ifndef HWTC_COUNT -#error "HWTC_COUNT is not set!" -#endif + #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING + #define HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 ) + #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) + #define HWTC_DIVISOR 16 -#ifndef HWTC_PERIOD -#error "HWTC_PERIOD is not set!" -#endif + #define IRQ_PRIORITY_ORDER 0 // lower irq priority values are more significant -#ifndef HWTC_DIVISOR -#error "HWTC_DIVISOR is not set!" -#endif +#elif (SELECTED_PORT != PORT_NOT_SET) -#ifndef IRQ_PRIORITY_ORDER -#error "IRQ_PRIORITY_ORDER is not set!" -#endif + #error "SELECTED_PORT had unsupported value!" + #define SELECTED_PORT PORT_NOT_SET -#if (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1) -#error "IRQ_PRIORITY_ORDER has bad value!" -#endif +#endif -#if (HWTC_DIVISOR < 1) -#error "HWTC_DIVISOR must be a non-zero positive value!" -#endif +#if (SELECTED_PORT != PORT_NOT_SET) + + #ifndef HWTC_COUNT_DIRECTION + #error "HWTC_COUNT_DIRECTION is not set!" + #endif + + #ifndef HWTC_COUNT + #error "HWTC_COUNT is not set!" + #endif + + #ifndef HWTC_PERIOD + #error "HWTC_PERIOD is not set!" + #endif + + #ifndef HWTC_DIVISOR + #error "HWTC_DIVISOR is not set!" + #endif + + #ifndef IRQ_PRIORITY_ORDER + #error "IRQ_PRIORITY_ORDER is not set!" + #elif (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1) + #error "IRQ_PRIORITY_ORDER has bad value!" + #endif + + #if (HWTC_DIVISOR < 1) + #error "HWTC_DIVISOR must be a non-zero positive value!" + #endif +#endif /******************************************************************************* * vTraceConsoleMessage * @@ -341,6 +429,11 @@ * This needs to be correctly defined to see status reports from the trace * status monitor task (this is defined in trcUser.c). ******************************************************************************/ +#if (SELECTED_PORT == PORT_Atmel_AT91SAM7) +/* Port specific includes */ +#include "console.h" +#endif + #define vTraceConsoleMessage(x) /******************************************************************************* @@ -358,9 +451,9 @@ * students, hobbyists or early-phase startups) we have an attractive offer: * Provide a hardware timer port and get a FREE single-user licence for * FreeRTOS+Trace Professional Edition. Read more about this offer at - * www.percepio.se or contact us directly at support@percepio.se. + * www.percepio.com or contact us directly at support@percepio.com. ******************************************************************************/ -uint32_t uiTracePortGetTimeStamp(void); +void uiTracePortGetTimeStamp(uint32_t *puiTimestamp); /******************************************************************************* * vTracePortEnd diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcBase.h b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcBase.h index a53d69244..4ffd55c6a 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcBase.h +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcBase.h @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcBase.h * @@ -33,10 +33,10 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ #ifndef TRCBASE_H @@ -44,12 +44,16 @@ #include #include -#include + #include "FreeRTOS.h" #include "trcConfig.h" #include "trcTypes.h" #include "trcPort.h" +extern volatile int recorder_busy; + +#define trcCRITICAL_SECTION_BEGIN() {taskENTER_CRITICAL(); recorder_busy++;} +#define trcCRITICAL_SECTION_END() {recorder_busy--; taskEXIT_CRITICAL();} #define NCLASSES 5 #define VERSION 0x1AA1 @@ -155,7 +159,7 @@ typedef struct uint8_t type; objectHandleType objHandle; uint16_t dts; /* differential timestamp - time since last event */ -} TSEvent; +} TSEvent, TREvent; typedef struct { @@ -245,11 +249,11 @@ typedef struct uint8_t irq_priority_order; /* sizeof(RecorderDataType) - just for control */ - uint32_t filesize; - + uint32_t filesize; + /* Current number of events recorded */ uint32_t numEvents; - + /* The buffer size, in number of event records */ uint32_t maxEvents; @@ -382,11 +386,14 @@ typedef struct extern objectHandleStackType objectHandleStacks; -extern uint8_t taskFlags[NTask]; +/* Structures to handle the exclude flags for all objects, tasks and event codes */ +#define NEventCodes 0x100 +extern uint8_t excludedFlags[(NEventCodes+NQueue+NSemaphore+NMutex+NTask) / 8 + 1]; +extern uint8_t ifeFlags[NTask / 8 + 1]; /* Internal functions */ -uint32_t prvTraceGetDTS(uint32_t param_maxDTS); +uint16_t prvTraceGetDTS(uint16_t param_maxDTS); void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength); @@ -404,7 +411,7 @@ traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel); void prvTraceUpdateCounters(void); -void prvCheckDataToBeOverwrittenForMultiEntryUserEvents(uint32_t nEntries); +void prvCheckDataToBeOverwrittenForMultiEntryUserEvents(uint8_t nEntries); objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass); @@ -417,7 +424,7 @@ void vTraceSetObjectName(traceObjectClass objectclass, void* xTraceNextFreeEventBufferSlot(void); -uint32_t uiIndexOfObject(objectHandleType objecthandle, +uint16_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass); @@ -427,7 +434,7 @@ uint32_t uiIndexOfObject(objectHandleType objecthandle, * Called by various parts in the recorder. Stops the recorder and stores a * pointer to an error message, which is printed by the monitor task. ******************************************************************************/ -void vTraceError(char* msg); +void vTraceError(const char* msg); /******************************************************************************* * xTraceGetLastError @@ -470,17 +477,37 @@ RecorderDataPtr->ObjectPropertyTable.objbytes \ [uiIndexOfObject(handle, TRACE_CLASS_TASK) \ + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[TRACE_CLASS_TASK]+3] -#define TASK_FLAG_BITMASK_ExcludeTaskFromTrace 1 -#define TASK_FLAG_BITMASK_MarkNextEventAsTaskInstanceFinish 2 +#define SET_FLAG_ISEXCLUDED(bitIndex) excludedFlags[(bitIndex) >> 3] |= (1 << ((bitIndex) & 7)) +#define CLEAR_FLAG_ISEXCLUDED(bitIndex) excludedFlags[(bitIndex) >> 3] &= ~(1 << ((bitIndex) & 7)) +#define GET_FLAG_ISEXCLUDED(bitIndex) (excludedFlags[(bitIndex) >> 3] & (1 << ((bitIndex) & 7))) + +#define SET_FLAG_MARKIFE(bitIndex) ifeFlags[(bitIndex) >> 3] |= (1 << ((bitIndex) & 7)) +#define CLEAR_FLAG_MARKIFE(bitIndex) ifeFlags[(bitIndex) >> 3] &= ~(1 << ((bitIndex) & 7)) +#define GET_FLAG_MARKIFE(bitIndex) (ifeFlags[(bitIndex) >> 3] & (1 << ((bitIndex) & 7))) + +#define SET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) SET_FLAG_ISEXCLUDED(eventCode) +#define CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) CLEAR_FLAG_ISEXCLUDED(eventCode) +#define GET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) GET_FLAG_ISEXCLUDED(eventCode) + +#define SET_QUEUE_FLAG_ISEXCLUDED(queueHandle) SET_FLAG_ISEXCLUDED(NEventCodes+queueHandle-1) +#define CLEAR_QUEUE_FLAG_ISEXCLUDED(queueHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+queueHandle-1) +#define GET_QUEUE_FLAG_ISEXCLUDED(queueHandle) GET_FLAG_ISEXCLUDED(NEventCodes+queueHandle-1) + +#define SET_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreHandle) SET_FLAG_ISEXCLUDED(NEventCodes+NQueue+semaphoreHandle-1) +#define CLEAR_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+NQueue+semaphoreHandle-1) +#define GET_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreHandle) GET_FLAG_ISEXCLUDED(NEventCodes+NQueue+semaphoreHandle-1) -#define SET_TASK_FLAG_ISEXCLUDED(taskHandle) taskFlags[taskHandle] |= 0x01 -#define CLEAR_TASK_FLAG_ISEXCLUDED(taskHandle) taskFlags[taskHandle] &= 0xFE -#define GET_TASK_FLAG_ISEXCLUDED(taskHandle) (taskFlags[taskHandle] & 0x01) +#define SET_MUTEX_FLAG_ISEXCLUDED(mutexHandle) SET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+mutexHandle-1) +#define CLEAR_MUTEX_FLAG_ISEXCLUDED(mutexHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+mutexHandle-1) +#define GET_MUTEX_FLAG_ISEXCLUDED(mutexHandle) GET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+mutexHandle-1) -#define SET_TASK_FLAG_MARKIFE(taskHandle) taskFlags[taskHandle] |= 0x02 -#define CLEAR_TASK_FLAG_MARKIFE(taskHandle) taskFlags[taskHandle] &= 0xFD -#define GET_TASK_FLAG_MARKIFE(taskHandle) (taskFlags[taskHandle] & 0x02) +#define SET_TASK_FLAG_ISEXCLUDED(taskHandle) SET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+NMutex+taskHandle-1) +#define CLEAR_TASK_FLAG_ISEXCLUDED(taskHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+NMutex+taskHandle-1) +#define GET_TASK_FLAG_ISEXCLUDED(taskHandle) GET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+NMutex+taskHandle-1) +#define SET_TASK_FLAG_MARKIFE(bitIndex) SET_FLAG_MARKIFE(bitIndex-1) +#define CLEAR_TASK_FLAG_MARKIFE(bitIndex) CLEAR_FLAG_MARKIFE(bitIndex-1) +#define GET_TASK_FLAG_MARKIFE(bitIndex) GET_FLAG_MARKIFE(bitIndex-1) /* For debug printouts - the names of the object classes */ extern char OBJECTCLASSNAME[NCLASSES][10]; diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcHooks.h b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcHooks.h index 544c4e37c..7876dff15 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcHooks.h +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcHooks.h @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcHooks.h * @@ -45,26 +45,36 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ #ifndef TRCHOOKS_H #define TRCHOOKS_H -#include "trcKernel.h" - #if (configUSE_TRACE_FACILITY == 1) + #include "trcUser.h" + + #undef INCLUDE_xTaskGetSchedulerState #define INCLUDE_xTaskGetSchedulerState 1 + + #undef INCLUDE_xTaskGetCurrentTaskHandle #define INCLUDE_xTaskGetCurrentTaskHandle 1 - - /* Called on each OS tick */ + +#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1 + /* Called for each task that becomes ready */ + #undef traceMOVED_TASK_TO_READY_STATE + #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ + vTraceStoreTaskReady((unsigned char)pxTCB->uxTaskNumber); +#endif + + /* Called on each OS tick. Will call uiPortGetTimestamp to make sure it is called at least once every OS tick. */ #undef traceTASK_INCREMENT_TICK #define traceTASK_INCREMENT_TICK( xTickCount ) \ - {extern uint32_t uiTraceTickCount; uiTraceTickCount = xTickCount;} + if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxMissedTicks == 0) {extern uint32_t uiTraceTickCount; uiTraceTickCount++; uiTracePortGetTimeStamp(0);} /* Called on each task-switch */ #undef traceTASK_SWITCHED_IN @@ -74,7 +84,7 @@ /* Called on vTaskSuspend */ #undef traceTASK_SUSPEND #define traceTASK_SUSPEND( pxTaskToSuspend ) \ - vTraceStoreKernelCall(TASK_SUSPEND, pxTaskToSuspend->uxTaskNumber); \ + vTraceStoreKernelCall(TASK_SUSPEND, TRACE_CLASS_TASK, pxTaskToSuspend->uxTaskNumber); \ vTraceSetTaskInstanceFinished((uint8_t)pxTaskToSuspend->uxTaskNumber); /* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */ @@ -93,16 +103,22 @@ vTraceSetTaskInstanceFinished((uint8_t)pxCurrentTCB->uxTaskNumber); \ portEXIT_CRITICAL(); +#ifndef INCLUDE_OBJECT_DELETE +#define INCLUDE_OBJECT_DELETE 0 +#endif + #if (INCLUDE_OBJECT_DELETE == 1) /* Called on vTaskDelete */ #undef traceTASK_DELETE #define traceTASK_DELETE( pxTaskToDelete ) \ - vTraceStoreKernelCall(EVENTGROUP_DELETE + TRACE_CLASS_TASK, pxTaskToDelete->uxTaskNumber); \ + trcCRITICAL_SECTION_BEGIN(); \ + vTraceStoreKernelCall(EVENTGROUP_DELETE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, pxTaskToDelete->uxTaskNumber); \ vTraceStoreObjectNameOnCloseEvent((objectHandleType)pxTaskToDelete->uxTaskNumber, TRACE_CLASS_TASK); \ vTraceStoreObjectPropertiesOnCloseEvent((objectHandleType)pxTaskToDelete->uxTaskNumber, TRACE_CLASS_TASK); \ vTraceSetPriorityProperty(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber, (uint8_t)pxTaskToDelete->uxPriority); \ vTraceSetObjectState(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber, TASK_STATE_INSTANCE_NOT_ACTIVE); \ - vTraceFreeObjectHandle(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber); + vTraceFreeObjectHandle(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber); \ + trcCRITICAL_SECTION_END(); #endif /* Called on vTaskCreate */ @@ -112,14 +128,14 @@ pxNewTCB->uxTaskNumber = xTraceGetObjectHandle(TRACE_CLASS_TASK); \ vTraceSetObjectName(TRACE_CLASS_TASK, (objectHandleType)pxNewTCB->uxTaskNumber, (char*)pxNewTCB->pcTaskName); \ vTraceSetPriorityProperty(TRACE_CLASS_TASK, (objectHandleType)pxNewTCB->uxTaskNumber, (uint8_t)pxNewTCB->uxPriority); \ - vTraceStoreKernelCall(EVENTGROUP_CREATE + TRACE_CLASS_TASK, (objectHandleType)pxNewTCB->uxTaskNumber);\ + vTraceStoreKernelCall(EVENTGROUP_CREATE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, pxNewTCB->uxTaskNumber);\ } - /* Called in vTaskCreate, if it fails (typically if the stack fails can not be allocated) */ + /* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */ #undef traceTASK_CREATE_FAILED #define traceTASK_CREATE_FAILED() \ portENTER_CRITICAL();\ - vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK, 0); \ + vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, 0); \ portEXIT_CRITICAL(); /* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */ @@ -127,15 +143,15 @@ #define traceQUEUE_CREATE( pxNewQueue )\ portENTER_CRITICAL(); \ pxNewQueue->ucQueueNumber = xTraceGetObjectHandle(TraceObjectClassTable[pxNewQueue->ucQueueType]);\ + vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \ vTraceSetObjectState(TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber, 0); \ - vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \ portEXIT_CRITICAL(); /* Called in xQueueCreate, if the queue creation fails */ #undef traceQUEUE_CREATE_FAILED #define traceQUEUE_CREATE_FAILED( queueType ) \ portENTER_CRITICAL();\ - vTraceStoreKernelCall((uint8_t)(EVENTGROUP_FAILED_CREATE + TraceObjectClassTable[queueType]), (objectHandleType)0); \ + vTraceStoreKernelCall((uint8_t)(EVENTGROUP_FAILED_CREATE + TraceObjectClassTable[queueType]), TraceObjectClassTable[queueType], 0); \ portEXIT_CRITICAL(); /* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */ @@ -143,28 +159,28 @@ #define traceCREATE_MUTEX( pxNewQueue ) \ portENTER_CRITICAL();\ pxNewQueue->ucQueueNumber = xTraceGetObjectHandle(TRACE_CLASS_MUTEX); \ - vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \ - vTraceSetObjectState(TRACE_CLASS_MUTEX, pxNewQueue->ucQueueNumber, 0); \ + vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \ + vTraceSetObjectState(TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber, 0); \ portEXIT_CRITICAL(); /* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */ #undef traceCREATE_MUTEX_FAILED #define traceCREATE_MUTEX_FAILED() \ portENTER_CRITICAL();\ - vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_MUTEX, 0);\ + vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_MUTEX, TRACE_CLASS_MUTEX, 0);\ portEXIT_CRITICAL(); /* Called when the Mutex can not be given, since not holder */ #undef traceGIVE_MUTEX_RECURSIVE_FAILED #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) \ portENTER_CRITICAL();\ - vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TRACE_CLASS_MUTEX, pxMutex->ucQueueNumber); \ + vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TRACE_CLASS_MUTEX, TRACE_CLASS_MUTEX, pxMutex->ucQueueNumber); \ portEXIT_CRITICAL(); /* Called when a message is sent to a queue */ #undef traceQUEUE_SEND #define traceQUEUE_SEND( pxQueue ) \ - vTraceStoreKernelCall(EVENTGROUP_SEND + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ + vTraceStoreKernelCall(EVENTGROUP_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){\ vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (uint8_t)pxQueue->ucQueueNumber, (uint8_t)0); \ }else{\ @@ -175,20 +191,20 @@ #undef traceQUEUE_SEND_FAILED #define traceQUEUE_SEND_FAILED( pxQueue ) \ portENTER_CRITICAL();\ - vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ + vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ portEXIT_CRITICAL(); /* Called when the task is blocked due to a send operation on a full queue */ #undef traceBLOCKING_ON_QUEUE_SEND #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) \ portENTER_CRITICAL();\ - vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_SEND + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ + vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ portEXIT_CRITICAL(); /* Called when a message is received from a queue */ #undef traceQUEUE_RECEIVE #define traceQUEUE_RECEIVE( pxQueue ) \ - vTraceStoreKernelCall(EVENTGROUP_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ + vTraceStoreKernelCall(EVENTGROUP_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){\ extern volatile void * volatile pxCurrentTCB; \ vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxCurrentTCB)); /*For mutex, store the new owner rather than queue length */ \ @@ -200,7 +216,7 @@ #undef traceBLOCKING_ON_QUEUE_RECEIVE #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \ portENTER_CRITICAL(); \ - vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ + vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ if (TraceObjectClassTable[pxQueue->ucQueueType] != TRACE_CLASS_MUTEX){\ extern volatile void * volatile pxCurrentTCB; \ vTraceSetTaskInstanceFinished((objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxCurrentTCB)); \ @@ -210,36 +226,36 @@ /* Called on xQueuePeek */ #undef traceQUEUE_PEEK #define traceQUEUE_PEEK( pxQueue ) \ - vTraceStoreKernelCall(EVENTGROUP_PEEK + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); + vTraceStoreKernelCall(EVENTGROUP_PEEK + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); /* Called when a receive operation on a queue fails (timeout) */ #undef traceQUEUE_RECEIVE_FAILED #define traceQUEUE_RECEIVE_FAILED( pxQueue ) \ portENTER_CRITICAL(); \ - vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ + vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ portEXIT_CRITICAL(); /* Called when a message is sent from interrupt context, e.g., using xQueueSendFromISR */ #undef traceQUEUE_SEND_FROM_ISR #define traceQUEUE_SEND_FROM_ISR( pxQueue ) \ - vTraceStoreKernelCall(EVENTGROUP_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ - vTraceSetObjectState(TRACE_CLASS_QUEUE, (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting + 1)); + vTraceStoreKernelCall(EVENTGROUP_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ + vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting + 1)); /* Called when a message send from interrupt context fails (since the queue was full) */ #undef traceQUEUE_SEND_FROM_ISR_FAILED #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) \ - vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); + vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); /* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */ #undef traceQUEUE_RECEIVE_FROM_ISR #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \ - vTraceStoreKernelCall(EVENTGROUP_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ - vTraceSetObjectState(TRACE_CLASS_QUEUE, (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting - 1)); + vTraceStoreKernelCall(EVENTGROUP_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ + vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting - 1)); /* Called when a message receive from interrupt context fails (since the queue was empty) */ #undef traceQUEUE_RECEIVE_FROM_ISR_FAILED #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) \ - vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); + vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); #if (INCLUDE_OBJECT_DELETE == 1) /* Called on vQueueDelete */ @@ -247,7 +263,7 @@ #define traceQUEUE_DELETE( pxQueue ) \ { \ portENTER_CRITICAL();\ - vTraceStoreKernelCall(EVENTGROUP_DELETE + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ + vTraceStoreKernelCall(EVENTGROUP_DELETE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ vTraceStoreObjectNameOnCloseEvent((objectHandleType)pxQueue->ucQueueNumber, TraceObjectClassTable[pxQueue->ucQueueType]); \ vTraceStoreObjectPropertiesOnCloseEvent((objectHandleType)pxQueue->ucQueueNumber, TraceObjectClassTable[pxQueue->ucQueueType]); \ if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){ \ @@ -263,30 +279,30 @@ /* Called in vTaskPrioritySet */ #undef traceTASK_PRIORITY_SET #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \ - vTraceStoreKernelCallWithParam(TASK_PRIORITY_SET, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\ + vTraceStoreKernelCallWithParam(TASK_PRIORITY_SET, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\ vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority); /* Called in vTaskPriorityInherit, which is called by Mutex operations */ #undef traceTASK_PRIORITY_INHERIT #define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \ - vTraceStoreKernelCallWithParam(TASK_PRIORITY_INHERIT, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\ + vTraceStoreKernelCallWithParam(TASK_PRIORITY_INHERIT, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\ vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority ); /* Called in vTaskPriorityDisinherit, which is called by Mutex operations */ #undef traceTASK_PRIORITY_DISINHERIT #define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \ - vTraceStoreKernelCallWithParam(TASK_PRIORITY_DISINHERIT, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\ + vTraceStoreKernelCallWithParam(TASK_PRIORITY_DISINHERIT, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\ vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority ); /* Called in vTaskResume */ #undef traceTASK_RESUME #define traceTASK_RESUME( pxTaskToResume ) \ - vTraceStoreKernelCall(TASK_RESUME, pxTaskToResume->uxTaskNumber); + vTraceStoreKernelCall(TASK_RESUME, TRACE_CLASS_TASK, pxTaskToResume->uxTaskNumber); /* Called in vTaskResumeFromISR */ #undef traceTASK_RESUME_FROM_ISR #define traceTASK_RESUME_FROM_ISR( pxTaskToResume )\ - vTraceStoreKernelCall(TASK_RESUME_FROM_ISR, pxTaskToResume->uxTaskNumber); + vTraceStoreKernelCall(TASK_RESUME_FROM_ISR, TRACE_CLASS_TASK, pxTaskToResume->uxTaskNumber); #endif -#endif \ No newline at end of file +#endif diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcKernel.h b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcKernel.h index ca678acd6..c81db92e1 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcKernel.h +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcKernel.h @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcKernel.h * @@ -33,32 +33,33 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ #ifndef TRCKERNEL_H #define TRCKERNEL_H -#include "trcTypes.h" - -#if (configUSE_TRACE_FACILITY == 1) - #include "trcBase.h" /* Internal functions */ + +#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1 +void vTraceStoreTaskReady(objectHandleType handle); +#endif + void vTraceStoreTaskswitch(void); -void vTraceStoreKernelCall(uint32_t eventcode, uint32_t byteParam); +void vTraceStoreKernelCall(uint32_t eventcode, traceObjectClass objectClass, uint32_t byteParam); void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint16_t param); -void vTraceStoreKernelCallWithParam(uint32_t evtcode, uint32_t objectNumber, - uint8_t param); +void vTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass, + uint32_t objectNumber, uint8_t param); void vTraceSetTaskInstanceFinished(objectHandleType handle); @@ -84,6 +85,8 @@ void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle, #define TASK_STATE_INSTANCE_ACTIVE 1 #define TASK_STATE_INSTANCE_MARKED_FINISHED 2 +extern objectHandleType handle_of_running_task; + /* This defines the mapping between FreeRTOS queue types and our internal class IDs */ extern traceObjectClass TraceObjectClassTable[5]; @@ -102,8 +105,14 @@ extern traceObjectClass TraceObjectClassTable[5]; ******************************************************************************/ #define NULL_EVENT (0x00) /* Ignored in the analysis*/ -#define RECORDING_START (0x01) /* Not yet used */ -#define RECORDING_STOP (0x02) /* Not yet used */ + +/******************************************************************************* + * EVENTGROUP_RE + * + * Events that indicate that something is ready to execute. + ******************************************************************************/ +#define EVENTGROUP_RE (NULL_EVENT + 2) /*0x02*/ +#define TR_TASK_READY (EVENTGROUP_RE + 0) /*0x02*/ /******************************************************************************* * EVENTGROUP_TS @@ -111,11 +120,11 @@ extern traceObjectClass TraceObjectClassTable[5]; * Events for storing task-switches and interrupts. The RESUME events are * generated if the task/interrupt is already marked active. ******************************************************************************/ -#define EVENTGROUP_TS (0x04) -#define TS_ISR_BEGIN (EVENTGROUP_TS + 0) /* 4 */ -#define TS_ISR_RESUME (EVENTGROUP_TS + 1) /* 5 */ -#define TS_TASK_BEGIN (EVENTGROUP_TS + 2) /* 6 */ -#define TS_TASK_RESUME (EVENTGROUP_TS + 3) /* 7 */ +#define EVENTGROUP_TS (EVENTGROUP_RE + 2) /*0x04*/ +#define TS_ISR_BEGIN (EVENTGROUP_TS + 0) /*0x04*/ +#define TS_ISR_RESUME (EVENTGROUP_TS + 1) /*0x05*/ +#define TS_TASK_BEGIN (EVENTGROUP_TS + 2) /*0x06*/ +#define TS_TASK_RESUME (EVENTGROUP_TS + 3) /*0x07*/ /******************************************************************************* * EVENTGROUP_OBJCLOSE_NAME @@ -126,7 +135,7 @@ extern traceObjectClass TraceObjectClassTable[5]; * EVENTGROUP_OBJCLOSE_PROP), containg the handle-name mapping and object * properties valid up to this point. ******************************************************************************/ -#define EVENTGROUP_OBJCLOSE_NAME (0x08) +#define EVENTGROUP_OBJCLOSE_NAME (EVENTGROUP_TS + 4) /*0x08*/ /******************************************************************************* * EVENTGROUP_OBJCLOSE_PROP @@ -214,14 +223,14 @@ extern traceObjectClass TraceObjectClassTable[5]; /* Other events - object class is implied: TASK */ #define EVENTGROUP_OTHERS (EVENTGROUP_DELETE + 8) /*0x88*/ -#define TASK_DELAY_UNTIL (EVENTGROUP_OTHERS + 0) -#define TASK_DELAY (EVENTGROUP_OTHERS + 1) -#define TASK_SUSPEND (EVENTGROUP_OTHERS + 2) -#define TASK_RESUME (EVENTGROUP_OTHERS + 3) -#define TASK_RESUME_FROM_ISR (EVENTGROUP_OTHERS + 4) -#define TASK_PRIORITY_SET (EVENTGROUP_OTHERS + 5) -#define TASK_PRIORITY_INHERIT (EVENTGROUP_OTHERS + 6) -#define TASK_PRIORITY_DISINHERIT (EVENTGROUP_OTHERS + 7) +#define TASK_DELAY_UNTIL (EVENTGROUP_OTHERS + 0) /*0x88*/ +#define TASK_DELAY (EVENTGROUP_OTHERS + 1) /*0x89*/ +#define TASK_SUSPEND (EVENTGROUP_OTHERS + 2) /*0x8A*/ +#define TASK_RESUME (EVENTGROUP_OTHERS + 3) /*0x8B*/ +#define TASK_RESUME_FROM_ISR (EVENTGROUP_OTHERS + 4) /*0x8C*/ +#define TASK_PRIORITY_SET (EVENTGROUP_OTHERS + 5) /*0x8D*/ +#define TASK_PRIORITY_INHERIT (EVENTGROUP_OTHERS + 6) /*0x8E*/ +#define TASK_PRIORITY_DISINHERIT (EVENTGROUP_OTHERS + 7) /*0x8F*/ /* Not yet used */ #define EVENTGROUP_FTRACE_PLACEHOLDER (EVENTGROUP_OTHERS + 8) /*0x90*/ @@ -231,9 +240,9 @@ extern traceObjectClass TraceObjectClassTable[5]; #define USER_EVENT (EVENTGROUP_USEREVENT + 0) /* Allow for 0-15 arguments (the number of args is added to event code) */ -#define USER_EVENT_LAST (EVENTGROUP_USEREVENT + 15) +#define USER_EVENT_LAST (EVENTGROUP_USEREVENT + 15) /*0xA7*/ -/****************************************************************************** +/******************************************************************************* * XTS Event - eXtended TimeStamp events * The timestamps used in the recorder are "differential timestamps" (DTS), i.e. * the time since the last stored event. The DTS fields are either 1 or 2 bytes @@ -263,5 +272,3 @@ extern traceObjectClass TraceObjectClassTable[5]; #define RESERVED_DUMMY_CODE (EVENTGROUP_SYS + 3) /*0xAB*/ #endif - -#endif \ No newline at end of file diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcTypes.h b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcTypes.h index 32e41565f..7bf438c8b 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcTypes.h +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcTypes.h @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcTypes.h * @@ -33,10 +33,10 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ #ifndef TRCTYPES_H @@ -56,4 +56,26 @@ typedef uint8_t traceObjectClass; #define TRACE_CLASS_TASK ((traceObjectClass)3) #define TRACE_CLASS_ISR ((traceObjectClass)4) +typedef uint8_t traceKernelService; + +#define TRACE_KERNEL_SERVICE_TASK_CREATE ((traceKernelService)0) +#define TRACE_KERNEL_SERVICE_TASK_DELETE ((traceKernelService)1) +#define TRACE_KERNEL_SERVICE_TASK_DELAY ((traceKernelService)2) +#define TRACE_KERNEL_SERVICE_PRIORITY_SET ((traceKernelService)3) +#define TRACE_KERNEL_SERVICE_TASK_SUSPEND ((traceKernelService)4) +#define TRACE_KERNEL_SERVICE_TASK_RESUME ((traceKernelService)5) +#define TRACE_KERNEL_SERVICE_QUEUE_CREATE ((traceKernelService)6) +#define TRACE_KERNEL_SERVICE_QUEUE_DELETE ((traceKernelService)7) +#define TRACE_KERNEL_SERVICE_QUEUE_SEND ((traceKernelService)8) +#define TRACE_KERNEL_SERVICE_QUEUE_RECEIVE ((traceKernelService)9) +#define TRACE_KERNEL_SERVICE_QUEUE_PEEK ((traceKernelService)10) +#define TRACE_KERNEL_SERVICE_MUTEX_CREATE ((traceKernelService)11) +#define TRACE_KERNEL_SERVICE_MUTEX_DELETE ((traceKernelService)12) +#define TRACE_KERNEL_SERVICE_MUTEX_GIVE ((traceKernelService)13) +#define TRACE_KERNEL_SERVICE_MUTEX_TAKE ((traceKernelService)14) +#define TRACE_KERNEL_SERVICE_SEMAPHORE_CREATE ((traceKernelService)15) +#define TRACE_KERNEL_SERVICE_SEMAPHORE_DELETE ((traceKernelService)16) +#define TRACE_KERNEL_SERVICE_SEMAPHORE_GIVE ((traceKernelService)17) +#define TRACE_KERNEL_SERVICE_SEMAPHORE_TAKE ((traceKernelService)18) + #endif diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcUser.h b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcUser.h index 984bc16df..3e80162fa 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcUser.h +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/Include/trcUser.h @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcUser.h * The public API of the trace recorder library. @@ -32,10 +32,10 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ #ifndef TRCUSER_H @@ -43,9 +43,9 @@ #include "FreeRTOS.h" -#if (configUSE_TRACE_FACILITY == 1) +#include "trcKernel.h" -#include "trcBase.h" +#if (configUSE_TRACE_FACILITY == 1) #ifdef __cplusplus extern "C" { @@ -147,14 +147,22 @@ void vTraceSetQueueName(void* queue, const char* name); * portEXIT_CRITICAL(); * } ******************************************************************************/ -void vTraceSetISRProperties(objectHandleType handle, char* name, char priority); +void vTraceSetISRProperties(objectHandleType handle, const char* name, char priority); /******************************************************************************* * vTraceStoreISRBegin * - * Registers the beginning of an Interrupt Service Routine. This must not be - * interrupted by another ISR containing recorder library calls, so if allowing - * nested ISRs this must be called with interrupts disabled. + * Registers the beginning of an Interrupt Service Routine. + * + * Note! This may only be used for interrupts affected by portENTER_CRITICAL. + * In some FreeRTOS ports, such as ARM Cortex M3, this does not disable all + * interrupts. Interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY are still + * enabled, but may not call the FreeRTOS API. Such may not call the recorder + * API, including this function. + * + * See http://www.freertos.org/a00110.html + * + * If allowing nested ISRs, this must be called with interrupts disabled. * * Example: * #define ID_ISR_TIMER1 1 // lowest valid ID is 1 @@ -178,9 +186,17 @@ void vTraceStoreISRBegin(objectHandleType id); /******************************************************************************* * vTraceStoreISREnd * - * Registers the end of an Interrupt Service Routine. This must not be - * interrupted by another ISR containing recorder library calls, so if allowing - * nested ISRs this must be called with interrupts disabled. + * Registers the end of an Interrupt Service Routine. + * + * Note! This may only be used for interrupts affected by portENTER_CRITICAL. + * In some FreeRTOS ports, such as ARM Cortex M3, this does not disable all + * interrupts. Interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY are still + * enabled, but may not call the FreeRTOS API. Such may not call the recorder + * API, including this function. + * + * See http://www.freertos.org/a00110.html + * + * If allowing nested ISRs, this must be called with interrupts disabled. * * Example: * #define ID_ISR_TIMER1 1 // lowest valid ID is 1 @@ -202,12 +218,15 @@ void vTraceStoreISRBegin(objectHandleType id); void vTraceStoreISREnd(void); #else - /* If not including the ISR recording */ - #define vTraceSetISRProperties(handle, name, priority) - #define vTraceStoreISRBegin(id) - #define vTraceStoreISREnd() +void vTraceIncreaseISRActive(void); + +void vTraceDecreaseISRActive(void); + +#define vTraceSetISRProperties(handle, name, priority) +#define vTraceStoreISRBegin(id) vTraceIncreaseISRActive() +#define vTraceStoreISREnd() vTraceDecreaseISRActive() #endif @@ -290,7 +309,7 @@ uint32_t uiTraceGetTraceBufferSize(void); * executed and/or located in time-critical code. The lookup operation is * however fairly fast due to the design of the symbol table. ******************************************************************************/ -traceLabel xTraceOpenLabel(char* label); +traceLabel xTraceOpenLabel(const char* label); /****************************************************************************** * vTraceUserEvent @@ -341,16 +360,21 @@ void vTraceUserEvent(traceLabel eventLabel); * %hu - 16 bit unsigned integer * %bd - 8 bit signed integer * %bu - 8 bit unsigned integer - * %lf - double-precision float + * %lf - double-precision float (Note! See below...) * * Up to 15 data arguments are allowed, with a total size of maximum 32 byte. * In case this is exceeded, the user event is changed into an error message. * * The data is stored in trace buffer, and is packed to allow storing multiple * smaller data entries in the same 4-byte record, e.g., four 8-bit values. - * A string requires two bytes, as the symbol table is limited to 64K. Storing a - * double (%lf) uses two records, so this is quite costly. Use float (%f) unless - * the higher precision is really necessary. + * A string requires two bytes, as the symbol table is limited to 64K. Storing + * a double (%lf) uses two records, so this is quite costly. Use float (%f) + * unless the higher precision is really necessary. + * + * Note that the double-precision float (%lf) assumes a 64 bit double + * representation. This does not seem to be the case on e.g. PIC24F. + * Before using a %lf argument on a 16-bit MCU, please verify that + * "sizeof(double)" actually gives 8 as expected. If not, use %f instead. ******************************************************************************/ void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...); @@ -363,14 +387,30 @@ void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...); #endif /****************************************************************************** - * vTraceExcludeTask + * vTraceExclude______FromTrace * - * Excludes a task from the recording using a flag in the Object Property Table. + * Excludes a task or object from the trace. * This can be useful if some irrelevant task is very frequent and is "eating - * up the buffer". This should be called the task has been created, but + * up the buffer". This should be called after the task has been created, but * before starting the FreeRTOS scheduler. *****************************************************************************/ -void vTraceExcludeTaskFromSchedulingTrace(const char* name); +void vTraceExcludeQueueFromTrace(void* handle); +void vTraceExcludeSemaphoreFromTrace(void* handle); +void vTraceExcludeMutexFromTrace(void* handle); +void vTraceExcludeTaskFromTrace(void* handle); +void vTraceExcludeKernelServiceFromTrace(traceKernelService kernelService); + +/****************************************************************************** + * vTraceInclude______InTrace + * + * Includes a task, object or kernel service in the trace. This is only + * necessary if the task or object has been previously exluded. + *****************************************************************************/ +void vTraceIncludeQueueInTrace(void* handle); +void vTraceIncludeSemaphoreInTrace(void* handle); +void vTraceIncludeMutexInTrace(void* handle); +void vTraceIncludeTaskInTrace(void* handle); +void vTraceIncludeKernelServiceInTrace(traceKernelService kernelService); #ifdef __cplusplus } @@ -381,9 +421,12 @@ void vTraceExcludeTaskFromSchedulingTrace(const char* name); #include "trcPort.h" #define vTraceInit() +#define uiTraceStart() (1) #define vTraceStart() #define vTraceStop() #define vTraceClear() +#define vTraceStartStatusMonitor() +#define vTracePortSetOutFile(f) #define vTraceGetTraceBuffer() ((void*)0) #define uiTraceGetTraceBufferSize() 0 #define xTraceOpenLabel(label) 0 @@ -391,9 +434,11 @@ void vTraceExcludeTaskFromSchedulingTrace(const char* name); #define vTracePrintF(eventLabel,formatStr,...) #define vTraceExcludeTaskFromSchedulingTrace(name) #define vTraceSetQueueName(queue, name) + #define vTraceTaskSkipDefaultInstanceFinishedEvents() #define vTraceSetISRProperties(handle, name, priority) #define vTraceStoreISRBegin(id) #define vTraceStoreISREnd() #endif #endif + diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/debugger trace upload.txt b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/debugger trace upload.txt new file mode 100644 index 000000000..417a54bb7 --- /dev/null +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/debugger trace upload.txt @@ -0,0 +1,126 @@ + +FreeRTOS+Trace - Uploading the trace data +----------------------------------------- +Percepio AB, Nov. 8, 2012 + +This document decribes how to upload the trace data from the target system to +FreeRTOS+Trace. For information on how to integrate and enable the recorder +library in your FreeRTOS project, see the FreeRTOS+Trace User Manual. + +FreeRTOS+Trace uses your existing debugger to upload the trace data from the +chip RAM. This is a plain RAM dump, that is done whenever you want to look at +the trace buffer contents. This means it works with essentially with any debug +probe on the market. + +Note that hardware-generated trace is not required (or used by) FreeRTOS+Trace. +We however plan to add support for that in future versions of FreeRTOS+Trace +and other Tracealyzer products. + +Built-in support for Segger J-Link/J-Trace and Atmel SAM-ICE +------------------------------------------------------------ +FreeRTOS+Trace v2.3 supports Segger J-Link and J-Link compatible debuggers +directly, without any debugger IDE involved. Using other debug probes is +also possible, but requires some extra steps, described below. + +If you have a Segger J-Link/J-Trace debug probe or another J-Link compatible +debug probe, just select + + "File" menu -> "Upload from ". + +This opens a dialog where you get to enter the memory region where +the recorder data structure is located. Normally you select the entire +internal RAM according to the datasheet of your MCU, but the exact address +can be found can by inspecting the "RecorderData" struct or the +"RecorderDataPtr" pointer with your debugger. + +Typical values are 0x0, 0x10000000 or 0x20000000 as start address +and 0x10000 or 0x20000 as size (64 KB or 128 KB). + +This makes FreeRTOS+Trace reads the chip RAM and locate the trace data. +Note that this option is only available if a compatible debug probe is found. + +J-Link compatible debug probes also include Atmel SAM-ICE and many built-in +debug interfaces on demonstration/evaluation boards (where there is a USB +connection directly to the board). Look for a Segger J-Link label on the board. + +MemoryLogger extension in Atmel Studio 6 +---------------------------------------- +Atmel's new MemoryLogger extension provides a superb integration with +FreeRTOS+Trace. Look for "MemoryLogger" in Atmel Gallery, available in +Atmel Studio and at the Atmel website. + +This extension automatically detects the path to FreeRTOS+Trace, if +installed, and gives you a single-click upload/refresh. You can use it +while debugging and optionally get an automatic refresh eash time the +MCU is halted, e.g., on each breakpoint. + +Using other development environments and debug probes +----------------------------------------------------- +Most debuggers are able to save the RAM contents to a file. FreeRTOS+Trace +supports the following common formats: +- Binary (.bin), supporting gdb, J-Link and Renesas HEW. +- Intel Hex (.hex), supporting IAR Embedded Workbench and Atmel Studio (atprogram.exe) +- MCH (.mch), supporting Microchip MPLAB. + +When you store the RAM dump, you must also make sure to select the right region, +i.e., start address and size. The recorder data is stored in a single data +block, identified by the pointer RecorderDataPtr. +It is not necessary to match the begin and end of the recorder data, as long as +it is fully included by the dumped memory region. FreeRTOS+Trace automatically +finds the trace data in the RAM dump, thanks to special signatures. For chips +with on-chip RAM only, we therefore recommend to dump the entire RAM. This is +usually very fast. +For chips with larger amounts of (external) RAM, it is typically possible to +dump a limited region where the data is typically found. + +Using IAR Embedded Workbench for ARM, version 6.3 +------------------------------------------------- +In the debugger view, when stopped on a breakpoint: +- Select "Debug" menu, "Memory" submenu, "Save..." (keyboard shortcut: ALT,d,y,s) +- In the Save dialog + - Zone: Memory + - Start Adress: 10000000 (for NXP LPC1766 in the demo project) + - End Adress: 1000FFFF (for NXP LPC1766 in the demo project) + - File format: Intel Extended + - Filename: .hex + - Press "Save" button +You can now open .hex in FreeRTOS+Trace. + +To find the right Start and End addresses, check the address of the symbol +"RecorderData". The addresses does not need to match this symbol exactly, as +long as the whole data is included. + +Using Renesas High-performance Embedded Workshop v4.09 +------------------------------------------------------ +In the debugger view, when stopped on a breakpoint: +- Select "Debug" menu, "Save Memory..." (keyboard shortcut: ALT,d,a) +- In the Save dialog + - Format: Binary + - Filename: .bin + - Start Address: 00000000 (For RX62N in the demo project) + - End Address: 0000FFFF (For RX62N in the demo project) + - Access size: 1 + - Press "Save" button and open .bin in FreeRTOS+Trace. + +Using Microchip MPLAB v8.86 +------------------------------------------------------ +- Select "View" -> "File Registers". This shows you the memory contents. +- Make sure "Hex" is selected in the bottom left (instead of "Symbolic"). Hex mode seems to be default. +- Right click in the view and select "Export Table...". +- In the dialog ("Export As"), make sure "Single Column Output" is selected (seems to be default). +- Select start address 0x0000 and make sure the end address is beyond the RecorderData structure. + The default values seems to be the whole RAM, so you probably don't need to change this. +- 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). + +Using STM32 ST-Link +------------------------------------------------------ +- Start "ST-Link Utility" +- Connect to the device and view the device memory. +- Set the view to display the entire RAM, or at least the section containing the RecorderData structure. +- Select "Save as" and choose binary (.bin) or Intel Hex (.hex) format. +- Open the resulting file in FreeRTOS+Trace. + +In case you have any question, contact support@percepio.com + +Percepio AB +www.percepio.com diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/readme.txt b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/readme.txt index 91a11b80c..0553c8bd1 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/readme.txt +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/readme.txt @@ -1,43 +1,53 @@ -THIS PRODUCT IS UNDER ACTIVE DEVELOPMENT, PLEASE SEE -THE PERCEPIO WEBSITE FOR A COMPLETE LIST OF THE LATEST PORTS - -FreeRTOS+Trace Demo -------------------- +FreeRTOS+Trace Trace Recorder Library +------------------------------------- Percepio AB -www.percepio.se +www.percepio.com + +This directory contains the core trace recorder library used by FreeRTOS+Trace v2.3. + +Ready-to-run demonstrations projects are found at www.percepio.com. + +For information on how to integrate the recorder library in your FreeRTOS build, see +the FreeRTOS+Trace User Manual, section 2. + +For information on how to upload the trace data from your target system RAM to +FreeRTOS+Trace, see "debugger trace upload.txt" -This package contains: -/Demo/DemoAppl The demo application used in the included demo projects. -/Demo/Eclipse-AT91SAM7 Demo project for Eclipse/GCC with Atmel AT91SAM7X256 as preconfigured target. -/Demo/IAR - Cortex M3 Demo project for IAR Embedded Workbench for ARM, with NXP LPC1766 as preconfigured target. -/Demo/Renesas RDK HEW - RX600 Demo project for Renesas HEW, with the RX62N as preconfigured target. -/Demo/MSVC Win32 Demo project Microsoft Visual Studio, using the Win32 port of FreeRTOS. -/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!). -/TraceRecorderSrc The trace recorder library for FreeRTOS / FreeRTOS+Trace. +NOTE: This trace recorder library requires FreeRTOS v7.3.0 or later. -Note that the individual Demo project directories are not self-contained. -They refer to the FreeRTOS-v7.1.1, DemoAppl and TraceRecorderSrc directories. +Files included +-------------- +- trcConfig.h - The recorder's configuration file, check this! +- trcUser.c / trcUser.h - The main API towards the application (trcUser.h in the only include necessary). +- trcKernel.c / trcKernel.h - Internal routines for storing kernel events. +- trcBase.c / trcBase.h - Internal routines for manipulating the data structures and calculating timestamps. +- trcPort.c / trcPort.h - The port layer, abstracting the hardware (mainly the timer used for timestamping). +- trcHooks.h - The interface between FreeRTOS and the recorder, containing trace macro defintions. +- trcTypes.h - Type definitions used. Hardware Timer Ports -------------------- This release contains hardware timer ports for the following hardware architectures: -- ARM Cortex M3/M4 (all brands) -- Atmel AT91SAM7X -- Renesas RX600 +- ARM Cortex M3/M4 (all brands, such as Atmel SAM3/SAM4, NXP 17xx, 18xx, 43xx, STM32, Freescale Kinetis, ...) +- Atmel AT91SAM7x +- Atmel AT32UC3 (AVR32) +- Renesas RX600 (e.g., RX62N) +- Microchip dsPIC/PIC24 -The package moreover contain several "unofficial" ports, provided by external contributors and not yet verified by Percepio AB. -See trcPort.h for the details. +These are defined in trcPort.h. This also contains several "unofficial" ports, provided by external contributors. +By unofficial, it means that they are not yet verified by Percepio AB. Please refer to trcPort.h for detailed information. +If you use an unofficial port and beleive it is incorrect, please let us know! -In case your hardware is not yet directly supported, developing a new port is quite easy. -See trcPort.h for further information. +In case your MCU is not yet supported directly, developing a new port is quite easy, just a matter of defining a few macros +according to your specific MCU. See trcPort.h for further information. -In case you have any questions, do not hesitate to contact support@percepio.se +In case you have any questions, do not hesitate to contact support@percepio.com Percepio AB Köpmangatan 1A 72215 Västerås Sweden -www.percepio.se \ No newline at end of file +www.percepio.com \ No newline at end of file diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcBase.c b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcBase.c index 7146c0f08..c80915cc9 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcBase.c +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcBase.c @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcBase.c * @@ -33,17 +33,14 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ -#include "FreeRTOS.h" -#include "task.h" -#include "trcBase.h" -#include "trcKernel.h" #include "trcUser.h" +#include "task.h" #if (configUSE_TRACE_FACILITY == 1) @@ -56,12 +53,13 @@ * RecorderData * * The main data structure. This is the data read by FreeRTOS+Trace, typically - * through a debugger RAM dump. This is accessed through RecorderDataPtr. + * through a debugger RAM dump. The recorder access this through the pointer + * RecorderDataPtr, to allow for dynamic memory allocation as well. * - * On the NXP LPC176x you may use the upper RAM bank (AHB) for this purpose. - * For instance, the LPC1766 has 32 KB AHB RAM which allows for allocating a - * buffer size of 7900 events without affecting the main RAM. - * To place RecorderData in this RAM bank, use the below declaration. + * On the NXP LPC17xx you may use the secondary RAM bank (AHB RAM) for this + * purpose. For instance, the LPC1766 has 32 KB AHB RAM which allows for + * allocating a buffer size of at least 7500 events without affecting the main + * RAM. To place RecorderData in this RAM bank, use the below declaration. * * #pragma location="AHB_RAM_MEMORY" * RecorderDataType RecorderData = ... @@ -69,8 +67,13 @@ * This of course works for other hardware architectures with additional RAM * banks as well, just replace "AHB_RAM_MEMORY" with the name of the right * address section from the linker file. + * + * However, to keep trcBase.c portable and still have a preconfigured IAR demo + * using AHB RAM, we don't add the pragma directly in trcBase.c but in a header + * included where the pragma should go. This is used depending on the setting + * USE_LINKER_PRAGMA, defined in trcConfig.h. * - * If using GCC, this is done by adding a "section" attribute: + * If using GCC, this is instead done by adding a "section" attribute: * * RecorderDataType RecorderData __attribute__ ((section ("name"))) = ... * @@ -78,6 +81,9 @@ ******************************************************************************/ #if (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_STATIC) +#if (USE_LINKER_PRAGMA == 1) +#include "recorderdata_linker_pragma.h" +#endif RecorderDataType RecorderData = { /* start marker, 12 chars */ @@ -236,13 +242,18 @@ RecorderDataType RecorderData = }; RecorderDataType* RecorderDataPtr = &RecorderData; -#endif +/* This version of the function does nothing as the trace data is statically allocated */ +RecorderDataType* xTraceInitTraceData(void) +{ + return 0; +} -#if (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_DYNAMIC) +#elif (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_DYNAMIC) RecorderDataType* RecorderDataPtr = NULL; +/* This version of the function dynamically allocates the trace data */ RecorderDataType* xTraceInitTraceData(void) { RecorderDataType* tmp = (RecorderDataType*)pvPortMalloc(sizeof(RecorderDataType)); @@ -326,6 +337,7 @@ RecorderDataType* xTraceInitTraceData(void) #endif +volatile int recorder_busy = 0; char sprintfBuffer[150]; @@ -373,18 +385,13 @@ objectHandleStackType objectHandleStacks = }; -/* Used for internal state flags of tasks */ -uint8_t taskFlags[NTask]; +/* Used for internal state flags of objects */ +uint8_t excludedFlags[(NEventCodes+NQueue+NSemaphore+NMutex+NTask) / 8 + 1]; +uint8_t ifeFlags[NTask / 8 + 1]; /* Gives the last error message of the recorder. NULL if no error message. */ char* traceErrorMessage = NULL; -#if (INCLUDE_EVENT_STATS == 1) -/* Used for an internal reporting mechanism, which displays the count and ratio -of each object type in a console printout generated in vTracePortEnd */ -uint16_t eventCount[256]; -#endif - void* xTraceNextFreeEventBufferSlot(void) { if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE) @@ -396,12 +403,12 @@ void* xTraceNextFreeEventBufferSlot(void) eventData[RecorderDataPtr->nextFreeIndex*4]); } -uint32_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass) +uint16_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass) { if ((objectclass < NCLASSES) && (objecthandle > 0) && (objecthandle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass])) { - return (uint32_t)(RecorderDataPtr-> + return (uint16_t)(RecorderDataPtr-> ObjectPropertyTable.StartIndexOfClass[objectclass] + (RecorderDataPtr-> ObjectPropertyTable.TotalPropertyBytesPerClass[objectclass] * @@ -438,7 +445,7 @@ uint32_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass) objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass) { static objectHandleType handle; - static uint32_t indexOfHandle; + static int indexOfHandle; indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass]; if (objectHandleStacks.objectHandles[indexOfHandle] == 0) @@ -459,28 +466,31 @@ objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass) /* ERROR */ switch(objectclass) { - case TRACE_CLASS_TASK: + case TRACE_CLASS_TASK: vTraceError("Not enough TASK handles - increase NTask in trcConfig.h"); break; - case TRACE_CLASS_ISR: + case TRACE_CLASS_ISR: vTraceError("Not enough ISR handles - increase NISR in trcConfig.h"); break; - case TRACE_CLASS_SEMAPHORE: + case TRACE_CLASS_SEMAPHORE: vTraceError("Not enough SEMAPHORE handles - increase NSemaphore in trcConfig.h"); break; - case TRACE_CLASS_MUTEX: + case TRACE_CLASS_MUTEX: vTraceError("Not enough MUTEX handles - increase NMutex in trcConfig.h"); break; - case TRACE_CLASS_QUEUE: + case TRACE_CLASS_QUEUE: vTraceError("Not enough QUEUE handles - increase NQueue in trcConfig.h"); break; + default: + vTraceError("Invalid object class."); + break; } handle = 0; /* an invalid/anonymous handle - but the recorder is stopped now... */ } else { - int32_t hndCount; + int hndCount; objectHandleStacks.indexOfNextAvailableHandle[objectclass]++; hndCount = objectHandleStacks.indexOfNextAvailableHandle[objectclass] - @@ -499,7 +509,7 @@ objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass) void vTraceFreeObjectHandle(traceObjectClass objectclass, objectHandleType handle) { - uint32_t indexOfHandle; + int indexOfHandle; /* Check that there is room to push the handle on the stack */ if ( (objectHandleStacks.indexOfNextAvailableHandle[objectclass] - 1) < @@ -542,7 +552,7 @@ void vTraceSetObjectName(traceObjectClass objectclass, objectHandleType handle, const char* name) { - static uint32_t idx; + static uint16_t idx; if (handle == 0) { @@ -594,6 +604,9 @@ void vTraceSetObjectName(traceObjectClass objectclass, (void)strncpy((char*)&(RecorderDataPtr->ObjectPropertyTable.objbytes[idx]), name, RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ objectclass ] ); +#ifdef WIN32 + printf("vTraceSetObjectName(%d, %d, %s)\n", objectclass, handle, name); +#endif } } } @@ -607,13 +620,13 @@ traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel) crc = 0; prvTraceGetChecksum(name, &crc, &len); - taskENTER_CRITICAL(); + trcCRITICAL_SECTION_BEGIN(); result = prvTraceLookupSymbolTableEntry(name, crc, len, userEventChannel); if (!result) { result = prvTraceCreateSymbolTableEntry(name, crc, len, userEventChannel); } - taskEXIT_CRITICAL(); + trcCRITICAL_SECTION_END(); return result; } @@ -634,12 +647,12 @@ traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel) * trace start will be aborted. This can occur if any of the Nxxxx constants * (e.g., NTask) in trcConfig.h is too small. ******************************************************************************/ -void vTraceError(char* msg) +void vTraceError(const char* msg) { vTraceStop(); if (traceErrorMessage == NULL) { - traceErrorMessage = msg; + traceErrorMessage = (char*)msg; (void)strncpy(RecorderDataPtr->systemInfo, traceErrorMessage, TRACE_DESCRIPTION_MAX_LENGTH); @@ -663,17 +676,19 @@ void vTraceError(char* msg) *****************************************************************************/ void prvCheckDataToBeOverwrittenForMultiEntryUserEvents( - uint32_t nofEntriesToCheck) + uint8_t nofEntriesToCheck) { - uint32_t i = 0, e = 0; + /* Generic "int" type is desired - should be 16 bit variable on 16 bit HW */ + unsigned int i = 0; + unsigned int e = 0; while (i < nofEntriesToCheck) { e = RecorderDataPtr->nextFreeIndex + i; if ((RecorderDataPtr->eventData[e*4] > USER_EVENT) && (RecorderDataPtr->eventData[e*4] < USER_EVENT + 16)) { - uint32_t nDataEvents = (uint32_t)(RecorderDataPtr->eventData[e*4] - USER_EVENT); - if (e + nDataEvents < RecorderDataPtr->maxEvents) + uint8_t nDataEvents = (uint8_t)(RecorderDataPtr->eventData[e*4] - USER_EVENT); + if ((e + nDataEvents) < RecorderDataPtr->maxEvents) { (void)memset(& RecorderDataPtr->eventData[e*4], 0, 4 + 4 * nDataEvents); } @@ -693,11 +708,7 @@ void prvTraceUpdateCounters(void) { return; } - -#if (INCLUDE_EVENT_STATS == 1) - eventCount[RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex*4]]++; -#endif - + RecorderDataPtr->numEvents++; RecorderDataPtr->nextFreeIndex++; @@ -736,11 +747,12 @@ void prvTraceUpdateCounters(void) * The parameter param_maxDTS should be 0xFF for 8-bit dts or 0xFFFF for * events with 16-bit dts fields. *****************************************************************************/ -uint32_t prvTraceGetDTS(uint32_t param_maxDTS) +uint16_t prvTraceGetDTS(uint16_t param_maxDTS) { - XTSEvent* xts; - int32_t dts = 0; - uint32_t old_ts = RecorderDataPtr->absTimeLastEvent; + static uint32_t old_timestamp = 0; + XTSEvent* xts = 0; + uint32_t dts = 0; + uint32_t timestamp = 0; if (RecorderDataPtr->frequency == 0) { @@ -760,62 +772,66 @@ uint32_t prvTraceGetDTS(uint32_t param_maxDTS) if (xTaskGetSchedulerState() != 0) /* Has the scheduler started? */ { RecorderDataPtr->frequency = - HWTC_PERIOD * configTICK_RATE_HZ / HWTC_DIVISOR; + (uint32_t)HWTC_PERIOD * (uint32_t)configTICK_RATE_HZ / (uint32_t)HWTC_DIVISOR; } #endif } /************************************************************************** - * The below statement reads the timestamp from the timer port module. Note - * the modulo operation on RecorderDataPtr->frequency, which makes the overflow - * case (if (dts < 0)) occur every 1 sec. - * This is to make it easier to test. The overflow will happen sooner - * or later anyway. + * The below statements read the timestamp from the timer port module. + * If necessary, whole seconds are extracted using division while the rest + * comes from the modulo operation. **************************************************************************/ - - if (RecorderDataPtr->frequency > 0) - { - RecorderDataPtr->absTimeLastEvent = - uiTracePortGetTimeStamp() % RecorderDataPtr->frequency; - } - else + + uiTracePortGetTimeStamp(×tamp); + + /*************************************************************************** + * This condition is only for the Win32 port, since it does not use the tick + * count but instead only HWTC_COUNT (from the performance counter). + * Without this condition, you sometimes get a negative dts value (converted + * into a very large unsiged value) when the performance counter wraps + * around. In other "normal" ports also using the FreeRTOS tick counter, this + * condition can not occur and therefore has no impact. + ***************************************************************************/ + if (timestamp < old_timestamp) { - /* Special case if the recorder has not yet started (frequency may be uninitialized, i.e., zero) - The modulo operation is not necessary on the first events, since it is surely much less than - one second since startup. */ - RecorderDataPtr->absTimeLastEvent = uiTracePortGetTimeStamp(); + timestamp += RecorderDataPtr->frequency; } - dts = (int32_t)(RecorderDataPtr->absTimeLastEvent - old_ts); - if (dts < 0) /* when the modulo operation wraps around (after 1 second) */ + dts = timestamp - old_timestamp; + old_timestamp = timestamp; + + if (RecorderDataPtr->frequency > 0) { - if (RecorderDataPtr->frequency == 0) + /* Check if dts > 1 second */ + if (dts > RecorderDataPtr->frequency) { - /* Frequency should normally be initialized on the first logged event after - the FreeRTOS scheduler has started. In this case, it has not yet been - initialized (frequency is 0) and the dts (time since last event) was - negative. This is an illegal combination that indicates a problem in - uiTracePortGetTimeStamp, probably due to incorrect HWTC macros in trcPort.h. - - The dts variable normally becomes negative when the modulo operation wraps - around, but since the modulo operation is not used in this case (only used - if frequency has been set), dts only becomes negative if - uiTracePortGetTimeStamp returned a smaller value than last time. - This is an error. The values returned by uiTracePortGetTimeStamp should be - monotonically incresing (since it is a timestamp). */ - - vTraceError("Timestamping error, see comment in prvTraceGetDTS (trcBase.c)"); - return 0; + /* More than 1 second has passed */ + RecorderDataPtr->absTimeLastEventSecond += dts / RecorderDataPtr->frequency; + /* The part that is not an entire second is added to absTimeLastEvent */ + RecorderDataPtr->absTimeLastEvent += dts % RecorderDataPtr->frequency; + } + else + RecorderDataPtr->absTimeLastEvent += dts; + + /* Check if absTimeLastEvent >= 1 second */ + if (RecorderDataPtr->absTimeLastEvent >= RecorderDataPtr->frequency) + { + /* RecorderDataPtr->absTimeLastEvent is more than or equal to 1 second, but always less than 2 seconds */ + RecorderDataPtr->absTimeLastEventSecond++; + RecorderDataPtr->absTimeLastEvent -= RecorderDataPtr->frequency; + /* RecorderDataPtr->absTimeLastEvent is now less than 1 second */ } - dts = (int32_t)(RecorderDataPtr->frequency - old_ts + RecorderDataPtr->absTimeLastEvent); - - /* This is good for 136 years (incremented every 1 second) */ - RecorderDataPtr->absTimeLastEventSecond++; + } + else + { + /* Special case if the recorder has not yet started (frequency may be uninitialized, i.e., zero) */ + RecorderDataPtr->absTimeLastEvent = timestamp; } /* If the dts (time since last event) does not fit in event->dts (only 8 or 16 bits) */ - if (dts > (int32_t)param_maxDTS) + if (dts > param_maxDTS) { /* Create an XTS event (eXtended TimeStamp) containing the higher dts bits*/ xts = (XTSEvent*) xTraceNextFreeEventBufferSlot(); @@ -842,10 +858,9 @@ uint32_t prvTraceGetDTS(uint32_t param_maxDTS) } } - return dts % (param_maxDTS + 1); + return (uint16_t)(dts % (param_maxDTS + 1)); } - /******************************************************************************* * prvTraceLookupSymbolTableEntry * @@ -959,14 +974,14 @@ uint16_t prvTraceCreateSymbolTableEntry(const char* name, ******************************************************************************/ void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength) { - char c; - int32_t length = 0; - int32_t crc = 0; + unsigned char c; + int length = 0; + int crc = 0; if ( pname != (const char *) 0 ) { for ( ; (c = *pname++) != '\0'; ) { - crc += (int32_t)c; + crc += c; length++; } } @@ -974,4 +989,4 @@ void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength) *plength = (uint8_t)length; } -#endif \ No newline at end of file +#endif diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcKernel.c b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcKernel.c index 012268a69..98b84a8ea 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcKernel.c +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcKernel.c @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcKernel.c * @@ -34,18 +34,19 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ -#include "FreeRTOS.h" +#include "trcUser.h" #include "task.h" -#include "trcKernel.h" #if (configUSE_TRACE_FACILITY == 1) + + /****************************************************************************** * TraceObjectClassTable * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_). @@ -73,13 +74,72 @@ uint8_t nISRactive = 0; objectHandleType handle_of_last_logged_task = 0; uint8_t inExcludedTask = 0; +static uint8_t prvTraceIsObjectExcluded(traceObjectClass, uint32_t); + +/******************************************************************************* + * prvTraceIsObjectExcluded + * + * Private function that accepts an object class and an object number and uses + * that to determine if the object has been flagged as excluded. + ******************************************************************************/ +static uint8_t prvTraceIsObjectExcluded(traceObjectClass objectClass, uint32_t objectNumber) +{ + switch(objectClass) + { + case TRACE_CLASS_QUEUE: + return GET_QUEUE_FLAG_ISEXCLUDED(objectNumber); + break; + case TRACE_CLASS_SEMAPHORE: + return GET_SEMAPHORE_FLAG_ISEXCLUDED(objectNumber); + break; + case TRACE_CLASS_MUTEX: + return GET_MUTEX_FLAG_ISEXCLUDED(objectNumber); + break; + case TRACE_CLASS_TASK: + return GET_TASK_FLAG_ISEXCLUDED(objectNumber); + break; + } + return 0; +} + +#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1 +/******************************************************************************* + * vTraceStoreTaskReady + * + * This function stores a ready state for the task handle sent in as parameter. + ******************************************************************************/ +void vTraceStoreTaskReady(objectHandleType handle) +{ + uint16_t dts3; + TREvent* tr; + + if (!GET_TASK_FLAG_ISEXCLUDED(handle)) + { + dts3 = (uint16_t)prvTraceGetDTS(0xFFFF); + if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ + { + tr = (TREvent*)xTraceNextFreeEventBufferSlot(); + + if (tr != NULL) + { + tr->type = TR_TASK_READY; + tr->dts = dts3; + tr->objHandle = handle; + + prvTraceUpdateCounters(); + } + } + } +} +#endif + /******************************************************************************* * vTraceStoreKernelCall * * This is the main integration point for storing FreeRTOS kernel calls, and * is called by the hooks in FreeRTOS.h (see trcKernel.h for event codes). ******************************************************************************/ -void vTraceStoreKernelCall(uint32_t ecode, uint32_t objectNumber) +void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber) { KernelCall * kse; uint16_t dts1; @@ -88,38 +148,53 @@ void vTraceStoreKernelCall(uint32_t ecode, uint32_t objectNumber) { return; } - - /* This checks if this is the first kernel call after a call to - vTraceTaskInstanceIsFinished. In that case, calls to this kernel service - with this specific kernel object become the "instance finish event" - (IFE) of the calling task.*/ - if (GET_TASK_FLAG_MARKIFE(handle_of_last_logged_task)) - { - /* Reset the flag - this has been handled now */ - CLEAR_TASK_FLAG_MARKIFE(handle_of_last_logged_task); - - /* Store the kernel service tagged as instance finished event */ - PROPERTY_TASK_IFE_SERVICECODE(handle_of_last_logged_task) = - (uint8_t)ecode; - - /* Store the handle of the specific kernel object */ - PROPERTY_TASK_IFE_OBJHANDLE(handle_of_last_logged_task) = - (objectHandleType)objectNumber; - } - if (RecorderDataPtr->recorderActive && (!inExcludedTask || nISRactive)) + if (RecorderDataPtr->recorderActive) { - dts1 = (uint16_t)prvTraceGetDTS(0xFFFF); + + /* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */ + if (nISRactive || !inExcludedTask) + { + /* Make sure ISRs never change the IFE flags of tasks */ + if (!nISRactive) + { + /* This checks if this is the first kernel call after a call to + vTraceTaskInstanceIsFinished. In that case, calls to this kernel service + with this specific kernel object become the "instance finish event" + (IFE) of the calling task.*/ + if (GET_TASK_FLAG_MARKIFE(handle_of_last_logged_task)) + { + /* Reset the flag - this has been handled now */ + CLEAR_TASK_FLAG_MARKIFE(handle_of_last_logged_task); - if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ - { - kse = (KernelCall*) xTraceNextFreeEventBufferSlot(); - if (kse != NULL) + /* Store the kernel service tagged as instance finished event */ + PROPERTY_TASK_IFE_SERVICECODE(handle_of_last_logged_task) = + (uint8_t)ecode; + + /* Store the handle of the specific kernel object */ + PROPERTY_TASK_IFE_OBJHANDLE(handle_of_last_logged_task) = + (objectHandleType)objectNumber; + } + } + + /* Check if the referenced object or the event code is excluded */ + if (!prvTraceIsObjectExcluded(objectClass, objectNumber) && !GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode)) { - kse->dts = dts1; - kse->type = (uint8_t)ecode; - kse->objHandle = (uint8_t)objectNumber; - prvTraceUpdateCounters(); + trcCRITICAL_SECTION_BEGIN(); + dts1 = (uint16_t)prvTraceGetDTS(0xFFFF); + + if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ + { + kse = (KernelCall*) xTraceNextFreeEventBufferSlot(); + if (kse != NULL) + { + kse->dts = dts1; + kse->type = (uint8_t)ecode; + kse->objHandle = (uint8_t)objectNumber; + prvTraceUpdateCounters(); + } + } + trcCRITICAL_SECTION_END(); } } } @@ -131,8 +206,9 @@ void vTraceStoreKernelCall(uint32_t ecode, uint32_t objectNumber) * Used for storing kernel calls with a handle and a numeric parameter. This is * only used for traceTASK_PRIORITY_SET at the moment. ******************************************************************************/ -void vTraceStoreKernelCallWithParam(uint32_t evtcode, - uint32_t objectNumber, +void vTraceStoreKernelCallWithParam(uint32_t evtcode, + traceObjectClass objectClass, + uint32_t objectNumber, uint8_t param) { KernelCallWithParamAndHandle * kse; @@ -141,19 +217,25 @@ void vTraceStoreKernelCallWithParam(uint32_t evtcode, if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && (! inExcludedTask || nISRactive)) { - dts2 = (uint8_t)prvTraceGetDTS(0xFF); + /* Check if the referenced object or the event code is excluded */ + if (!prvTraceIsObjectExcluded(objectClass, objectNumber) && !GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode)) + { + trcCRITICAL_SECTION_BEGIN(); + dts2 = (uint8_t)prvTraceGetDTS(0xFF); - if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ - { - kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot(); - if (kse != NULL) - { - kse->dts = dts2; - kse->type = (uint8_t)evtcode; - kse->objHandle = (uint8_t)objectNumber; - kse->param = param; - prvTraceUpdateCounters(); + if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ + { + kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot(); + if (kse != NULL) + { + kse->dts = dts2; + kse->type = (uint8_t)evtcode; + kse->objHandle = (uint8_t)objectNumber; + kse->param = param; + prvTraceUpdateCounters(); + } } + trcCRITICAL_SECTION_END(); } } } @@ -172,70 +254,104 @@ void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint16_t param) if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && (! inExcludedTask || nISRactive)) - { - dts6 = (uint8_t)prvTraceGetDTS(0xFF); + { + /* Check if the event code is excluded */ + if (!GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode)) + { + trcCRITICAL_SECTION_BEGIN(); + dts6 = (uint8_t)prvTraceGetDTS(0xFF); - if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ - { - kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot(); - if (kse != NULL) - { - kse->dts = dts6; - kse->type = (uint8_t)evtcode; - kse->param = param; - prvTraceUpdateCounters(); + if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ + { + kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot(); + if (kse != NULL) + { + kse->dts = dts6; + kse->type = (uint8_t)evtcode; + kse->param = param; + prvTraceUpdateCounters(); + } } + trcCRITICAL_SECTION_END(); } } } +objectHandleType handle_of_running_task = 0; + /******************************************************************************* * vTraceStoreTaskswitch - * Called by the scheduler, from the SWITCHED_OUT hook. - * At this point interrupts are disabled, so no need to disable interrupts. + * Called by the scheduler from the SWITCHED_OUT hook, and by uiTraceStart. + * At this point interrupts are assumed to be disabled! ******************************************************************************/ void vTraceStoreTaskswitch(void) { uint16_t dts3; - TSEvent* ts; - static objectHandleType handle_of_running_task = 0; + TSEvent* ts; int8_t skipEvent = 0; + uint32_t schedulerState = 0; + + /*************************************************************************** + This is used to detect if a high-priority ISRs is illegally using the + recorder ISR trace functions (vTraceStoreISRBegin and ...End) while the + recorder is busy with a task-level event or lower priority ISR event. + + If this is detected, it triggers a call to vTraceError with the error + "Illegal call to vTraceStoreISRBegin/End". If you get this error, it means + that the macro taskENTER_CRITICAL does not disable this ISR, as required. + You can solve this by adjusting the value of the FreeRTOS constant + configMAX_SYSCALL_INTERRUPT_PRIORITY, which is defined in FreeRTOSConfig.h + + Note: Setting recorder_busy is normally handled in our macros + trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this + function since critical sections should not be used in the context switch + event...) + ***************************************************************************/ + recorder_busy++; - if (xTaskGetSchedulerState() == 0) + schedulerState = xTaskGetSchedulerState(); + + if (schedulerState == 0) { /* This occurs on the very first taskswitch event, generated by vTraceStart and uiTraceStart if the scheduler is not yet started. This creates a dummy "(startup)" task entry internally in the recorder */ + if (handle_of_running_task == 0) + { + handle_of_running_task = xTraceGetObjectHandle(TRACE_CLASS_TASK); - handle_of_running_task = xTraceGetObjectHandle(TRACE_CLASS_TASK); - vTraceSetObjectName(TRACE_CLASS_TASK, - handle_of_running_task, - "(startup)"); - vTraceSetPriorityProperty(TRACE_CLASS_TASK, - handle_of_running_task, - 0); + vTraceSetObjectName(TRACE_CLASS_TASK, + handle_of_running_task, + "(startup)"); + + vTraceSetPriorityProperty(TRACE_CLASS_TASK, + handle_of_running_task, + 0); + } } else { handle_of_running_task = (objectHandleType)uxTaskGetTaskNumber(xTaskGetCurrentTaskHandle()); } - + /* Skip the event if the task has been excluded, using vTraceExcludeTask */ if (GET_TASK_FLAG_ISEXCLUDED(handle_of_running_task)) { skipEvent = 1; inExcludedTask = 1; - } + } + else + inExcludedTask = 0; + /* Skip the event if the same task is scheduled */ if (handle_of_running_task == handle_of_last_logged_task) { skipEvent = 1; } - - + if (! RecorderDataPtr->recorderActive) { skipEvent = 1; @@ -243,15 +359,12 @@ void vTraceStoreTaskswitch(void) /* If this event should be logged, log it! */ if (skipEvent == 0) - { + { dts3 = (uint16_t)prvTraceGetDTS(0xFFFF); if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ - { - inExcludedTask = 0; - - handle_of_last_logged_task = handle_of_running_task; - + { + handle_of_last_logged_task = handle_of_running_task; ts = (TSEvent*)xTraceNextFreeEventBufferSlot(); if (ts != NULL) @@ -276,8 +389,10 @@ void vTraceStoreTaskswitch(void) prvTraceUpdateCounters(); } } - } - + } + + /* See comment on recorder_busy++ above. */ + recorder_busy--; } /******************************************************************************* @@ -299,8 +414,9 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle, name = PROPERTY_NAME_GET(objectclass, handle); idx = prvTraceOpenSymbol(name, 0); - - ce = (ObjCloseNameEvent*) xTraceNextFreeEventBufferSlot(); + + // Interrupt disable not necessary, already done in trcHooks.h macro + ce = (ObjCloseNameEvent*) xTraceNextFreeEventBufferSlot(); if (ce != NULL) { ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass; @@ -308,6 +424,7 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle, ce->symbolIndex = idx; prvTraceUpdateCounters(); } + } void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle, @@ -321,6 +438,7 @@ void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle, return; } + // Interrupt disable not necessary, already done in trcHooks.h macro pe = (ObjClosePropEvent*) xTraceNextFreeEventBufferSlot(); if (pe != NULL) { @@ -370,5 +488,4 @@ uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id) return PROPERTY_OBJECT_STATE(objectclass, id); } - -#endif \ No newline at end of file +#endif diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcPort.c b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcPort.c index 9367ff791..e98dd57a8 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcPort.c +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcPort.c @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcPort.c * @@ -37,17 +37,16 @@ * , hobbyists or early-phase startups) we have an attractive offer: * Provide a hardware timer port and get a FREE single-user licence for * FreeRTOS+Trace Professional Edition. Read more about this offer at - * www.percepio.se or contact us directly at support@percepio.se. + * www.percepio.com or contact us directly at support@percepio.com. * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ -#include "FreeRTOS.h" -#include "trcPort.h" + #include "trcUser.h" #if (configUSE_TRACE_FACILITY == 1) @@ -56,6 +55,7 @@ static char* prvFileName = NULL; #endif + /******************************************************************************* * uiTraceTickCount * @@ -79,37 +79,60 @@ uint32_t uiTraceTickCount = 0; * OFFER FROM PERCEPIO: * For silicon companies and non-corporate FreeRTOS users (researchers, students * , hobbyists or early-phase startups) we have an attractive offer: - * Provide a hardware timer port and get a FREE single-user licence for + * Provide a hardware timer port and get a FREE single-user license for * FreeRTOS+Trace Professional Edition. Read more about this offer at - * www.percepio.se or contact us directly at support@percepio.se. + * www.percepio.com or contact us directly at support@percepio.com. ******************************************************************************/ -uint32_t uiTracePortGetTimeStamp() +void uiTracePortGetTimeStamp(uint32_t *pTimestamp) { - /* Keep these static to avoid using more stack than necessary */ - static uint32_t last_timestamp = 0; - static uint32_t timestamp; - + static uint32_t last_traceTickCount = 0; + static uint32_t last_hwtc_count = 0; + uint32_t traceTickCount = 0; + uint32_t hwtc_count = 0; + + /* Retrieve HWTC_COUNT only once since the same value should be used all throughout this function. */ #if (HWTC_COUNT_DIRECTION == DIRECTION_INCREMENTING) - timestamp = ((uiTraceTickCount * HWTC_PERIOD) + HWTC_COUNT) / HWTC_DIVISOR; -#else -#if (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING) - timestamp = ((uiTraceTickCount * HWTC_PERIOD) + (HWTC_PERIOD - HWTC_COUNT)) / HWTC_DIVISOR; + hwtc_count = HWTC_COUNT; +#elif (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING) + hwtc_count = HWTC_PERIOD - HWTC_COUNT; #else Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly! Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING #endif -#endif + + if (last_traceTickCount - uiTraceTickCount - 1 < 0x80000000) + { + /* This means last_traceTickCount is higher than uiTraceTickCount, + so we have previously compensated for a missed tick. + Therefore we use the last stored value because that is more accurate. */ + traceTickCount = last_traceTickCount; + } + else + { + /* Business as usual */ + traceTickCount = uiTraceTickCount; + } - /* May occur due to overflow, if the update of uiTraceTickCount has been + /* Check for overflow. May occur if the update of uiTraceTickCount has been delayed due to disabled interrupts. */ - if (timestamp < last_timestamp) + if (traceTickCount == last_traceTickCount && hwtc_count < last_hwtc_count) { - timestamp += (HWTC_PERIOD / HWTC_DIVISOR); + /* A trace tick has occurred but not been executed by the kernel, so we compensate manually. */ + traceTickCount++; } - - last_timestamp = timestamp; - - return timestamp; + + /* Check if the return address is OK, then we perform the calculation. */ + if (pTimestamp) + { + /* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */ + *pTimestamp = traceTickCount * (HWTC_PERIOD / HWTC_DIVISOR); + /* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / HWTC_DIVISOR. */ + *pTimestamp += (hwtc_count + traceTickCount * (HWTC_PERIOD % HWTC_DIVISOR)) / HWTC_DIVISOR; + } + + /* Store the previous values. */ + last_traceTickCount = traceTickCount; + last_hwtc_count = hwtc_count; } /******************************************************************************* diff --git a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcUser.c b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcUser.c index c5127502c..2e4bc1aac 100644 --- a/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcUser.c +++ b/FreeRTOS-Plus/FreeRTOS-Plus-Trace/trcUser.c @@ -1,6 +1,6 @@ /******************************************************************************* - * FreeRTOS+Trace v2.2.3 Recorder Library - * Percepio AB, www.percepio.se + * FreeRTOS+Trace v2.3.0 Recorder Library + * Percepio AB, www.percepio.com * * trcUser.c * @@ -33,23 +33,21 @@ * * FreeRTOS+Trace is available as Free Edition and in two premium editions. * You may use the premium features during 30 days for evaluation. - * Download FreeRTOS+Trace at http://www.percepio.se/index.php?page=downloads + * Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ * * Copyright Percepio AB, 2012. - * www.percepio.se + * www.percepio.com ******************************************************************************/ -#include "FreeRTOS.h" +#include +#include + +#include "trcUser.h" #include "task.h" -#include "queue.h" +#include "semphr.h" #if (configUSE_TRACE_FACILITY == 1) -#include "string.h" -#include "stdarg.h" -#include "trcUser.h" -#include "trcKernel.h" - extern uint8_t inExcludedTask; extern uint8_t nISRactive; extern uint8_t handle_of_last_logged_task; @@ -60,8 +58,8 @@ extern uint32_t hwtc_count_sum_after_tick_counter; extern unsigned char ucQueueGetQueueType(void*); extern unsigned char ucQueueGetQueueNumber(void*); extern char* traceErrorMessage; - static void vTraceMonitorTask(void); +static void prvTraceExcludeOrIncludeKernelServiceFromTrace(traceKernelService, uint8_t); /******************************************************************************* * vTraceMonitorTask @@ -119,8 +117,8 @@ static void vTraceMonitorTask(void) { sprintf(localsprintbuffer, "\n\r[FreeRTOS+Trace] Event count: %d, Duration: %d ms. [%d ticks]\n\r", - RecorderDataPtr->numEvents, - RecorderDataPtr->absTimeLastEventSecond*1000 + (RecorderDataPtr->absTimeLastEvent*1000)/ RecorderDataPtr->frequency, xTaskGetTickCount()); + (int)RecorderDataPtr->numEvents, + (int)(RecorderDataPtr->absTimeLastEventSecond*1000 + (RecorderDataPtr->absTimeLastEvent*1000)/ RecorderDataPtr->frequency), (int)xTaskGetTickCount()); vTraceConsoleMessage(localsprintbuffer); } @@ -148,20 +146,21 @@ static void vTraceMonitorTask(void) ******************************************************************************/ void vTraceClear(void) { - taskENTER_CRITICAL(); - + trcCRITICAL_SECTION_BEGIN(); + RecorderDataPtr->absTimeLastEvent = 0; RecorderDataPtr->nextFreeIndex = 0; RecorderDataPtr->numEvents = 0; RecorderDataPtr->bufferIsFull = 0; - taskEXIT_CRITICAL(); + trcCRITICAL_SECTION_END(); + } /******************************************************************************* * vTraceStartStatusMonitor * - * This starts a task to monitor the state of the recorder. + * This starts a task to monitor the state of½ the recorder. * This task periodically prints a line to the console window, which shows the * number of events recorded and the latest timestamp. This task * calls vTracePortEnd when the recorder has been stopped, where custom @@ -187,12 +186,15 @@ void vTraceStartStatusMonitor(void) * Any error message is also presented when opening a trace file in * FreeRTOS+Trace v2.2.2 or later. ******************************************************************************/ + uint32_t uiTraceStart(void) { if (traceErrorMessage == NULL) { + trcCRITICAL_SECTION_BEGIN(); RecorderDataPtr->recorderActive = 1; vTraceStoreTaskswitch(); /* Register the currently running task */ + trcCRITICAL_SECTION_END(); } return RecorderDataPtr->recorderActive; @@ -263,31 +265,335 @@ uint32_t uiTraceGetTraceBufferSize(void) } /******************************************************************************* - * vTraceExcludeTask - * Excludes a task from the recording using a flag in the Object Property Table. - * This can be useful if some irrelevant task is very frequent and is "eating - * up the buffer". This should be called after the task has been created, but - * preferably before starting the FreeRTOS scheduler. + * prvTraceExcludeOrIncludeKernelServiceFromTrace + * + * Includes or excludes all events that is related to the kernel service. ******************************************************************************/ -void vTraceExcludeTaskFromSchedulingTrace(const char* name) +static void prvTraceExcludeOrIncludeKernelServiceFromTrace(traceKernelService kernelService, uint8_t flag) { - objectHandleType i; - int32_t found = 0; - for (i = 1; i < RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_TASK]; i++) + switch(kernelService) { - if (strncmp(name, - PROPERTY_NAME_GET(TRACE_CLASS_TASK, i), - RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[TRACE_CLASS_TASK]) == 0) + case TRACE_KERNEL_SERVICE_TASK_CREATE: + if (flag) { - found = 1; - SET_TASK_FLAG_ISEXCLUDED(i); - break; + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_TASK); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK); } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_TASK); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK); + } + break; + case TRACE_KERNEL_SERVICE_TASK_DELETE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_TASK); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_TASK); + } + break; + case TRACE_KERNEL_SERVICE_TASK_DELAY: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY); + SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY_UNTIL); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY_UNTIL); + } + break; + case TRACE_KERNEL_SERVICE_PRIORITY_SET: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_PRIORITY_SET); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_PRIORITY_SET); + } + break; + case TRACE_KERNEL_SERVICE_TASK_SUSPEND: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_SUSPEND); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_SUSPEND); + } + break; + case TRACE_KERNEL_SERVICE_TASK_RESUME: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_RESUME); + SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_RESUME_FROM_ISR); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_RESUME); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_RESUME_FROM_ISR); + } + break; + case TRACE_KERNEL_SERVICE_QUEUE_CREATE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_QUEUE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_QUEUE); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_QUEUE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_QUEUE); + } + break; + case TRACE_KERNEL_SERVICE_QUEUE_DELETE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_QUEUE); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_QUEUE); + } + break; + case TRACE_KERNEL_SERVICE_QUEUE_SEND: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_QUEUE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_QUEUE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_QUEUE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_QUEUE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_QUEUE); + + + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_QUEUE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_QUEUE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_QUEUE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_QUEUE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_QUEUE); + } + break; + case TRACE_KERNEL_SERVICE_QUEUE_RECEIVE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_QUEUE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_QUEUE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_QUEUE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_QUEUE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_QUEUE); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_QUEUE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_QUEUE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_QUEUE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_QUEUE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_QUEUE); + } + break; + case TRACE_KERNEL_SERVICE_QUEUE_PEEK: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_QUEUE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_SEMAPHORE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_MUTEX); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_QUEUE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_SEMAPHORE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_PEEK + TRACE_CLASS_MUTEX); + } + break; + case TRACE_KERNEL_SERVICE_MUTEX_CREATE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_MUTEX); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_MUTEX); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_MUTEX); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_MUTEX); + } + break; + case TRACE_KERNEL_SERVICE_MUTEX_DELETE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_MUTEX); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_MUTEX); + } + break; + case TRACE_KERNEL_SERVICE_MUTEX_GIVE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_MUTEX); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_MUTEX); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_MUTEX); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_MUTEX); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_MUTEX); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_MUTEX); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_MUTEX); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_MUTEX); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_MUTEX); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_MUTEX); + } + break; + case TRACE_KERNEL_SERVICE_MUTEX_TAKE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_MUTEX); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_MUTEX); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_MUTEX); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_MUTEX); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_MUTEX); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_MUTEX); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_MUTEX); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_MUTEX); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_MUTEX); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_MUTEX); + } + break; + case TRACE_KERNEL_SERVICE_SEMAPHORE_CREATE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_SEMAPHORE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_SEMAPHORE); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_CREATE + TRACE_CLASS_SEMAPHORE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_SEMAPHORE); + } + break; + case TRACE_KERNEL_SERVICE_SEMAPHORE_DELETE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_SEMAPHORE); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_DELETE + TRACE_CLASS_SEMAPHORE); + } + break; + case TRACE_KERNEL_SERVICE_SEMAPHORE_GIVE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_SEMAPHORE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_SEMAPHORE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_SEMAPHORE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_SEMAPHORE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_SEMAPHORE); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND + TRACE_CLASS_SEMAPHORE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND + TRACE_CLASS_SEMAPHORE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_SEND + TRACE_CLASS_SEMAPHORE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR + TRACE_CLASS_SEMAPHORE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_SEND_FROM_ISR + TRACE_CLASS_SEMAPHORE); + } + break; + case TRACE_KERNEL_SERVICE_SEMAPHORE_TAKE: + if (flag) + { + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_SEMAPHORE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_SEMAPHORE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_SEMAPHORE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_SEMAPHORE); + SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_SEMAPHORE); + } + else + { + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE + TRACE_CLASS_SEMAPHORE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE + TRACE_CLASS_SEMAPHORE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_BLOCK_ON_RECEIVE + TRACE_CLASS_SEMAPHORE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR + TRACE_CLASS_SEMAPHORE); + CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TRACE_CLASS_SEMAPHORE); + } + break; } - if (!found) - { - vTraceError("Could not find task to exclude!"); - } +} + +/****************************************************************************** + * vTraceExclude______FromTrace + * + * Excludes a task or object from the trace. + * This can be useful if some irrelevant task is very frequent and is "eating + * up the buffer". This should be called after the task has been created, but + * before starting the FreeRTOS scheduler. + *****************************************************************************/ +void vTraceExcludeQueueFromTrace(void* handle) +{ + SET_QUEUE_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle)); +} + +void vTraceExcludeSemaphoreFromTrace(void* handle) +{ + SET_SEMAPHORE_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle)); +} + +void vTraceExcludeMutexFromTrace(void* handle) +{ + SET_MUTEX_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle)); +} + +void vTraceExcludeTaskFromTrace(void* handle) +{ + SET_TASK_FLAG_ISEXCLUDED(uxTaskGetTaskNumber(handle)); +} + +void vTraceExcludeKernelServiceFromTrace(traceKernelService kernelService) +{ + prvTraceExcludeOrIncludeKernelServiceFromTrace(kernelService, 1); +} + +/****************************************************************************** + * vTraceInclude______InTrace + * + * Includes a task, object or kernel service in the trace. This is only + * necessary if the task or object has been previously exluded. + *****************************************************************************/ +void vTraceIncludeQueueInTrace(void* handle) +{ + CLEAR_QUEUE_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle)); +} + +void vTraceIncludeSemaphoreInTrace(void* handle) +{ + CLEAR_SEMAPHORE_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle)); +} + +void vTraceIncludeMutexInTrace(void* handle) +{ + CLEAR_MUTEX_FLAG_ISEXCLUDED(ucQueueGetQueueNumber(handle)); +} + +void vTraceIncludeTaskInTrace(void* handle) +{ + CLEAR_TASK_FLAG_ISEXCLUDED(uxTaskGetTaskNumber(handle)); +} + +void vTraceIncludeKernelServiceInTrace(traceKernelService kernelService) +{ + prvTraceExcludeOrIncludeKernelServiceFromTrace(kernelService, 0); } /******************************************************************************* @@ -371,16 +677,20 @@ static uint8_t isrstack[MAX_ISR_NESTING]; * ... * void ISR_handler() * { - * portENTER_CRITICAL(); // Required if nested ISRs are allowed * vTraceStoreISRBegin(ID_OF_ISR_TIMER1); - * portEXIT_CRITICAL(); * ... - * portENTER_CRITICAL(); // Required if nested ISRs are allowed * vTraceStoreISREnd(); - * portEXIT_CRITICAL(); * } + * + * NOTE: To safely record ISRs, you need to make sure that all traced + * interrupts actually are disabled by trcCRITICAL_SECTION_BEGIN(), which + * typically is mapped to portENTER_CRITICAL(), which uses the macro + * portDISABLE_INTERRUPTS. However, in some ports of FreeRTOS and depending on + * FreeRTOS configuration, this does not disable high priority interrupts! + * If an ISR calls vTraceStoreISRBegin while the recorder is busy, it will + * stop the recording and give an error message. ******************************************************************************/ -void vTraceSetISRProperties(objectHandleType handle, char* name, char priority) +void vTraceSetISRProperties(objectHandleType handle, const char* name, char priority) { vTraceSetObjectName(TRACE_CLASS_ISR, handle, name); vTraceSetPriorityProperty(TRACE_CLASS_ISR, handle, priority); @@ -389,9 +699,7 @@ void vTraceSetISRProperties(objectHandleType handle, char* name, char priority) /******************************************************************************* * vTraceStoreISRBegin * - * Registers the beginning of an Interrupt Service Routine. This must not be - * interrupted by another ISR containing recorder library calls, so if allowing - * nested ISRs this must be called with interrupts disabled. + * Registers the beginning of an Interrupt Service Routine. * * Example: * #define ID_ISR_TIMER1 1 // lowest valid ID is 1 @@ -401,26 +709,38 @@ void vTraceSetISRProperties(objectHandleType handle, char* name, char priority) * ... * void ISR_handler() * { - * portENTER_CRITICAL(); // Required if nested ISRs are allowed * vTraceStoreISRBegin(ID_OF_ISR_TIMER1); - * portEXIT_CRITICAL(); * ... - * portENTER_CRITICAL(); // Required if nested ISRs are allowed * vTraceStoreISREnd(); - * portEXIT_CRITICAL(); * } + * + * NOTE: You need to make sure that any traced interrupts actually are + * disabled by trcCRITICAL_SECTION_BEGIN(), i.e., taskENTER_CRITICAL() which + * uses portDISABLE_INTERRUPTS(). + * In some ports of FreeRTOS, this does not disable high-priority interrupts, + * i.e., with priorities above configMAX_SYSCALL_INTERRUPT_PRIORITY. + * If an invalid call to vTraceStoreISRBegin is detected (i.e., that preempted + * a critical section of the recorder) this will generate a recorder error + * using vTraceError. ******************************************************************************/ void vTraceStoreISRBegin(objectHandleType handle) { uint16_t dts4; TSEvent* ts = NULL; + if (recorder_busy) + { + vTraceError("Illegal call to vTraceStoreISRBegin/End"); + return; + } if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) { + trcCRITICAL_SECTION_BEGIN(); dts4 = (uint16_t)prvTraceGetDTS(0xFFFF); if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ { + if (nISRactive < MAX_ISR_NESTING) { isrstack[nISRactive] = handle; @@ -438,17 +758,45 @@ void vTraceStoreISRBegin(objectHandleType handle) { /* This should not occur unless something is very wrong */ vTraceError("Too many nested interrupts!"); - } + } } + trcCRITICAL_SECTION_END(); + } +} + + +#if (SELECTED_PORT == PORT_ARM_CortexM) + +int tailchain_irq_pending(void); + +/******************************************************************************* + * tailchain_irq_pending + * + * For Cortex-M chips only. Returns 1 if an interrupt is pending, by checking + * the 8 NVIC IRQ pend registers at 0xE000E200 to 0xE000E21C. Returns 0 if no + * interrupt is pending. This is used to predict tailchaining of ISRs. + ******************************************************************************/ +int tailchain_irq_pending(void) +{ + uint32_t* pend_reg = ((uint32_t*)0xE000E200); + int i; + + for (i=0; i<8; i++) + { + if (pend_reg[i] != 0) + { + return 1; } + } + return 0; } +#endif + /******************************************************************************* * vTraceStoreISREnd * - * Registers the end of an Interrupt Service Routine. This must not be - * interrupted by another ISR containing recorder library calls, so if allowing - * nested ISRs this must be called with interrupts disabled. + * Registers the end of an Interrupt Service Routine. * * Example: * #define ID_ISR_TIMER1 1 // lowest valid ID is 1 @@ -458,26 +806,49 @@ void vTraceStoreISRBegin(objectHandleType handle) * ... * void ISR_handler() * { - * portENTER_CRITICAL(); // Required if nested ISRs are allowed * vTraceStoreISRBegin(ID_OF_ISR_TIMER1); - * portEXIT_CRITICAL(); * ... - * portENTER_CRITICAL(); // Required if nested ISRs are allowed * vTraceStoreISREnd(); - * portEXIT_CRITICAL(); * } + * + * NOTE: You need to make sure that any traced interrupts actually are + * disabled by trcCRITICAL_SECTION_BEGIN(), i.e., taskENTER_CRITICAL() which + * uses portDISABLE_INTERRUPTS(). + * In some ports of FreeRTOS, this does not disable high-priority interrupts, + * i.e., with priorities above configMAX_SYSCALL_INTERRUPT_PRIORITY. + * If an invalid call to vTraceStoreISREnd is detected (i.e., that preempted + * a critical section of the recorder) this will generate a recorder error + * using vTraceError. ******************************************************************************/ void vTraceStoreISREnd(void) { TSEvent* ts; uint16_t dts5; + if (recorder_busy) + { + vTraceError("Illegal call to vTraceStoreISRBegin/End"); + return; + } + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) - { + { + #if (SELECTED_PORT == PORT_ARM_CortexM) + if (tailchain_irq_pending() > 0) + { + nISRactive--; /* If an IRQ strikes exactly here, the resulting + ISR tailchaining is not detected. The trace instead shows a very + short fragment of the earlier preempted task/ISR, and then the new + ISR begins. */ + return; + } + #endif + + trcCRITICAL_SECTION_BEGIN(); dts5 = (uint16_t)prvTraceGetDTS(0xFFFF); if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ - { + { ts = (TSEvent*)xTraceNextFreeEventBufferSlot(); if (ts != NULL) { @@ -498,9 +869,24 @@ void vTraceStoreISREnd(void) prvTraceUpdateCounters(); } } + trcCRITICAL_SECTION_END(); } } +#else + +/* ISR tracing is turned off */ +void vTraceIncreaseISRActive(void) +{ + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + nISRactive++; +} + +void vTraceDecreaseISRActive(objectHandleType handle) +{ + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + nISRactive--; +} #endif @@ -523,14 +909,14 @@ void vTraceUserEvent(traceLabel eventLabel) UserEvent* ue; uint8_t dts1; - if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive ) && handle_of_last_logged_task) - { - taskENTER_CRITICAL(); + if (RecorderDataPtr->recorderActive && (! inExcludedTask || nISRactive ) && handle_of_last_logged_task) + { + trcCRITICAL_SECTION_BEGIN(); dts1 = (uint8_t)prvTraceGetDTS(0xFF); if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ - { + { ue = (UserEvent*) xTraceNextFreeEventBufferSlot(); if (ue != NULL) { @@ -540,7 +926,7 @@ void vTraceUserEvent(traceLabel eventLabel) prvTraceUpdateCounters(); } } - taskEXIT_CRITICAL(); + trcCRITICAL_SECTION_END(); } } @@ -550,112 +936,139 @@ void vTraceUserEvent(traceLabel eventLabel) (8*32 bit = 32 byte) available for argument data */ #define MAX_ARG_SIZE (4+32) -static uint8_t writeInt8(void * buffer, uint8_t index, uint8_t value); -static uint8_t writeInt16(void * buffer, uint8_t index, uint16_t value); -static uint8_t writeInt32(void * buffer, uint8_t index, uint32_t value); +static uint8_t writeInt8(void * buffer, uint8_t i, uint8_t value); +static uint8_t writeInt16(void * buffer, uint8_t i, uint16_t value); +static uint8_t writeInt32(void * buffer, uint8_t i, uint32_t value); #if (INCLUDE_FLOAT_SUPPORT) -static uint8_t writeFloat(void * buffer, uint8_t index, float value); -static uint8_t writeDouble(void * buffer, uint8_t index, double value); +static uint8_t writeFloat(void * buffer, uint8_t i, float value); +static uint8_t writeDouble(void * buffer, uint8_t i, double value); #endif /*** Locally used in vTracePrintF ***/ -static uint8_t writeInt8(void * buffer, uint8_t index, uint8_t value) +static uint8_t writeInt8(void * buffer, uint8_t i, uint8_t value) { - if (index + 1 > MAX_ARG_SIZE) + if (i >= MAX_ARG_SIZE) { return 255; } - ((uint8_t*)buffer)[index] = value; + ((uint8_t*)buffer)[i] = value; + + if (i + 1 > MAX_ARG_SIZE) + { + return 255; + } - return index + 1; + return i + 1; } /*** Locally used in vTracePrintF ***/ -static uint8_t writeInt16(void * buffer, uint8_t index, uint16_t value) -{ +static uint8_t writeInt16(void * buffer, uint8_t i, uint16_t value) +{ /* Align to multiple of 2 */ - while ((index % 2) != 0) - { - ((uint8_t*)buffer)[index] = 0; - index++; + while ((i % 2) != 0) + { + if (i >= MAX_ARG_SIZE) + { + return 255; + } + + ((uint8_t*)buffer)[i] = 0; + i++; } - if (index + 2 > MAX_ARG_SIZE) + if (i + 2 > MAX_ARG_SIZE) { return 255; } - ((uint16_t*)buffer)[index/2] = value; + ((uint16_t*)buffer)[i/2] = value; - return index + 2; + return i + 2; } /*** Locally used in vTracePrintF ***/ -static uint8_t writeInt32(void * buffer, uint8_t index, uint32_t value) +static uint8_t writeInt32(void * buffer, uint8_t i, uint32_t value) { /* A 32 bit value should begin at an even 4-byte address */ - while ((index % 4) != 0) + while ((i % 4) != 0) { - ((uint8_t*)buffer)[index] = 0; - index++; + if (i >= MAX_ARG_SIZE) + { + return 255; + } + + ((uint8_t*)buffer)[i] = 0; + i++; } - if (index + 4 > MAX_ARG_SIZE) + if (i + 4 > MAX_ARG_SIZE) { return 255; } - ((uint32_t*)buffer)[index/4] = value; + ((uint32_t*)buffer)[i/4] = value; - return index + 4; + return i + 4; } #if (INCLUDE_FLOAT_SUPPORT) /*** Locally used in vTracePrintF ***/ -static uint8_t writeFloat(void * buffer, uint8_t index, float value) +static uint8_t writeFloat(void * buffer, uint8_t i, float value) { /* A 32 bit value should begin at an even 4-byte address */ - while ((index % 4) != 0) + while ((i % 4) != 0) { - ((uint8_t*)buffer)[index] = 0; - index++; + if (i >= MAX_ARG_SIZE) + { + return 255; + } + + ((uint8_t*)buffer)[i] = 0; + i++; } - if (index + 4 > MAX_ARG_SIZE) + if (i + 4 > MAX_ARG_SIZE) { return 255; } - ((float*)buffer)[index/4] = value; + ((float*)buffer)[i/4] = value; - return index + 4; + return i + 4; } /*** Locally used in vTracePrintF ***/ -static uint8_t writeDouble(void * buffer, uint8_t index, double value) +static uint8_t writeDouble(void * buffer, uint8_t i, double value) { + uint32_t * dest = buffer; + uint32_t * src = (void*)&value; /* The double is written as two 32 bit values, and should begin at an even 4-byte address (to avoid having to align with 8 byte) */ - while (index % 4 != 0) + while (i % 4 != 0) { - ((uint8_t*)buffer)[index] = 0; - index++; + if (i >= MAX_ARG_SIZE) + { + return 255; + } + + ((uint8_t*)buffer)[i] = 0; + i++; } - if (index + 8 > MAX_ARG_SIZE) + if (i + 8 > MAX_ARG_SIZE) { return 255; } - ((uint32_t*)buffer)[index/4+0] = ((uint32_t*)&value)[0]; - ((uint32_t*)buffer)[index/4+1] = ((uint32_t*)&value)[1]; - - return index + 8; + dest[i/4+0] = src[0]; + dest[i/4+1] = src[1]; + + return i + 8; } #endif @@ -715,7 +1128,7 @@ void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...) UserEvent* ue1; va_list vl; uint8_t argCounter = 0; - uint8_t index = 0; + uint8_t i = 0; uint8_t nofEventEntries = 0; uint16_t formatStrIndex = 0; @@ -729,10 +1142,10 @@ void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...) * from different tasks overlaps (interrupts are only disabled in a small * part of this function, otherwise enabled) ***************************************************************************/ - uint32_t dummy = 0; /* for the alignment of tempDataBuffer*/ - uint8_t tempDataBuffer[MAX_ARG_SIZE]; - dummy = dummy; /* to eliminate compiler warnings*/ - + + uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4]; + + if ((inExcludedTask == 0) && (nISRactive == 0) && (RecorderDataPtr->recorderActive == 1) && @@ -744,7 +1157,7 @@ void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...) ue1 = (UserEvent*)(&tempDataBuffer[0]); ue1->type = EVENT_BEING_WRITTEN; /* Update this as the last step */ - index = 4; + i = 4; formatStrIndex = 0; va_start(vl, formatStr); /* Begin reading the arguments list */ @@ -759,7 +1172,7 @@ void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...) vTraceError("vTracePrintF - Too many arguments, max 15 allowed!"); va_end(vl); formatStr = "[vTracePrintF error] Too many arguments, max 15 allowed!"; - index = 4; + i = 4; break; } @@ -788,35 +1201,35 @@ void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...) formatStrIndex++; switch (formatStr[formatStrIndex]) { - case 'd': index = writeInt32(tempDataBuffer, - index, + case 'd': i = writeInt32((uint8_t*)tempDataBuffer, + i, (uint32_t)va_arg(vl, uint32_t)); break; - case 'u': index = writeInt32(tempDataBuffer, - index, + case 'u': i = writeInt32((uint8_t*)tempDataBuffer, + i, (uint32_t)va_arg(vl, uint32_t)); break; - case 's': index = writeInt16(tempDataBuffer, - index, - (uint16_t)xTraceOpenLabel((char*)va_arg(vl, uint32_t))); + case 's': i = writeInt16((uint8_t*)tempDataBuffer, + i, + (uint16_t)xTraceOpenLabel((char*)va_arg(vl, char*))); break; #if (INCLUDE_FLOAT_SUPPORT) /* Yes, "double" as type also in the float case. This since "float" is promoted into "double" by the va_arg stuff. */ - case 'f': index = writeFloat(tempDataBuffer, - index, + case 'f': i = writeFloat((uint8_t*)tempDataBuffer, + i, (float)va_arg(vl, double)); break; #else /* No support for floats, but attempt to store a float user event avoid a possible crash due to float reference. Instead store the data on uint_32 format (will not be displayed anyway). This is just -to keep va_arg and index consistent. */ +to keep va_arg and i consistent. */ - case 'f': index = writeInt32(tempDataBuffer, - index, + case 'f': i = writeInt32((uint8_t*)tempDataBuffer, + i, (uint32_t)va_arg(vl, double)); #endif case 'l': @@ -824,20 +1237,20 @@ to keep va_arg and index consistent. */ switch (formatStr[formatStrIndex]) { #if (INCLUDE_FLOAT_SUPPORT) - case 'f': index = writeDouble(tempDataBuffer, - index, + case 'f': i = writeDouble((uint8_t*)tempDataBuffer, + i, (double)va_arg(vl, double)); break; #else /* No support for floats, but attempt to store a float user event avoid a possible crash due to float reference. Instead store the data on uint_32 format (will not be displayed anyway). This is just -to keep va_arg and index consistent. */ - case 'f': index = writeInt32(tempDataBuffer, /* In this case, the value will not be shown anyway */ - index, +to keep va_arg and i consistent. */ + case 'f': i = writeInt32((uint8_t*)tempDataBuffer, /* In this case, the value will not be shown anyway */ + i, (uint32_t)va_arg(vl, double)); - index = writeInt32(tempDataBuffer, /* Do it twice, to write in total 8 bytes */ - index, + i = writeInt32((uint8_t*)tempDataBuffer, /* Do it twice, to write in total 8 bytes */ + i, (uint32_t)va_arg(vl, double)); #endif @@ -847,12 +1260,12 @@ to keep va_arg and index consistent. */ formatStrIndex++; switch (formatStr[formatStrIndex]) { - case 'd': index = writeInt16(tempDataBuffer, - index, + case 'd': i = writeInt16((uint8_t*)tempDataBuffer, + i, (uint16_t)va_arg(vl, uint32_t)); break; - case 'u': index = writeInt16(tempDataBuffer, - index, + case 'u': i = writeInt16((uint8_t*)tempDataBuffer, + i, (uint16_t)va_arg(vl, uint32_t)); break; } @@ -861,12 +1274,12 @@ to keep va_arg and index consistent. */ formatStrIndex++; switch (formatStr[formatStrIndex]) { - case 'd': index = writeInt8(tempDataBuffer, - index, + case 'd': i = writeInt8((uint8_t*)tempDataBuffer, + i, (uint8_t)va_arg(vl, uint32_t)); break; - case 'u': index = writeInt8(tempDataBuffer, - index, + case 'u': i = writeInt8((uint8_t*)tempDataBuffer, + i, (uint8_t)va_arg(vl, uint32_t)); break; } @@ -874,33 +1287,35 @@ to keep va_arg and index consistent. */ } } formatStrIndex++; - if (index == 255) + if (i == 255) { va_end(vl); - vTraceError("vTracePrintF - Too large arguments, max 32 byte allowed!"); + //vTraceError("vTracePrintF - Too large arguments, max 32 byte allowed!"); formatStr = "[vTracePrintF error] Too large arguments, max 32 byte allowed!"; - index = 4; + i = 4; break; } } va_end(vl); - + /* Store the format string, with a reference to the channel symbol */ ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel); - taskENTER_CRITICAL(); + trcCRITICAL_SECTION_BEGIN(); ue1->dts = (uint8_t)prvTraceGetDTS(0xFF); if (! RecorderDataPtr->recorderActive) { + /* Abort, since an XTS event (created by prvTraceGetDTS) filled the buffer, and the recorder stopped since not circular buffer. */ - taskEXIT_CRITICAL(); + trcCRITICAL_SECTION_END(); + return; } - nofEventEntries = (index+3)/4; + nofEventEntries = (i+3)/4; /* If the data does not fit in the remaining main buffer, wrap around to 0 if allowed, otherwise stop the recorder and quit). */ @@ -915,8 +1330,10 @@ to keep va_arg and index consistent. */ #else /* Abort and stop recorder, since the event data will not fit in the buffer and not circular buffer in this case... */ - taskEXIT_CRITICAL(); + trcCRITICAL_SECTION_END(); vTraceStop(); + + return; #endif } @@ -931,7 +1348,7 @@ to keep va_arg and index consistent. */ /* Copy the local buffer to the main buffer */ (void)memcpy(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4], tempDataBuffer, - index); + i); /* Update the event type, i.e., number of data entries following the main USER_EVENT entry (Note: important that this is after the memcpy, @@ -956,8 +1373,8 @@ to keep va_arg and index consistent. */ #endif } - taskEXIT_CRITICAL(); - } + trcCRITICAL_SECTION_END(); + } } /******************************************************************************* @@ -972,7 +1389,7 @@ to keep va_arg and index consistent. */ * * xTraceOpenLabel() * - * whihc adds the string to the symbol table (if not already present) + * which adds the string to the symbol table (if not already present) * and returns the corresponding handle. * * This can be used in two ways: @@ -995,7 +1412,7 @@ to keep va_arg and index consistent. */ * executed and/or located in time-critical code. The lookup operation is * however fairly fast due to the design of the symbol table. ******************************************************************************/ -traceLabel xTraceOpenLabel(char* label) +traceLabel xTraceOpenLabel(const char* label) { return prvTraceOpenSymbol(label, 0); }