Update the FreeRTOS+Trace recorder and Win32 demo app.

pull/1/head
Richard Barry 12 years ago
parent 96218c34a1
commit 26152204a4

@ -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;
}

@ -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

@ -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

@ -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
*

@ -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

@ -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 <stdio.h>
#include <string.h>
#include <stdint.h>
#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];

@ -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
#endif

@ -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

@ -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

@ -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

@ -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 <debug probe name>".
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: <name>.hex
- Press "Save" button
You can now open <name>.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: <name>.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 <name>.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

@ -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
www.percepio.com

@ -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(&timestamp);
/***************************************************************************
* 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
#endif

@ -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
#endif

@ -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;
}
/*******************************************************************************

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save