Add FreeRTOS-Plus directory.

This commit is contained in:
Richard Barry 2012-08-11 21:34:11 +00:00
parent 7bd5f21ad5
commit f508a5f653
6798 changed files with 134949 additions and 19 deletions

View file

@ -0,0 +1,22 @@
FreeRTOS+Trace v2.2.3
---------------------
This directory contains the recorder files that the typical FreeRTOS+Trace user needs to be aware of.
- trcPort.h - contains the hardware ports and the setting of what port to use.
- trcConfig.h - contains the recorder configuration.
The files in this directory are however not referenced by any of the demo projects.
Copies of these files are instead found in each Demo project directory.
These copies are included here to make the TraceRecorderSrc directory complete.
If you use this template, you will need to update the following macro definitions in trcPort.h:
- SELECTED_PORT
- IRQ_PRIORITY_ORDER
- vTraceConsoleMessage (optional, if console prints are desired)
Always remember to check the settings used in trcConfig.h.
Percepio AB
www.percepio.se

View file

@ -0,0 +1,431 @@
/*******************************************************************************
* FreeRTOS+Trace v2.2.3 Recorder Library
* Percepio AB, www.percepio.se
*
* trcConfig.h
*
* Configuration parameters for the trace recorder library. Before using the
* trace recorder library, please check that the default settings are
* appropriate for your system, and if necessary adjust these. Most likely, you
* will need to adjust the NTask, NISR, NQueue, NMutex and NSemaphore values to
* reflect the number of such objects in your system. These may be
* overapproximated, although larger values values implies more RAM usage.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* 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
*
* Copyright Percepio AB, 2012.
* www.percepio.se
******************************************************************************/
#ifndef TRCCONFIG_H
#define TRCCONFIG_H
/*******************************************************************************
* CONFIGURATION RELATED TO CAPACITY AND ALLOCATION
******************************************************************************/
/*******************************************************************************
* EVENT_BUFFER_SIZE
*
* Macro which should be defined as an integer value.
*
* This defines the capacity of the event buffer, i.e., the number of records
* it may store. Each registered event typically use one record (4 byte), but
* 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
/*******************************************************************************
* SYMBOL_TABLE_SIZE
*
* Macro which should be defined as an integer value.
*
* This defines the capacity of the symbol table, in bytes. This symbol table
* stores User Events labels and names of deleted tasks, queues, or other kernel
* objects. Note that the names of active objects not stored here but in the
* Object Table. Thus, if you don't use User Events or delete any kernel
* objects you set this to zero (0) to minimize RAM usage.
******************************************************************************/
#define SYMBOL_TABLE_SIZE 1000
/*******************************************************************************
* NTask, NISR, NQueue, NSemaphore, NMutex
*
* A group of Macros which should be defined as an integer value of zero (0)
* or larger.
*
* This defines the capacity of the Object Property Table - the maximum number
* of objects active at any given point within each object class.
*
* NOTE: In case objects are deleted and created during runtime, this setting
* does not limit the total amount of objects, only the number of concurrently
* active objects.
*
* Using too small values will give an error message through the vTraceError
* 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.
*
* Also 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.
*
* NOTE 3: The FreeRTOS timer task creates a Queue, that should be accounted
* for in NQueue.
******************************************************************************/
#define NTask 15
#define NISR 4
#define NQueue 3
#define NSemaphore 4
#define NMutex 2
/* Maximum object name length for each class (includes zero termination) */
#define NameLenTask configMAX_TASK_NAME_LEN
#define NameLenISR 10
#define NameLenQueue 15
#define NameLenSemaphore 15
#define NameLenMutex 15
/******************************************************************************
* TRACE_DESCRIPTION
*
* Macro which should be defined as a string.
*
* This string is stored in the trace and displayed in FreeRTOS+Trace. Can be
* used to store, e.g., system version or build date. This is also used to store
* internal error messages from the recorder, which if occurs overwrites the
* value defined here. This may be maximum 256 chars.
*****************************************************************************/
#define TRACE_DESCRIPTION "FreeRTOS+Trace Demo"
/******************************************************************************
* TRACE_DESCRIPTION_MAX_LENGTH
*
* The maximum length (including zero termination) for the TRACE_DESCRIPTION
* string. Since this string also is used for internal error messages from the
* recorder do not make it too short, as this may truncate the error messages.
* Default is 80.
* Maximum allowed length is 256 - the trace will fail to load if longer.
*****************************************************************************/
#define TRACE_DESCRIPTION_MAX_LENGTH 80
/******************************************************************************
* TRACE_DATA_ALLOCATION
*
* This defines how to allocate the recorder data structure, i.e., using a
* static declaration or using a dynamic allocation in runtime (malloc).
*
* Should be one of these two options:
* - TRACE_DATA_ALLOCATION_STATIC (default)
* - TRACE_DATA_ALLOCATION_DYNAMIC
*
* Using static allocation has the benefits of compile-time errors if the buffer
* is too large (too large constants in trcConfig.h) and no need to call the
* initialization routine (xTraceInitTraceData).
*
* Using dynamic allocation may give more flexibility in some cases.
*****************************************************************************/
#define TRACE_DATA_ALLOCATION TRACE_DATA_ALLOCATION_STATIC
/******************************************************************************
* CONFIGURATION REGARDING WHAT CODE/FEATURES TO INCLUDE
*****************************************************************************/
/******************************************************************************
* INCLUDE_FLOAT_SUPPORT
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* If this is zero (0), all references to floating point values are removed,
* in case floating point values are not supported by the platform used.
* Floating point values are only used in vTracePrintF and its subroutines, to
* store float (%f) or double (%lf) argments.
*
* Note: vTracePrintF can still be used with integer and string arguments in
* either case.
*****************************************************************************/
#define INCLUDE_FLOAT_SUPPORT 1
/******************************************************************************
* INCLUDE_USER_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* If this is zero (0) the code for creating User Events is excluded to
* reduce code size. User Events are application-generated events, like
* "printf" but for the trace log instead of console output. User Events are
* much faster than a printf and can therefore be used in timing critical code.
* See vTraceUserEvent() and vTracePrintF() in trcUser.h
*
* Note that FreeRTOS+Trace Standard Edition or Professional Edition is required
* for User Events, they are not displayed in FreeRTOS+Trace Free Edition.
*****************************************************************************/
#define INCLUDE_USER_EVENTS 1
/*****************************************************************************
* INCLUDE_ISR_TRACING
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* If this is zero (0), the code for recording Interrupt Service Routines is
* excluded to reduce code size. Note, recording ISRs require that you insert
* calls to vTraceStoreISRBegin and vTraceStoreISREnd in your interrupt handlers.
* There is no automatic recording of ISRs like for task scheduling, since
* FreeRTOS does not have a central interrupt dispatcher.
*****************************************************************************/
#define INCLUDE_ISR_TRACING 1
/******************************************************************************
* INCLUDE_OBJECT_DELETE
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* This must be enabled (1) if tasks, queues or other
* traced kernel objects are deleted at runtime, e.g., using vTaskDelete or
* vQueueDelete. If no deletes are made, this can be set to 0 in order to
* exclude the delete-handling code.
*****************************************************************************/
#define INCLUDE_OBJECT_DELETE 1
/******************************************************************************
* CONFIGURATION RELATED TO BEHAVIOR
*****************************************************************************/
/******************************************************************************
* RECORDER_STORE_MODE
*
* Macro which should be defined as one of:
* - STORE_MODE_RING_BUFFER
* - STORE_MODE_STOP_WHEN_FULL
* Default is STORE_MODE_RING_BUFFER.
*
* With RECORDER_STORE_MODE set to STORE_MODE_RING_BUFFER, the events are stored
* in a ring buffer, i.e., where the oldest events are overwritten when the
* buffer becomes full. This allows you to get the last events leading up to an
* interesting state, e.g., an error, without having a large trace buffer for
* string the whole run since startup. In this mode, the recorder can run
* "forever" as the buffer never gets full, i.e., in the sense that it always
* has room for more events.
*
* To fetch the trace in mode STORE_MODE_RING_BUFFER, you need to first halt the
* system using your debugger and then do a RAM dump, or to explicitly stop the
* recorder using vTraceStop() and then store/upload the trace data using a
* FreeRTOS task that you need to provide yourself. The trace data is found in
* the struct RecorderData, initialized in trcBase.c.
*
* Note that, if you upload the trace using a RAM dump, i.e., when the system is
* halted on a breakpoint or by a debugger command, there is no need to stop the
* recorder first.
*
* When RECORDER_STORE_MODE is STORE_MODE_STOP_WHEN_FULL, the recording is
* stopped when the buffer becomes full. When the recorder stops itself this way
* vTracePortEnd() is called which allows for custom actions, such as triggering
* a task that stores the trace buffer, i.e., in case taking a RAM dump
* using an on-chip debugger is not possible. In the Windows port, vTracePortEnd
* saves the trace to file directly, but this is not recommended in a real-time
* system since the scheduler is blocked during the processing of vTracePortEnd.
*****************************************************************************/
#ifndef WIN32
#define RECORDER_STORE_MODE STORE_MODE_RING_BUFFER
#else
/* Default in the Win32 demo */
#define RECORDER_STORE_MODE STORE_MODE_STOP_WHEN_FULL
#endif
/******************************************************************************
* STOP_AFTER_N_EVENTS
*
* Macro which should be defined as an integer value, or not defined.
* Default is -1
*
* STOP_AFTER_N_EVENTS is intended for tests of the ring buffer mode (when
* RECORDER_STORE_MODE is STORE_MODE_RING_BUFFER). It stops the recording when
* the specified number of events has been observed. This value can be larger
* than the buffer size, to allow for test of the "wrapping around" that occurs
* in ring buffer mode . A negative value (or no definition of this macro)
* disables this feature.
*****************************************************************************/
#define STOP_AFTER_N_EVENTS -1
/******************************************************************************
* USE_IMPLICIT_IFE_RULES
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* ### Instance Finish Events (IFE) ###
*
* For tasks with "infinite" main loops (non-terminating tasks), the concept
* of a task instance has no clear definition, it is an application-specific
* thing. FreeRTOS+Trace allows you to define Instance Finish Events (IFEs),
* which marks the point in a cyclic task when the "task instance" ends.
* The IFE is a blocking kernel call, typically in the main loop of a task
* which typically reads a message queue, waits for a semaphore or performs
* an explicit delay.
*
* If USE_IMPLICIT_IFE_RULES is one (1), the following FreeRTOS kernel calls
* are considered by default to be IFEs (Implicit IFEs):
* - vTaskDelay
* - vTaskDelayUntil
* - vTaskSuspend
* - xQueueReceive (blocking cases only)
* - xSemaphoreTake (blocking cases only)
*
* However, Implicit IFEs only applies to blocking kernel calls. If an
* xQueueReceive reads a message without blocking, it does not create a new
* instance since no blocking occurred.
*
* Moreover, the actual IFE might sometimes be another blocking call such as
* xQueueSend or xSemaphoreGive. We therefore allow for user-defined
* Explicit IFEs by calling
*
* vTraceTaskInstanceIsFinished()
*
* right before the kernel call considered as IFE. This does not create an
* additional event but instead stores the service code and object handle
* of the IFE call as properties of the task.
*
* If using Explicit IFEs and the task also calls an Implicit IFE like
* vTaskDelay, this may result in additional incorrect task instances.
* This is solved by disabling the Implicit IFEs for the task, by adding
* a call to
*
* vTraceTaskSkipDefaultInstanceFinishedEvents()
*
* in the very beginning of that task. This allows you to combine Explicit IFEs
* for some tasks with Implicit IFEs for the rest of the tasks, if
* USE_IMPLICIT_IFE_RULES is 1.
*
* By setting USE_IMPLICIT_IFE_RULES to zero (0), the implicit IFEs are disabled
* for all tasks. Tasks will then be considered to have a single instance only,
* covering all execution fragments, unless you define an explicit IFE in each
* task by calling vTraceTaskInstanceIsFinished before the blocking call.
*****************************************************************************/
#define USE_IMPLICIT_IFE_RULES 1
/******************************************************************************
* INCLUDE_SAVE_TO_FILE
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 0.
*
* If enabled (1), the recorder will include code for saving the trace
* to a local file system.
******************************************************************************/
#ifdef WIN32
#define INCLUDE_SAVE_TO_FILE 1
#else
#define INCLUDE_SAVE_TO_FILE 0
#endif
/******************************************************************************
* TRACE_PROGRESS_MONITOR_TASK_PRIORITY
*
* Macro which sets the priority of the "recorder status monitor" task.
*
* This task, vTraceMonitorTask in trcUser.c, periodically writes
* the recorder status using the vTraceConsoleMessage macro, which is to
* be mapped to your console "printf" routine. The task is named TraceMon but
* is intentionally excluded from the demo trace.
*
* Default is tskIDLE_PRIORITY + 1
* Note that if your system constantly has a high CPU load from high-priority
* tasks, this might not be get a chance to execute.
*
* See vTraceMonitorTask in trcUser.c
*****************************************************************************/
#define TRACE_PROGRESS_MONITOR_TASK_PRIORITY (tskIDLE_PRIORITY + 1)
/******************************************************************************
* TRACE_PROGRESS_MONITOR_TASK_STACKSIZE
*
* Macro which sets the stack size of the "recorder status monitor" task.
*
* This task, vTraceMonitorTask in trcUser.c, periodically writes
* the recorder status using the vTraceConsoleMessage macro, which is to
* be mapped to your console "printf" routine. The task is intentionally
* excluded from the demo trace.
*
* See vTraceMonitorTask in trcUser.c
*****************************************************************************/
#define TRACE_PROGRESS_MONITOR_TASK_STACKSIZE 500
/******************************************************************************
* TRACE_PROGRESS_MONITOR_TASK_PERIOD
*
* Macro which sets the period of the "recorder status monitor" task.
*
* This task, vTraceMonitorTask in trcUser.c, periodically writes
* the recorder status using the vTraceConsoleMessage macro, which is to
* be mapped to your console "printf" routine. The task is named TraceMon but
* is intentionally excluded from the demo trace.
*
* Default is 1000 FreeRTOS ticks (typically 1 second). On the Windows port, a
* lower value is suggested since the Windows port runs very slowly, often 20-40
* times slower than the simulated FreeRTOS time.
*
* See vTraceMonitorTask in trcUser.c
*****************************************************************************/
#ifdef WIN32
#define TRACE_PROGRESS_MONITOR_TASK_PERIOD 100
#else
#define TRACE_PROGRESS_MONITOR_TASK_PERIOD 1000
#endif
/******************************************************************************
* TEAM_LICENSE_CODE
*
* Macro which defines a string - the team license code.
* If no team license is available, this should be an empty string "".
* This should be maximum 32 chars, including zero-termination.
*****************************************************************************/
#define TEAM_LICENSE_CODE ""
#endif

View file

@ -0,0 +1,397 @@
/*******************************************************************************
* FreeRTOS+Trace v2.2.3 Recorder Library
* Percepio AB, www.percepio.se
*
* trcPort.h
*
* Contains together with trcPort.c all portability issues of the trace recorder
* library.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* 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
*
* Copyright Percepio AB, 2012.
* www.percepio.se
******************************************************************************/
#ifndef TRCPORT_H
#define TRCPORT_H
#include "trcBase.h"
/* If FreeRTOS Win32 port */
#ifdef WIN32
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
/* Standard includes. */
#include <stdio.h>
#include <windows.h>
#include <direct.h>
/*******************************************************************************
* The Win32 port by default saves the trace to file and then kills the
* program when the recorder is stopped, to facilitate quick, simple tests
* of the recorder.
******************************************************************************/
#define WIN32_PORT_SAVE_WHEN_STOPPED 1
#define WIN32_PORT_EXIT_WHEN_STOPPED 1
#endif
#define DIRECTION_INCREMENTING 1
#define DIRECTION_DECREMENTING 2
/******************************************************************************
* Supported ports
*
* PORT_HWIndependent
* A hardware independent fallback option for event timestamping. Provides low
* resolution timestamps based on the OS tick.
* This may be used on the Win32 port, but may also be used on embedded hardware
* platforms. Note that this gives suboptimal display in FreeRTOS+Trace. All
* time durations will be truncated to the OS tick frequency, typically 1 KHz.
* This means that a task or ISR that executes in less than 1 ms get an exection
* time of zero. They are however still visible in FreeRTOS+Trace.
*
* PORT_Win32
* "Accurate" timestamping based on the Windows permance counter. Note that
* this gives the host machine time, not the simulated FreeRTOS time (tick
* 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:
* - PORT_Atmel_AT91SAM7
* - PORT_ARM_CortexM
* - PORT_Renesas_RX600
*
* We also provide several "unofficial" hardware-specific ports. There have
* been developed by external contributors, and have not yet been verified
* by Percepio AB. Let us know if you have problems getting these to work.
*
* Unoffical hardware specific ports provided are:
* - PORT_TEXAS_INSTRUMENTS_TMS570
* - PORT_TEXAS_INSTRUMENTS_MSP430
* - PORT_MICROCHIP_PIC32
* - PORT_MICROCHIP_dsPIC_AND_PIC24
* - PORT_XILINX_PPC405
* - PORT_XILINX_PPC440
*
******************************************************************************/
#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 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
/*** Select your port here! **************************************************/
#define SELECTED_PORT PORT_NOT_SET
/*****************************************************************************/
/*******************************************************************************
* IRQ_PRIORITY_ORDER
*
* Macro which should be defined as an integer of 0 or 1.
*
* This should be 0 if lower irq priority values implies higher priority
* levels, such as on ARM Cortex M. If the opposite scheme is used, i.e.,
* if higher irq priority values means higher priority, this should be 1.
*
* This setting is not critical. It is used only to sort and colorize the
* interrupts in priority order, in case you record interrupts using
* the vTraceStoreISRBegin and vTraceStoreISREnd routines.
*
* We provide this setting for some hardware architectures below:
* - ARM Cortex M: 0 (lower irq priority values are more significant)
* - Atmel AT91SAM7x: 1 (higher irq priority values are more significant)
* - 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)
*
* 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
* 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.
*
* HWTC_COUNT: The current value of the counter. This is expected to be reset
* a each tick interrupt. Thus, when the tick handler starts, the counter has
* already wrapped.
*
* HWTC_COUNT_DIRECTION: Should be one of:
* - DIRECTION_INCREMENTING - for hardware timer/counters of incrementing type
* such as the PIT on Atmel AT91SAM7X.
* When the counter value reach HWTC_PERIOD, it is reset to zero and the
* interrupt is signaled.
* - DIRECTION_DECREMENTING - for hardware timer/counters of decrementing type
* such as the SysTick on ARM Cortex M3/M4 chips.
* When the counter value reach 0, it is reset to HWTC_PERIOD and the
* interrupt is signaled.
*
* HWTC_PERIOD: The number of increments or decrements of HWTC_COUNT between
* two tick interrupts. This should preferably be mapped to the reload
* register of the hardware timer, to make it more portable between chips in the
* same family. The macro should in most cases be (reload register + 1).
*
* HWTC_DIVISOR: If the timer frequency is very high, like on the Cortex M chips
* (where the SysTick runs at the core clock frequency), the "differential
* 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
* 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
* Cortex M chip running at 72 MHZ should use a HWTC_DIVISOR of 2, while a
* faster chip require a higher HWTC_DIVISOR value.
*
* The HWTC macros and uiTracePortGetTimeStamp is the main porting issue
* or the trace recorder library. Typically you should not need to change
* the code of uiTracePortGetTimeStamp if using the HWTC macros.
*
* 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.
*
******************************************************************************/
#if (SELECTED_PORT == PORT_Win32)
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (ulGetRunTimeCounterValue())
#define HWTC_PERIOD 0
#define HWTC_DIVISOR 1
#elif (SELECTED_PORT == PORT_HWIndependent)
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT 0
#define HWTC_PERIOD 1
#define HWTC_DIVISOR 1
#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 */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF)
#define HWTC_PERIOD 2995
#define HWTC_DIVISOR 1
#elif (SELECTED_PORT == PORT_ARM_CortexM)
/* 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
#elif (SELECTED_PORT == PORT_Renesas_RX600)
#include "iodefine.h"
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (CMT0.CMCNT)
#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 RTIFRC0 *((uint32_t *)0xFFFFFC10)
#define RTICOMP0 *((uint32_t *)0xFFFFFC50)
#define RTIUDCP0 *((uint32_t *)0xFFFFFC54)
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (RTIFRC0 - (RTICOMP0 - RTIUDCP0))
#define HWTC_PERIOD (RTIUDCP0)
#define HWTC_DIVISOR 1
#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
#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
#elif (SELECTED_PORT == PORT_XILINX_PPC405)
/* 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
#elif (SELECTED_PORT == PORT_XILINX_PPC440)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* This should work with most PowerPC chips */
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT mfspr( 0x016 )
#define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ )
#define HWTC_DIVISOR 1
#else
#error "SELECTED_PORT is not set, or had unsupported value!"
#endif
#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!"
#endif
#if (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
/*******************************************************************************
* vTraceConsoleMessage
*
* A wrapper for your system-specific console "printf" console output function.
* This needs to be correctly defined to see status reports from the trace
* status monitor task (this is defined in trcUser.c).
******************************************************************************/
#define vTraceConsoleMessage(x)
/*******************************************************************************
* uiTracePortGetTimeStamp
*
* Returns the current time based on the HWTC macros which provide a hardware
* isolation layer towards the hardware timer/counter.
*
* The HWTC macros and uiTracePortGetTimeStamp is the main porting issue
* or the trace recorder library. Typically you should not need to change
* the code of uiTracePortGetTimeStamp if using the HWTC macros.
*
* 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.
******************************************************************************/
uint32_t uiTracePortGetTimeStamp(void);
/*******************************************************************************
* vTracePortEnd
*
* This function is called when the recorder is stopped due to full buffer.
* Mainly intended to show a message in the console.
* This is used by the Win32 port to store the trace to a file. The file path is
* set using vTracePortSetFileName.
******************************************************************************/
void vTracePortEnd(void);
#if (INCLUDE_SAVE_TO_FILE == 1)
/*******************************************************************************
* vTracePortSetOutFile
*
* Sets the filename/path used in vTracePortSave.
* This is set in a separate function, since the Win32 port calls vTracePortSave
* in vTracePortEnd if WIN32_PORT_SAVE_WHEN_STOPPED is set.
******************************************************************************/
void vTracePortSetOutFile(char* path);
/******************************************************************************
* vTracePortSave
*
* Saves the trace to a file on a target-side file system. The path is set in a
* separate function, vTracePortSetOutFile, since the Win32 port may call
* vTracePortSave in vTracePortEnd, if using WIN32_PORT_SAVE_WHEN_STOPPED.
******************************************************************************/
void vTracePortSave(void);
#endif
#endif

View file

@ -0,0 +1,497 @@
/*******************************************************************************
* FreeRTOS+Trace v2.2.3 Recorder Library
* Percepio AB, www.percepio.se
*
* trcBase.h
*
* Core functionallity of the FreeRTOS+Trace recorder library.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* 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
*
* Copyright Percepio AB, 2012.
* www.percepio.se
******************************************************************************/
#ifndef TRCBASE_H
#define TRCBASE_H
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "FreeRTOS.h"
#include "trcConfig.h"
#include "trcTypes.h"
#include "trcPort.h"
#define NCLASSES 5
#define VERSION 0x1AA1
#define MINOR_VERSION 1
#define STORE_MODE_STOP_WHEN_FULL 1
#define STORE_MODE_RING_BUFFER 2
#define TRACE_DATA_ALLOCATION_STATIC 1
#define TRACE_DATA_ALLOCATION_DYNAMIC 2
/******************************************************************************
* Object Property Table
* The Object Table contains name and other properties of the objects (tasks,
* queues, mutexes, etc). The below data structures defines the properties of
* each object class and are used to cast the byte buffer into a cleaner format.
*
* The values in the object table are continously overwritten and always
* represent the current state. If a property is changed during runtime, the OLD
* value should be stored in the trace buffer, not the new value (since the new
* value is found in the Object Property Table).
* For close events this mechanism is the old names are stored in the symbol
* table), for "priority set" (the old priority is stored in the event data)
* and for "isActive", where the value decides is the taskswitch event type
* should be "new" or "resume".
******************************************************************************/
/* The size of the Object Property Table entries, in bytes, per object */
/* Queue properties (except name): current number of message in queue */
#define PropertyTableSizeQueue (NameLenQueue + 1)
/* Semaphore properties (except name): state (signaled = 1, cleared = 0) */
#define PropertyTableSizeSemaphore (NameLenSemaphore + 1)
/* Mutex properties (except name): owner (task handle, 0 = free) */
#define PropertyTableSizeMutex (NameLenMutex + 1)
/* Task properties (except name): Byte 0: Current priority
Byte 1: state (if already active)
Byte 2: InstanceFinishEvent_ServiceCode
Byte 3: InstanceFinishEvent_ObjHandle */
#define PropertyTableSizeTask (NameLenTask + 4)
/* ISR properties: Byte 0: priority
Byte 1: state (if already active) */
#define PropertyTableSizeISR (NameLenISR + 2)
/* The layout of the byte array representing the Object Property Table */
#define StartIndexQueue 0
#define StartIndexSemaphore StartIndexQueue + NQueue * PropertyTableSizeQueue
#define StartIndexMutex StartIndexSemaphore + NSemaphore * PropertyTableSizeSemaphore
#define StartIndexTask StartIndexMutex + NMutex * PropertyTableSizeMutex
#define StartIndexISR StartIndexTask + NTask * PropertyTableSizeTask
#define DynObjTableSize StartIndexISR + NISR * PropertyTableSizeISR
typedef struct
{
/* = NCLASSES */
uint32_t NumberOfObjectClasses;
uint32_t ObjectPropertyTableSizeInBytes;
/* This is used to calculate the index in the dynamic object table
(handle - 1 - nofStaticObjects = index)*/
uint8_t NumberOfObjectsPerClass[ 4*((NCLASSES+3)/4)];
/* Allocation size rounded up to the closest multiple of 4 */
uint8_t NameLengthPerClass[ 4*((NCLASSES+3)/4) ];
uint8_t TotalPropertyBytesPerClass[ 4*((NCLASSES+3)/4) ];
/* Allocation size rounded up to the closest multiple of 2 */
uint16_t StartIndexOfClass[ 2*((NCLASSES+1)/2) ];
/* The actual handles issued, should be Initiated to all zeros */
uint8_t objbytes[ 4*((DynObjTableSize+3)/4) ];
} ObjectPropertyTableType;
/* Symbol table data structure */
typedef struct
{
/* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */
uint32_t symTableSize;
/* Entry 0 is reserved. Any reference to entry 0 implies NULL*/
uint32_t nextFreeSymbolIndex;
/* Size rounded up to closest multiple of 4, to avoid alignment issues*/
uint8_t symbytes[4*((SYMBOL_TABLE_SIZE+3)/4)];
/* Used for lookups - Up to 64 linked lists within the symbol table
connecting all entries with the same 6 bit checksum.
This field holds the current list heads. Should be initiated to zeros */
uint16_t latestEntryOfChecksum[64];
} symbolTableType;
/*******************************************************************************
* The data structures of the different events, all 4 bytes long
******************************************************************************/
typedef struct
{
uint8_t type;
objectHandleType objHandle;
uint16_t dts; /* differential timestamp - time since last event */
} TSEvent;
typedef struct
{
uint8_t type;
uint8_t objHandle;
uint16_t dts;
} KernelCall;
typedef struct
{
uint8_t type;
objectHandleType objHandle;
uint8_t param;
uint8_t dts;
} KernelCallWithParamAndHandle;
typedef struct
{
uint8_t type;
uint8_t dts;
uint16_t param;
} KernelCallWithParam16;
typedef struct
{
uint8_t type;
objectHandleType objHandle; /* the handle of the closed object */
uint16_t symbolIndex; /* the name of the closed object */
} ObjCloseNameEvent;
typedef struct
{
uint8_t type;
uint8_t arg1;
uint8_t arg2;
uint8_t arg3;
} ObjClosePropEvent;
typedef struct
{
uint8_t type;
uint8_t dts;
uint16_t payload; /* the name of the user event */
} UserEvent;
typedef struct
{
uint8_t type;
/* 8 bits extra for storing DTS, if it does not fit in ordinary event
(this one is always MSB if used) */
uint8_t xts_8;
/* 16 bits extra for storing DTS, if it does not fit in ordinary event. */
uint16_t xts_16;
} XTSEvent;
/*******************************************************************************
* The main datastructure, read by FreeRTOS+Trace from the RAM dump
******************************************************************************/
typedef struct
{
uint8_t startmarker0;
uint8_t startmarker1;
uint8_t startmarker2;
uint8_t startmarker3;
uint8_t startmarker4;
uint8_t startmarker5;
uint8_t startmarker6;
uint8_t startmarker7;
uint8_t startmarker8;
uint8_t startmarker9;
uint8_t startmarker10;
uint8_t startmarker11;
/* For FreeRTOS: 0x1AA1 */
uint16_t version;
/* Currently 1 for v2.2.2 (0 earlier)*/
uint8_t minor_version;
/* This should be 0 if lower irq priority values implies higher priority
levels, such as on ARM Cortex M. If the opposite scheme is used, i.e.,
if higher irq priority values means higher priority, this should be 1. */
uint8_t irq_priority_order;
/* sizeof(RecorderDataType) - just for control */
uint32_t filesize;
/* Current number of events recorded */
uint32_t numEvents;
/* The buffer size, in number of event records */
uint32_t maxEvents;
/* The event buffer index, where to write the next event */
uint32_t nextFreeIndex;
/* 1 if the buffer is full, 0 otherwise */
uint32_t bufferIsFull;
/* The frequency of the clock/timer/counter used as time base */
uint32_t frequency;
/* The absolute timestamp of the last stored event, in the native
timebase, modulo frequency! */
uint32_t absTimeLastEvent;
/* The number of seconds in total - lasts for 136 years */
uint32_t absTimeLastEventSecond;
/* 1 if the recorder has been started, 0 if not yet started or stopped.
This is a 32 bit variable due to alignment issues. */
uint32_t recorderActive;
/* For storing a Team License key */
uint8_t teamLicenceKey[32];
/* 0xF0F0F0F0 - for control only */
int32_t debugMarker0;
/* The Object Property Table holds information about currently active
tasks, queues, and other recorded objects. This is updated on each
create call and includes object name and other properties. */
ObjectPropertyTableType ObjectPropertyTable;
/* 0xF1F1F1F1 - for control only */
int32_t debugMarker1;
/* The Symbol Table stores strings for User Events and is also used to
store names of deleted objects, which still may be in the trace but no
longer are available. */
symbolTableType SymbolTable;
/* For includsion of float support, and for endian detection of floats.
The value should be (float)1 or (uint32_t)0 */
#if (INCLUDE_FLOAT_SUPPORT == 1)
float exampleFloatEncoding;
#else
uint32_t exampleFloatEncoding;
#endif
/* This is non-zero if an internal error occured in the recorder, e.g., if
one of the Nxxx constants was too small. The systemInfo string will then
contain an error message that is displayed when attempting to view the
trace file. */
uint32_t internalErrorOccured;
/* 0xF2F2F2F2 - for control only */
int32_t debugMarker2;
/* Generic system information string, presented in the tool. Note that this
is also used for storing any internal error messages from the recorder, so
do not make TRACE_DESCRIPTION_MAX_LENGTH too small. 80 is recommended. */
char systemInfo[TRACE_DESCRIPTION_MAX_LENGTH];
/* 0xF3F3F3F3 - for control only */
int32_t debugMarker3;
/* The event data, in 4-byte records */
uint8_t eventData[ EVENT_BUFFER_SIZE * 4 ];
uint8_t endmarker0;
uint8_t endmarker1;
uint8_t endmarker2;
uint8_t endmarker3;
uint8_t endmarker4;
uint8_t endmarker5;
uint8_t endmarker6;
uint8_t endmarker7;
uint8_t endmarker8;
uint8_t endmarker9;
uint8_t endmarker10;
uint8_t endmarker11;
} RecorderDataType;
extern RecorderDataType* RecorderDataPtr;
/******************************************************************************
* ObjectHandleStack
* This data-structure is used to provide a mechanism for 1-byte trace object
* handles. This way, only 1 byte is necessary instead of 4 bytes (a pointer)
* when storing a reference to an object. This allows for up to 255 objects of
* each object class - Task, ISR, Semaphore, CountingSemaphore, Mutex and Queue,
* active at any given moment. There can be more "historic" objects, that have
* been deleted - that number is only limited by the size of the symbol table.
* Note that handle zero (0) is not used, it is a code for an invalid handle.
*
* This data structure keeps track of the FREE handles, not the handles in use.
* This datastructure contains one stack per object class. When a handle is
* allocated to an object, the next free handle is popped from the stack. When
* a handle is released (on object delete), it is pushed back on the stack.
* Note that there is no initialization code that pushed the free handles
* initially, that is not necessary due to the following optimization:
*
* The stack of handles (objectHandles) is initially all zeros. Since zero
* is not a valid handle, that is a signal of additional handles needed.
* If a zero is received when popping a new handle, it is replaced by the
* index of the popped handle instead.
*
*****************************************************************************/
typedef struct
{
/* For each object class, the index of the next handle to allocate */
int16_t indexOfNextAvailableHandle[ NCLASSES ];
/* The lowest index of this class (constant) */
int16_t lowestIndexOfClass[ NCLASSES ];
/* The highest index of this class (constant) */
int16_t highestIndexOfClass[ NCLASSES ];
/* The highest use count for this class (for statistics) */
int16_t handleCountWaterMarksOfClass[ NCLASSES ];
/* The free object handles - a set of stacks within this array */
objectHandleType objectHandles[ NTask+NISR+NSemaphore+NMutex+NQueue ];
} objectHandleStackType;
/* Internal data */
extern objectHandleStackType objectHandleStacks;
extern uint8_t taskFlags[NTask];
/* Internal functions */
uint32_t prvTraceGetDTS(uint32_t param_maxDTS);
void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength);
traceLabel prvTraceCreateSymbolTableEntry(const char* name,
uint8_t crc6,
uint8_t len,
traceLabel channel);
traceLabel prvTraceLookupSymbolTableEntry(const char* name,
uint8_t crc6,
uint8_t len,
traceLabel channel);
traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel);
void prvTraceUpdateCounters(void);
void prvCheckDataToBeOverwrittenForMultiEntryUserEvents(uint32_t nEntries);
objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass);
void vTraceFreeObjectHandle(traceObjectClass objectclass,
objectHandleType handle);
void vTraceSetObjectName(traceObjectClass objectclass,
objectHandleType handle,
const char* name);
void* xTraceNextFreeEventBufferSlot(void);
uint32_t uiIndexOfObject(objectHandleType objecthandle,
uint8_t objectclass);
/*******************************************************************************
* vTraceError
*
* 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);
/*******************************************************************************
* xTraceGetLastError
*
* Gives the last error message, if any. NULL if no error message is stored.
* The message is cleared on read.
******************************************************************************/
char* xTraceGetLastError(void);
/*******************************************************************************
* xTraceInitTraceData
*
* Allocates and initializes the recorder datastructure, based on the constants
* in trcConfig.h. This allows for allocating the data on the heap, instead of
* using a static declaration.
******************************************************************************/
RecorderDataType* xTraceInitTraceData(void);
/* Internal macros */
#define PROPERTY_NAME_GET(objectclass, objecthandle) \
(const char*)(& RecorderDataPtr->ObjectPropertyTable.objbytes \
[uiIndexOfObject(objecthandle, objectclass)])
#define PROPERTY_OBJECT_STATE(objectclass, handle) \
RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass]]
#define PROPERTY_ACTOR_PRIORITY(objectclass, handle) \
RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass] + 1]
#define PROPERTY_TASK_IFE_SERVICECODE(handle) \
RecorderDataPtr->ObjectPropertyTable.objbytes \
[uiIndexOfObject(handle, TRACE_CLASS_TASK) \
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[TRACE_CLASS_TASK]+2]
#define PROPERTY_TASK_IFE_OBJHANDLE(handle) \
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_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_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)
/* For debug printouts - the names of the object classes */
extern char OBJECTCLASSNAME[NCLASSES][10];
/*=
{
"QUEUE"
"SEMAPHORE",
"MUTEX",
"TASK",
"ISR"
};*/
#endif

View file

@ -0,0 +1,292 @@
/*******************************************************************************
* FreeRTOS+Trace v2.2.3 Recorder Library
* Percepio AB, www.percepio.se
*
* trcHooks.h
*
* The kernel integration hooks for FreeRTOS (v7.1.0 or later). This file should
* be included in the end of FreeRTOSConfig.h, together with:
*
* #define configUSE_TRACE_FACILITY 1
*
* NOTE:
* For IAR Embedded Workbench for ARM, you need to have a preprocessor condition
* on the include, to except it from the assembler step which otherwise give
* compile-time errors.
*
* #ifdef __ICCARM__
* #include "percepio/Include/trcHooks.h"
* #endif
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* 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
*
* Copyright Percepio AB, 2012.
* www.percepio.se
******************************************************************************/
#ifndef TRCHOOKS_H
#define TRCHOOKS_H
#include "trcKernel.h"
#if (configUSE_TRACE_FACILITY == 1)
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
/* Called on each OS tick */
#undef traceTASK_INCREMENT_TICK
#define traceTASK_INCREMENT_TICK( xTickCount ) \
{extern uint32_t uiTraceTickCount; uiTraceTickCount = xTickCount;}
/* Called on each task-switch */
#undef traceTASK_SWITCHED_IN
#define traceTASK_SWITCHED_IN() \
vTraceStoreTaskswitch();
/* Called on vTaskSuspend */
#undef traceTASK_SUSPEND
#define traceTASK_SUSPEND( pxTaskToSuspend ) \
vTraceStoreKernelCall(TASK_SUSPEND, pxTaskToSuspend->uxTaskNumber); \
vTraceSetTaskInstanceFinished((uint8_t)pxTaskToSuspend->uxTaskNumber);
/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */
#undef traceTASK_DELAY
#define traceTASK_DELAY() \
portENTER_CRITICAL(); \
vTraceStoreKernelCallWithNumericParamOnly(TASK_DELAY, (uint16_t)xTicksToDelay);\
vTraceSetTaskInstanceFinished((uint8_t)pxCurrentTCB->uxTaskNumber);\
portEXIT_CRITICAL();
/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */
#undef traceTASK_DELAY_UNTIL
#define traceTASK_DELAY_UNTIL() \
portENTER_CRITICAL(); \
vTraceStoreKernelCallWithNumericParamOnly(TASK_DELAY_UNTIL, (uint16_t)xTimeToWake); \
vTraceSetTaskInstanceFinished((uint8_t)pxCurrentTCB->uxTaskNumber); \
portEXIT_CRITICAL();
#if (INCLUDE_OBJECT_DELETE == 1)
/* Called on vTaskDelete */
#undef traceTASK_DELETE
#define traceTASK_DELETE( pxTaskToDelete ) \
vTraceStoreKernelCall(EVENTGROUP_DELETE + 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);
#endif
/* Called on vTaskCreate */
#undef traceTASK_CREATE
#define traceTASK_CREATE( pxNewTCB ) \
if (pxNewTCB != NULL){ \
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);\
}
/* Called in vTaskCreate, if it fails (typically if the stack fails can not be allocated) */
#undef traceTASK_CREATE_FAILED
#define traceTASK_CREATE_FAILED() \
portENTER_CRITICAL();\
vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK, 0); \
portEXIT_CRITICAL();
/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */
#undef traceQUEUE_CREATE
#define traceQUEUE_CREATE( pxNewQueue )\
portENTER_CRITICAL(); \
pxNewQueue->ucQueueNumber = xTraceGetObjectHandle(TraceObjectClassTable[pxNewQueue->ucQueueType]);\
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); \
portEXIT_CRITICAL();
/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */
#undef traceCREATE_MUTEX
#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); \
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);\
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); \
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); \
if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){\
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (uint8_t)pxQueue->ucQueueNumber, (uint8_t)0); \
}else{\
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (uint8_t)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting + 1)); \
}
/* Called when a message failed to be sent to a queue (timeout) */
#undef traceQUEUE_SEND_FAILED
#define traceQUEUE_SEND_FAILED( pxQueue ) \
portENTER_CRITICAL();\
vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + 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); \
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); \
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 */ \
}else{\
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting - 1)); \
}
/* Called when the task is blocked due to a receive operation on an empty queue */
#undef traceBLOCKING_ON_QUEUE_RECEIVE
#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \
portENTER_CRITICAL(); \
vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
if (TraceObjectClassTable[pxQueue->ucQueueType] != TRACE_CLASS_MUTEX){\
extern volatile void * volatile pxCurrentTCB; \
vTraceSetTaskInstanceFinished((objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxCurrentTCB)); \
}\
portEXIT_CRITICAL();
/* Called on xQueuePeek */
#undef traceQUEUE_PEEK
#define traceQUEUE_PEEK( pxQueue ) \
vTraceStoreKernelCall(EVENTGROUP_PEEK + 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); \
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));
/* 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);
/* 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));
/* 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);
#if (INCLUDE_OBJECT_DELETE == 1)
/* Called on vQueueDelete */
#undef traceQUEUE_DELETE
#define traceQUEUE_DELETE( pxQueue ) \
{ \
portENTER_CRITICAL();\
vTraceStoreKernelCall(EVENTGROUP_DELETE + 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){ \
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxQueue->pxMutexHolder)); \
}else{ \
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)uxQueueMessagesWaiting(pxQueue)); \
} \
vTraceFreeObjectHandle(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber); \
portEXIT_CRITICAL();\
}
#endif
/* 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));\
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));\
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));\
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);
/* Called in vTaskResumeFromISR */
#undef traceTASK_RESUME_FROM_ISR
#define traceTASK_RESUME_FROM_ISR( pxTaskToResume )\
vTraceStoreKernelCall(TASK_RESUME_FROM_ISR, pxTaskToResume->uxTaskNumber);
#endif
#endif

View file

@ -0,0 +1,267 @@
/*******************************************************************************
* FreeRTOS+Trace v2.2.3 Recorder Library
* Percepio AB, www.percepio.se
*
* trcKernel.h
*
* Functions used by trcHooks.h, for the FreeRTOS kernel integration.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* 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
*
* Copyright Percepio AB, 2012.
* www.percepio.se
******************************************************************************/
#ifndef TRCKERNEL_H
#define TRCKERNEL_H
#include "trcTypes.h"
#if (configUSE_TRACE_FACILITY == 1)
#include "trcBase.h"
/* Internal functions */
void vTraceStoreTaskswitch(void);
void vTraceStoreKernelCall(uint32_t eventcode, uint32_t byteParam);
void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode,
uint16_t param);
void vTraceStoreKernelCallWithParam(uint32_t evtcode, uint32_t objectNumber,
uint8_t param);
void vTraceSetTaskInstanceFinished(objectHandleType handle);
void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value);
uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id);
void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value);
uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id);
#if (INCLUDE_OBJECT_DELETE == 1)
void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass);
void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass);
#endif
/* Internal constants for task state */
#define TASK_STATE_INSTANCE_NOT_ACTIVE 0
#define TASK_STATE_INSTANCE_ACTIVE 1
#define TASK_STATE_INSTANCE_MARKED_FINISHED 2
/* This defines the mapping between FreeRTOS queue types and our internal
class IDs */
extern traceObjectClass TraceObjectClassTable[5];
/*******************************************************************************
* The event codes - should match the offline config file.
*
* Some sections below are encoded to allow for constructions like:
*
* vTraceStoreKernelCall(EVENTGROUP_CREATE + objectclass, ...
*
* The object class ID is given by the three LSB bits, in such cases. Since each
* object class has a separate object property table, the class ID is needed to
* know what section in the object table to use for getting an object name from
* an object handle.
******************************************************************************/
#define NULL_EVENT (0x00) /* Ignored in the analysis*/
#define RECORDING_START (0x01) /* Not yet used */
#define RECORDING_STOP (0x02) /* Not yet used */
/*******************************************************************************
* EVENTGROUP_TS
*
* 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 */
/*******************************************************************************
* EVENTGROUP_OBJCLOSE_NAME
*
* About Close Events
* When an object is evicted from the object property table (object close), two
* internal events are stored (EVENTGROUP_OBJCLOSE_NAME and
* EVENTGROUP_OBJCLOSE_PROP), containg the handle-name mapping and object
* properties valid up to this point.
******************************************************************************/
#define EVENTGROUP_OBJCLOSE_NAME (0x08)
/*******************************************************************************
* EVENTGROUP_OBJCLOSE_PROP
*
* The internal event carrying properties of deleted objects
* The handle and object class of the closed object is not stored in this event,
* but is assumed to be the same as in the preceeding CLOSE event. Thus, these
* two events must be generated from within a critical section.
* When queues are closed, arg1 is the "state" property (i.e., number of
* buffered messages/signals).
* When actors are closed, arg1 is priority, arg2 is handle of the "instance
* finish" event, and arg3 is event code of the "instance finish" event.
* In this case, the lower three bits is the object class of the instance finish
* handle. The lower three bits are not used (always zero) when queues are
* closed since the queue type is given in the previous OBJCLOSE_NAME event.
******************************************************************************/
#define EVENTGROUP_OBJCLOSE_PROP (EVENTGROUP_OBJCLOSE_NAME + 8) /*0x10*/
/*******************************************************************************
* EVENTGROUP_CREATE
*
* The events in this group are used to log Kernel object creations.
* The lower three bits in the event code gives the object class, i.e., type of
* create operation (task, queue, semaphore, etc).
******************************************************************************/
#define EVENTGROUP_CREATE (EVENTGROUP_OBJCLOSE_PROP + 8) /*0x18*/
/*******************************************************************************
* EVENTGROUP_SEND
*
* The events in this group are used to log Send/Give events on queues,
* semaphores and mutexeds The lower three bits in the event code gives the
* object class, i.e., what type of object that is operated on (queue, semaphore
* or mutex).
******************************************************************************/
#define EVENTGROUP_SEND (EVENTGROUP_CREATE + 8) /*0x20*/
/*******************************************************************************
* EVENTGROUP_RECEIVE
*
* The events in this group are used to log Receive/Take events on queues,
* semaphores and mutexes. The lower three bits in the event code gives the
* object class, i.e., what type of object that is operated on (queue, semaphore
* or mutex).
******************************************************************************/
#define EVENTGROUP_RECEIVE (EVENTGROUP_SEND + 8) /*0x28*/
/* Send/Give operations, from ISR */
#define EVENTGROUP_SEND_FROM_ISR (EVENTGROUP_RECEIVE + 8) /*0x30*/
/* Receive/Take operations, from ISR */
#define EVENTGROUP_RECEIVE_FROM_ISR (EVENTGROUP_SEND_FROM_ISR + 8) /*0x38*/
/* "Failed" event type versions of above (timeout, failed allocation, etc) */
#define EVENTGROUP_FAILED_KSE (EVENTGROUP_RECEIVE_FROM_ISR + 8) /*0x40*/
/* Failed create calls - memory allocation failed */
#define EVENTGROUP_FAILED_CREATE (EVENTGROUP_FAILED_KSE) /*0x40*/
/* Failed send/give - timeout! */
#define EVENTGROUP_FAILED_SEND (EVENTGROUP_FAILED_CREATE + 8) /*0x48*/
/* Failed receive/take - timeout! */
#define EVENTGROUP_FAILED_RECEIVE (EVENTGROUP_FAILED_SEND + 8) /*0x50*/
/* Failed non-blocking send/give - queue full */
#define EVENTGROUP_FAILED_SEND_FROM_ISR (EVENTGROUP_FAILED_RECEIVE + 8) /*0x58*/
/* Failed non-blocking receive/take - queue empty */
#define EVENTGROUP_FAILED_RECEIVE_FROM_ISR \
(EVENTGROUP_FAILED_SEND_FROM_ISR + 8) /*0x60*/
/* Events when blocking on receive/take */
#define EVENTGROUP_BLOCK_ON_RECEIVE \
(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + 8) /*0x68*/
/* Events when blocking on send/give */
#define EVENTGROUP_BLOCK_ON_SEND (EVENTGROUP_BLOCK_ON_RECEIVE + 8) /*0x70*/
/* Events on queue peek (receive) */
#define EVENTGROUP_PEEK (EVENTGROUP_BLOCK_ON_SEND + 8) /*0x78*/
/* Events on object delete (vTaskDelete or vQueueDelete) */
#define EVENTGROUP_DELETE (EVENTGROUP_PEEK + 8) /*0x80*/
/* 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)
/* Not yet used */
#define EVENTGROUP_FTRACE_PLACEHOLDER (EVENTGROUP_OTHERS + 8) /*0x90*/
/* User events */
#define EVENTGROUP_USEREVENT (EVENTGROUP_FTRACE_PLACEHOLDER + 8) /*0x98*/
#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)
/******************************************************************************
* 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
* in the other events, depending on the bytes available in the event struct.
* If the time since the last event (the DTS) is larger than allowed for by
* the DTS field of the current event, an XTS event is inserted immidiatly
* before the original event. The XTS event contains up to 3 additional bytes
* of the DTS value - the higher bytes of the true DTS value. The lower 1-2
* bytes are stored in the normal DTS field.
* There are two types of XTS events, XTS8 and XTS16. An XTS8 event is stored
* when there is only room for 1 byte (8 bit) DTS data in the original event,
* which means a limit of 0xFF (255). The XTS16 is used when the original event
* has a 16 bit DTS field and thereby can handle values up to 0xFFFF (65535).
*
* Using a very high frequency time base can result in many XTS events.
* Preferably, the time between two OS ticks should fit in 16 bits, i.e.,
* at most 65535. If your time base has a higher frequency, you can define
* the TRACE
******************************************************************************/
#define EVENTGROUP_SYS (EVENTGROUP_USEREVENT + 16) /*0xA8*/
#define XTS8 (EVENTGROUP_SYS + 0) /*0xA8*/
#define XTS16 (EVENTGROUP_SYS + 1) /*0xA9*/
#define EVENT_BEING_WRITTEN (EVENTGROUP_SYS + 2) /*0xAA*/
#define RESERVED_DUMMY_CODE (EVENTGROUP_SYS + 3) /*0xAB*/
#endif
#endif

View file

@ -0,0 +1,59 @@
/*******************************************************************************
* FreeRTOS+Trace v2.2.3 Recorder Library
* Percepio AB, www.percepio.se
*
* trcTypes.h
*
* Data types used by the trace recorder library.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* 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
*
* Copyright Percepio AB, 2012.
* www.percepio.se
******************************************************************************/
#ifndef TRCTYPES_H
#define TRCTYPES_H
#include <stdint.h>
typedef uint16_t traceLabel;
typedef uint8_t objectHandleType;
typedef uint8_t traceObjectClass;
#define TRACE_CLASS_QUEUE ((traceObjectClass)0)
#define TRACE_CLASS_SEMAPHORE ((traceObjectClass)1)
#define TRACE_CLASS_MUTEX ((traceObjectClass)2)
#define TRACE_CLASS_TASK ((traceObjectClass)3)
#define TRACE_CLASS_ISR ((traceObjectClass)4)
#endif

View file

@ -0,0 +1,399 @@
/*******************************************************************************
* FreeRTOS+Trace v2.2.3 Recorder Library
* Percepio AB, www.percepio.se
*
* trcUser.h
* The public API of the trace recorder library.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* 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
*
* Copyright Percepio AB, 2012.
* www.percepio.se
******************************************************************************/
#ifndef TRCUSER_H
#define TRCUSER_H
#include "FreeRTOS.h"
#if (configUSE_TRACE_FACILITY == 1)
#include "trcBase.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* uiTraceStart
*
* Starts the recorder. The recorder will not be started if an error has been
* indicated using vTraceError, e.g. if any of the Nx constants in trcConfig.h
* has a too small value (NTASK, NQUEUE, etc).
*
* Returns 1 if the recorder was started successfully.
* Returns 0 if the recorder start was prevented due to a previous internal
* error. In that case, check vTraceGetLastError to get the error message.
* Any error message is also presented when opening a trace file in
* FreeRTOS+Trace v2.2.2 or later.
******************************************************************************/
uint32_t uiTraceStart(void);
/*******************************************************************************
* vTraceStart
*
* Starts the recorder. The recorder will not be started if an error has been
* indicated using vTraceError, e.g. if any of the Nx constants in trcConfig.h
* has a too small value (NTASK, NQUEUE, etc).
*
* This function is obsolete, but has been saved for backwards compatibility.
* We recommend using uiTraceStart instead.
******************************************************************************/
void vTraceStart(void);
/*******************************************************************************
* vTraceStartStatusMonitor
*
* This starts a task to monitor the status of the recorder module.
* This task periodically prints a line to the console window, which shows the
* recorder status, the number of events recorded and the latest timestamp.
* This task calls vTracePortEnd (trcPort.c) when it detects that the recorder
* has been stopped. This allows for adding custom actions, e.g., to store the
* trace to a file in case a file system is available on the device.
******************************************************************************/
void vTraceStartStatusMonitor(void);
/*******************************************************************************
* vTraceStop
*
* Stops the recorder. The recording can be resumed by calling vTraceStart.
* This does not reset the recorder. Use vTraceClear is that is desired.
******************************************************************************/
void vTraceStop(void);
/*******************************************************************************
* vTraceClear
*
* Resets the recorder. Only necessary if a restart is desired - this is not
* needed in the startup initialization.
******************************************************************************/
void vTraceClear(void);
/*******************************************************************************
* vTraceSetQueueName
*
* Assigns a name to a FreeRTOS Queue, Semaphore or Mutex. This function should
* be called right after creation of the queue/mutex/semaphore. If not using
* this function, the queues/mutexes/semaphores will be presented by their
* numeric handle only.
*
* Example:
* actuatorQ = xQueueCreate(3, sizeof(QueueMessage));
* vTraceSetQueueName(actuatorQ, "ActuatorQueue");
******************************************************************************/
void vTraceSetQueueName(void* queue, const char* name);
#if (INCLUDE_ISR_TRACING == 1)
/*******************************************************************************
* vTraceSetISRProperties
*
* Registers an Interrupt Service Routine in the recorder library, This must be
* called before using vTraceStoreISRBegin to store ISR events. This is
* typically called in the startup of the system, before the scheduler is
* started.
*
* Example:
* #define ID_ISR_TIMER1 1 // lowest valid ID is 1
* #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
* ...
* vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);
* ...
* void ISR_handler()
* {
* portENTER_CRITICAL(); // Required if nested ISRs are allowed
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
* portEXIT_CRITICAL();
* ...
* portENTER_CRITICAL(); // Required if nested ISRs are allowed
* vTraceStoreISREnd();
* portEXIT_CRITICAL();
* }
******************************************************************************/
void vTraceSetISRProperties(objectHandleType handle, char* name, char priority);
/*******************************************************************************
* vTraceStoreISRBegin
*
* Registers the beginning of an Interrupt Service Routine. This must not be
* interrupted by another ISR containing recorder library calls, so if allowing
* nested ISRs this must be called with interrupts disabled.
*
* Example:
* #define ID_ISR_TIMER1 1 // lowest valid ID is 1
* #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
* ...
* vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);
* ...
* void ISR_handler()
* {
* portENTER_CRITICAL(); // Required if nested ISRs are allowed
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
* portEXIT_CRITICAL();
* ...
* portENTER_CRITICAL(); // Required if nested ISRs are allowed
* vTraceStoreISREnd();
* portEXIT_CRITICAL();
* }
******************************************************************************/
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.
*
* Example:
* #define ID_ISR_TIMER1 1 // lowest valid ID is 1
* #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
* ...
* vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);
* ...
* void ISR_handler()
* {
* portENTER_CRITICAL(); // Required if nested ISRs are allowed
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
* portEXIT_CRITICAL();
* ...
* portENTER_CRITICAL(); // Required if nested ISRs are allowed
* vTraceStoreISREnd();
* portEXIT_CRITICAL();
* }
******************************************************************************/
void vTraceStoreISREnd(void);
#else
/* If not including the ISR recording */
#define vTraceSetISRProperties(handle, name, priority)
#define vTraceStoreISRBegin(id)
#define vTraceStoreISREnd()
#endif
/*******************************************************************************
* vvTraceTaskSkipDefaultInstanceFinishedEvents
*
* This is useful if there are implicit Instance Finish Events, such as
* vTaskDelayUntil or xQueueReceive, in a task where an explicit Instance Finish
* Event has been defined. This function tells the recorder that only the
* explicitly defined functions (using vTraceTaskInstanceIsFinished) should be
* treated as Instance Finish Events for this task. The implicit Instance Finish
* Events are thus disregarded for this task.
******************************************************************************/
void vTraceTaskSkipDefaultInstanceFinishedEvents(void);
/*******************************************************************************
* vTraceTaskInstanceIsFinished
*
* This defines an explicit Instance Finish Event for the current task. It tells
* the recorder that the current instance of this task is finished at the next
* kernel call of the task, e.g., a taskDelay or a queue receive. This function
* should be called right before the api function call considered to be the end
* of the task instamce, i.e., the Instance Finish Event.
******************************************************************************/
void vTraceTaskInstanceIsFinished(void);
/*******************************************************************************
* vTraceGetTraceBuffer
*
* Returns a pointer to the recorder data structure. Use this together with
* uiTraceGetTraceBufferSize if you wish to implement an own store/upload
* solution, e.g., in case a debugger connection is not available for uploading
* the data.
******************************************************************************/
void* vTraceGetTraceBuffer(void);
/*******************************************************************************
* uiTraceGetTraceBufferSize
*
* Gets the size of the recorder data structure. For use together with
* vTraceGetTraceBuffer if you wish to implement an own store/upload solution,
* e.g., in case a debugger connection is not available for uploading the data.
******************************************************************************/
uint32_t uiTraceGetTraceBufferSize(void);
#if (INCLUDE_USER_EVENTS == 1)
/*******************************************************************************
* xTraceOpenLabel
*
* Creates user event labels for user event channels or for individual events.
* User events can be used to log application events and data for display in
* the visualization tool. A user event is identified by a label, i.e., a string,
* which is stored in the recorder's symbol table.
* When logging a user event, a numeric handle (reference) to this string is
* used to identify the event. This is obtained by calling
*
* xTraceOpenLabel()
*
* whihc adds the string to the symbol table (if not already present)
* and returns the corresponding handle.
*
* This can be used in two ways:
*
* 1. The handle is looked up every time, when storing the user event.
*
* Example:
* vTraceUserEvent(xTraceOpenLabel("MyUserEvent"));
*
* 2. The label is registered just once, with the handle stored in an
* application variable - much like using a file handle.
*
* Example:
* myEventHandle = xTraceOpenLabel("MyUserEvent");
* ...
* vTraceUserEvent(myEventHandle);
*
* The second option is faster since no lookup is required on each event, and
* therefore recommended for user events that are frequently
* 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);
/******************************************************************************
* vTraceUserEvent
*
* Basic user event (Standard and Professional Edition only)
*
* Generates a User Event with a text label. The label is created/looked up
* in the symbol table using xTraceOpenLabel.
******************************************************************************/
void vTraceUserEvent(traceLabel eventLabel);
/******************************************************************************
* vTracePrintF
*
* Advanced user events (Professional Edition only)
*
* Generates User Event with formatted text and data, similar to a "printf".
* It is very fast compared to a normal "printf" since this function only
* stores the arguments. The actual formatting is done
* on the host PC when the trace is displayed in the viewer tool.
*
* User Event labels are created using xTraceOpenLabel.
* Example:
*
* traceLabel adc_uechannel = xTraceOpenLabel("ADC User Events");
* ...
* vTracePrint(adc_uechannel,
* "ADC channel %d: %lf volts",
* ch, (double)adc_reading/(double)scale);
*
* This can be combined into one line, if desired, but this is slower:
*
* vTracePrint(xTraceOpenLabel("ADC User Events"),
* "ADC channel %d: %lf volts",
* ch, (double)adc_reading/(double)scale);
*
* Calling xTraceOpenLabel multiple times will not create duplicate entries, but
* it is of course faster to just do it once, and then keep the handle for later
* use. If you don´t have any data arguments, only a text label/string, it is
* better to use vTraceUserEvent - it is faster.
*
* Format specifiers supported:
* %d - 32 bit signed integer
* %u - 32 bit unsigned integer
* %f - 32 bit float
* %s - string (is copied to the recorder symbol table)
* %hd - 16 bit signed integer
* %hu - 16 bit unsigned integer
* %bd - 8 bit signed integer
* %bu - 8 bit unsigned integer
* %lf - double-precision float
*
* 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.
******************************************************************************/
void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...);
#else
#define vTracePrintF(eventLabel, formatStr, ...);
#define xTraceOpenLabel(label) 0
#define vTraceUserEvent(eventLabel)
#endif
/******************************************************************************
* vTraceExcludeTask
*
* Excludes a task from the recording using a flag in the Object Property Table.
* This can be useful if some irrelevant task is very frequent and is "eating
* up the buffer". This should be called the task has been created, but
* before starting the FreeRTOS scheduler.
*****************************************************************************/
void vTraceExcludeTaskFromSchedulingTrace(const char* name);
#ifdef __cplusplus
}
#endif
#else
#include "trcPort.h"
#define vTraceInit()
#define vTraceStart()
#define vTraceStop()
#define vTraceClear()
#define vTraceGetTraceBuffer() ((void*)0)
#define uiTraceGetTraceBufferSize() 0
#define xTraceOpenLabel(label) 0
#define vTraceUserEvent(eventLabel)
#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

View file

@ -0,0 +1,40 @@
FreeRTOS+Trace Demo
-------------------
Percepio AB
www.percepio.se
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 that the individual Demo project directories are not self-contained.
They refer to the FreeRTOS-v7.1.1, DemoAppl and TraceRecorderSrc directories.
Hardware Timer Ports
--------------------
This release contains hardware timer ports for the following hardware architectures:
- ARM Cortex M3/M4 (all brands)
- Atmel AT91SAM7X
- Renesas RX600
The package moreover contain several "unofficial" ports, provided by external contributors and not yet verified by Percepio AB.
See trcPort.h for the details.
In case your hardware is not yet directly supported, developing a new port is quite easy.
See trcPort.h for further information.
In case you have any questions, do not hesitate to contact support@percepio.se
Percepio AB
Köpmangatan 1A
72215 Västerås
Sweden
www.percepio.se

View file

@ -0,0 +1,977 @@
/*******************************************************************************
* FreeRTOS+Trace v2.2.3 Recorder Library
* Percepio AB, www.percepio.se
*
* trcBase.c
*
* Core functionality of the trace recorder library.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* 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
*
* Copyright Percepio AB, 2012.
* www.percepio.se
******************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "trcBase.h"
#include "trcKernel.h"
#include "trcUser.h"
#if (configUSE_TRACE_FACILITY == 1)
/*******************************************************************************
* Static data initializations
******************************************************************************/
/*******************************************************************************
* RecorderData
*
* The main data structure. This is the data read by FreeRTOS+Trace, typically
* through a debugger RAM dump. This is accessed through RecorderDataPtr.
*
* 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.
*
* #pragma location="AHB_RAM_MEMORY"
* RecorderDataType RecorderData = ...
*
* 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.
*
* If using GCC, this is done by adding a "section" attribute:
*
* RecorderDataType RecorderData __attribute__ ((section ("name"))) = ...
*
* Remember to replace "name" with the correct section name.
******************************************************************************/
#if (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_STATIC)
RecorderDataType RecorderData =
{
/* start marker, 12 chars */
0x01, 0x02, 0x03, 0x04,
0x71, 0x72, 0x73, 0x74,
0xF1, 0xF2, 0xF3, 0xF4,
/* version code - also used to determine endianness */
VERSION,
/* minor file format version */
MINOR_VERSION,
/* irq priority order */
IRQ_PRIORITY_ORDER,
/* file size (for control) */
sizeof(RecorderDataType),
/* number of events stored so far */
0,
/* size of events buffer (in event records, each 4 bytes) */
EVENT_BUFFER_SIZE,
/* next free event index (event index, not byte address) */
0,
/* buffer is full */
0,
/* frequency of clock user for timestamps, in Hz - should be 0 here
as this is used to indicate "not yet initialized" - this is instead
initialized on the first taskswitch event. */
0,
/* the absolute timestamp of the last stored event, modulo frequency */
0,
/* the number of seconds so far */
0,
/* is recorder active (yes = 1) - note that "close" events are always
stored to keep the name-handle mapping updated!*/
0,
/* Generated by FreeRTOS+Trace in Team Admin mode. Otherwise this should be "". */
TEAM_LICENSE_CODE,
/* debug marker 0 */
0xF0F0F0F0,
/* The Object Property Table - holds info of all active objects */
{
/* Number of object classes, also those not used */
NCLASSES,
/* The size in bytes of the object table byte pool */
DynObjTableSize,
/* The number of slots/handles available for each class */
{
NQueue,
NSemaphore,
NMutex,
NTask,
NISR
},
/* The maximum name length for each object class */
{
NameLenQueue,
NameLenSemaphore,
NameLenMutex,
NameLenTask,
NameLenISR
},
/* The total length a property table entry of the class */
{
PropertyTableSizeQueue,
PropertyTableSizeSemaphore,
PropertyTableSizeMutex,
PropertyTableSizeTask,
PropertyTableSizeISR
},
/* The start index of each class in the object property table */
{
StartIndexQueue,
StartIndexSemaphore,
StartIndexMutex,
StartIndexTask,
StartIndexISR
},
/* the object property table - encoded in a byte array using above
definitions */
{0}
},
/* debug marker 1 */
0xF1F1F1F1,
/* The Symbol Table - holds all object names used since system
startup. Every string is unique, so objects with same name will share
an entry. Each name entry has four extra bytes: byte 0-1 is a link
reference in an internal linked list, used for fast lookups, byte 2-3
holds a reference to a channel label used for vTracePrintF format
strings, and byte 4.. holds the object name, followed by a
zero-termination.*/
{
SYMBOL_TABLE_SIZE,
/* next free index (0 is reserved to mean NULL) */
1,
/* the symbol table byte pool */
{0},
/* this is a 64 entry array holding 16-bit references (indexes)
to the most recent entry of each checksum - i.e., list heads.*/
{0},
},
#if (INCLUDE_FLOAT_SUPPORT == 1)
/* example float, for float endian detection */
(float)1.0,
#else
/* This code signals that no float support is included */
(uint32_t)0,
#endif
/* internalErrorOccured */
0,
/* debug marker 2 */
0xF2F2F2F2,
/* The trace description string, can hold any information about the system,
e.g., version, configuration. Error messages from the recorder are
copied to this buffer. Also used for internal error messages.*/
TRACE_DESCRIPTION,
/* debug marker 3 */
0xF3F3F3F3,
/* the event data buffer, size EVENT_BUFFER_SIZE*4 */
{0},
/* end markers, used to extract the trace from a RAM dump image */
0x0A, 0x0B, 0x0C, 0x0D,
0x71, 0x72, 0x73, 0x74,
0xF1, 0xF2, 0xF3, 0xF4
};
RecorderDataType* RecorderDataPtr = &RecorderData;
#endif
#if (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_DYNAMIC)
RecorderDataType* RecorderDataPtr = NULL;
RecorderDataType* xTraceInitTraceData(void)
{
RecorderDataType* tmp = (RecorderDataType*)pvPortMalloc(sizeof(RecorderDataType));
if (! tmp)
{
vTraceError("Malloc failed in xTraceInitTraceData! Reduce size constants in trcConfig.h");
return NULL;
}
(void)memset(tmp, 0, sizeof(RecorderDataType));
tmp->startmarker0 = 0x01;
tmp->startmarker1 = 0x02;
tmp->startmarker2 = 0x03;
tmp->startmarker3 = 0x04;
tmp->startmarker4 = 0x71;
tmp->startmarker5 = 0x72;
tmp->startmarker6 = 0x73;
tmp->startmarker7 = 0x74;
tmp->startmarker8 = 0xF1;
tmp->startmarker9 = 0xF2;
tmp->startmarker10 = 0xF3;
tmp->startmarker11 = 0xF4;
tmp->version = VERSION;
tmp->minor_version = MINOR_VERSION;
tmp->irq_priority_order = IRQ_PRIORITY_ORDER;
tmp->filesize = sizeof(RecorderDataType);
tmp->maxEvents = EVENT_BUFFER_SIZE;
tmp->debugMarker0 = 0xF0F0F0F0;
tmp->ObjectPropertyTable.NumberOfObjectClasses = NCLASSES;
tmp->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = DynObjTableSize;
tmp->ObjectPropertyTable.NumberOfObjectsPerClass[0] = NQueue;
tmp->ObjectPropertyTable.NumberOfObjectsPerClass[1] = NSemaphore;
tmp->ObjectPropertyTable.NumberOfObjectsPerClass[2] = NMutex;
tmp->ObjectPropertyTable.NumberOfObjectsPerClass[3] = NTask;
tmp->ObjectPropertyTable.NumberOfObjectsPerClass[4] = NISR;
tmp->ObjectPropertyTable.NameLengthPerClass[0] = NameLenQueue;
tmp->ObjectPropertyTable.NameLengthPerClass[1] = NameLenSemaphore;
tmp->ObjectPropertyTable.NameLengthPerClass[2] = NameLenMutex;
tmp->ObjectPropertyTable.NameLengthPerClass[3] = NameLenTask;
tmp->ObjectPropertyTable.NameLengthPerClass[4] = NameLenISR;
tmp->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;
tmp->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;
tmp->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;
tmp->ObjectPropertyTable.TotalPropertyBytesPerClass[3] = PropertyTableSizeTask;
tmp->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;
tmp->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;
tmp->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;
tmp->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;
tmp->ObjectPropertyTable.StartIndexOfClass[3] = StartIndexTask;
tmp->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;
tmp->debugMarker1 = 0xF1F1F1F1;
tmp->SymbolTable.symTableSize = SYMBOL_TABLE_SIZE;
tmp->SymbolTable.nextFreeSymbolIndex = 1;
#if (INCLUDE_FLOAT_SUPPORT == 1)
tmp->exampleFloatEncoding = (float)1.0; /* otherwize already zero */
#endif
tmp->debugMarker2 = 0xF2F2F2F2;
(void)strncpy(tmp->systemInfo, TRACE_DESCRIPTION, TRACE_DESCRIPTION_MAX_LENGTH);
tmp->debugMarker3 = 0xF3F3F3F3;
tmp->endmarker0 = 0x0A;
tmp->endmarker1 = 0x0B;
tmp->endmarker2 = 0x0C;
tmp->endmarker3 = 0x0D;
tmp->endmarker4 = 0x71;
tmp->endmarker5 = 0x72;
tmp->endmarker6 = 0x73;
tmp->endmarker7 = 0x74;
tmp->endmarker8 = 0xF1;
tmp->endmarker9 = 0xF2;
tmp->endmarker10 = 0xF3;
tmp->endmarker11 = 0xF4;
RecorderDataPtr = tmp;
return (RecorderDataType*)RecorderDataPtr;
}
#endif
char sprintfBuffer[150];
/* For debug printouts - the names of the object classes */
char OBJECTCLASSNAME[NCLASSES][10] =
{
"QUEUE",
"SEMAPHORE",
"MUTEX",
"TASK",
"ISR"
};
/* Initialization of the handle mechanism, see e.g, xTraceGetObjectHandle */
objectHandleStackType objectHandleStacks =
{
/* indexOfNextAvailableHandle */
{
0,
NQueue,
NQueue + NSemaphore,
NQueue + NSemaphore + NMutex,
NQueue + NSemaphore + NMutex + NTask
},
/* lowestIndexOfClass */
{
0,
NQueue,
NQueue + NSemaphore,
NQueue + NSemaphore + NMutex,
NQueue + NSemaphore + NMutex + NTask
},
/* highestIndexOfClass */
{
NQueue - 1,
NQueue + NSemaphore - 1,
NQueue + NSemaphore + NMutex - 1,
NQueue + NSemaphore + NMutex + NTask - 1,
NQueue + NSemaphore + NMutex + NTask + NISR - 1
},
{0},
{0}
};
/* Used for internal state flags of tasks */
uint8_t taskFlags[NTask];
/* 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)
{
vTraceError("Attempt to index outside event buffer!");
return NULL;
}
return (void*)(&RecorderDataPtr->
eventData[RecorderDataPtr->nextFreeIndex*4]);
}
uint32_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass)
{
if ((objectclass < NCLASSES) && (objecthandle > 0) && (objecthandle <=
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass]))
{
return (uint32_t)(RecorderDataPtr->
ObjectPropertyTable.StartIndexOfClass[objectclass] +
(RecorderDataPtr->
ObjectPropertyTable.TotalPropertyBytesPerClass[objectclass] *
(objecthandle-1)));
}
vTraceError("Object table lookup with invalid object handle or object class!");
return 0;
}
/*******************************************************************************
* Object handle system
* This provides a mechanism to assign each kernel object (tasks, queues, etc)
* with a 1-byte handle, that is used to identify the object in the trace.
* This way, only one byte instead of four is necessary to identify the object.
* This allows for maximum 255 objects, of each object class, active at any
* moment.
* Note that zero is reserved as an error code and is not a valid handle.
*
* In order to allow for fast dynamic allocation and release of object handles,
* the handles of each object class (e.g., TASK) are stored in a stack. When a
* handle is needed, e.g., on task creation, the next free handle is popped from
* the stack. When an object (e.g., task) is deleted, its handle is pushed back
* on the stack and can thereby be reused for other objects.
*
* Since this allows for reuse of object handles, a specific handle (e.g, "8")
* may refer to TASK_X at one point, and later mean "TASK_Y". To resolve this,
* the recorder uses "Close events", which are stored in the main event buffer
* when objects are deleted and their handles are released. The close event
* contains the mapping between object handle and object name which was valid up
* to this point in time. The object name is stored as a symbol table entry.
******************************************************************************/
objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass)
{
static objectHandleType handle;
static uint32_t indexOfHandle;
indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass];
if (objectHandleStacks.objectHandles[indexOfHandle] == 0)
{
/* Zero is used to indicate a never before used handle, i.e.,
new slots in the handle stack. The handle slot needs to
be initialized here (starts at 1). */
objectHandleStacks.objectHandles[indexOfHandle] =
(objectHandleType)(1 + indexOfHandle -
objectHandleStacks.lowestIndexOfClass[objectclass]);
}
handle = objectHandleStacks.objectHandles[indexOfHandle];
if ( objectHandleStacks.indexOfNextAvailableHandle[objectclass]
> objectHandleStacks.highestIndexOfClass[objectclass] )
{
/* ERROR */
switch(objectclass)
{
case TRACE_CLASS_TASK:
vTraceError("Not enough TASK handles - increase NTask in trcConfig.h");
break;
case TRACE_CLASS_ISR:
vTraceError("Not enough ISR handles - increase NISR in trcConfig.h");
break;
case TRACE_CLASS_SEMAPHORE:
vTraceError("Not enough SEMAPHORE handles - increase NSemaphore in trcConfig.h");
break;
case TRACE_CLASS_MUTEX:
vTraceError("Not enough MUTEX handles - increase NMutex in trcConfig.h");
break;
case TRACE_CLASS_QUEUE:
vTraceError("Not enough QUEUE handles - increase NQueue in trcConfig.h");
break;
}
handle = 0; /* an invalid/anonymous handle - but the recorder is stopped now... */
}
else
{
int32_t hndCount;
objectHandleStacks.indexOfNextAvailableHandle[objectclass]++;
hndCount = objectHandleStacks.indexOfNextAvailableHandle[objectclass] -
objectHandleStacks.lowestIndexOfClass[objectclass];
if (hndCount >
objectHandleStacks.handleCountWaterMarksOfClass[objectclass])
{
objectHandleStacks.handleCountWaterMarksOfClass[objectclass] =
(objectHandleType)hndCount;
}
}
return handle;
}
void vTraceFreeObjectHandle(traceObjectClass objectclass, objectHandleType handle)
{
uint32_t indexOfHandle;
/* Check that there is room to push the handle on the stack */
if ( (objectHandleStacks.indexOfNextAvailableHandle[objectclass] - 1) <
objectHandleStacks.lowestIndexOfClass[objectclass] )
{
/* Error */
vTraceError("Attempt to free more handles than allocated! (duplicate xTaskDelete or xQueueDelete?)");
}
else
{
objectHandleStacks.indexOfNextAvailableHandle[objectclass]--;
indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass];
objectHandleStacks.objectHandles[indexOfHandle] = handle;
}
}
/*******************************************************************************
* Objects Property Table
*
* This holds the names and properties of the currently active objects, such as
* tasks and queues. This is developed to support "dynamic" objects which might
* be deleted during runtime. Their handles are only valid during their
* lifetime, i.e., from create to delete, as they might be reused on later
* create operations. When an object is deleted from the OPT, its data is moved
* to the trace buffer and/or the symbol table.
* When an object (task, queue, etc.) is created, it receives a handle, which
* together with the object class specifies its location in the OPT. Thus,
* objects of different types may share the same name and/or handle, but still
* be independent objects.
******************************************************************************/
/*******************************************************************************
* vTraceSetObjectName
*
* Registers the names of queues, semaphores and other kernel objects in the
* recorder's Object Property Table, at the given handle and object class.
******************************************************************************/
void vTraceSetObjectName(traceObjectClass objectclass,
objectHandleType handle,
const char* name)
{
static uint32_t idx;
if (handle == 0)
{
vTraceError("Illegal handle (0) in vTraceSetObjectName.");
return;
}
switch(objectclass)
{
case TRACE_CLASS_TASK:
case TRACE_CLASS_ISR:
case TRACE_CLASS_SEMAPHORE:
case TRACE_CLASS_MUTEX:
case TRACE_CLASS_QUEUE:
break;
default:
vTraceError("Illegal object class in vTraceSetObjectName");
break;
}
if (handle >
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass])
{
switch(objectclass)
{
case TRACE_CLASS_TASK:
vTraceError("Not enough TASK handles - increase NTask in trcConfig.h");
break;
case TRACE_CLASS_ISR:
vTraceError("Not enough ISR handles - increase NISR in trcConfig.h");
break;
case TRACE_CLASS_SEMAPHORE:
vTraceError("Not enough SEMAPHORE handles - increase NSemaphore in trcConfig.h");
break;
case TRACE_CLASS_MUTEX:
vTraceError("Not enough MUTEX handles - increase NMutex in trcConfig.h");
break;
case TRACE_CLASS_QUEUE:
vTraceError("Not enough QUEUE handles - increase NQueue in trcConfig.h");
break;
}
}
else
{
idx = uiIndexOfObject(handle, objectclass);
if (traceErrorMessage == NULL)
{
(void)strncpy((char*)&(RecorderDataPtr->ObjectPropertyTable.objbytes[idx]),
name,
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ objectclass ] );
}
}
}
traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel)
{
static uint16_t result;
static uint8_t len;
static uint8_t crc;
len = 0;
crc = 0;
prvTraceGetChecksum(name, &crc, &len);
taskENTER_CRITICAL();
result = prvTraceLookupSymbolTableEntry(name, crc, len, userEventChannel);
if (!result)
{
result = prvTraceCreateSymbolTableEntry(name, crc, len, userEventChannel);
}
taskEXIT_CRITICAL();
return result;
}
/*******************************************************************************
* Supporting functions
******************************************************************************/
/*******************************************************************************
* vTraceError
*
* 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.
* If you are not using the monitor task, you may use xTraceGetLastError()
* from your application to check if the recorder is OK.
*
* Note: If a recorder error is registered before vTraceStart is called, the
* 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)
{
vTraceStop();
if (traceErrorMessage == NULL)
{
traceErrorMessage = msg;
(void)strncpy(RecorderDataPtr->systemInfo,
traceErrorMessage,
TRACE_DESCRIPTION_MAX_LENGTH);
RecorderDataPtr->internalErrorOccured = 1;
}
}
/******************************************************************************
* prvCheckDataToBeOverwrittenForMultiEntryUserEvents
*
* This checks if the next event to be overwritten is a multi-entry user event,
* i.e., a USER_EVENT followed by data entries.
* Such data entries do not have an event code at byte 0, as other events.
* All 4 bytes are user data, so the first byte of such data events must
* not be interpreted as type field. The number of data entries following
* a USER_EVENT is given in the event code of the USER_EVENT.
* Therefore, when overwriting a USER_EVENT (when using in ringbuffer mode)
* any data entries following must be replaced with NULL events (code 0).
*
* This is assumed to execute within a critical section...
*****************************************************************************/
void prvCheckDataToBeOverwrittenForMultiEntryUserEvents(
uint32_t nofEntriesToCheck)
{
uint32_t i = 0, 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)
{
(void)memset(& RecorderDataPtr->eventData[e*4], 0, 4 + 4 * nDataEvents);
}
}
i++;
}
}
/*******************************************************************************
* prvTraceUpdateCounters
*
* Updates the index of the event buffer.
******************************************************************************/
void prvTraceUpdateCounters(void)
{
if (RecorderDataPtr->recorderActive == 0)
{
return;
}
#if (INCLUDE_EVENT_STATS == 1)
eventCount[RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex*4]]++;
#endif
RecorderDataPtr->numEvents++;
RecorderDataPtr->nextFreeIndex++;
if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE)
{
#if (RECORDER_STORE_MODE == STORE_MODE_RING_BUFFER)
RecorderDataPtr->bufferIsFull = 1;
RecorderDataPtr->nextFreeIndex = 0;
#else
vTraceStop();
#endif
}
#if (RECORDER_STORE_MODE == STORE_MODE_RING_BUFFER)
prvCheckDataToBeOverwrittenForMultiEntryUserEvents(1);
#endif
#ifdef STOP_AFTER_N_EVENTS
#if (STOP_AFTER_N_EVENTS > -1)
if (RecorderDataPtr->numEvents >= STOP_AFTER_N_EVENTS)
{
vTraceStop();
}
#endif
#endif
}
/******************************************************************************
* prvTraceGetDTS
*
* Returns a differential timestamp (DTS), i.e., the time since
* last event, and creates an XTS event if the DTS does not fit in the
* number of bits given. The XTS event holds the MSB bytes of the DTS.
*
* 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)
{
XTSEvent* xts;
int32_t dts = 0;
uint32_t old_ts = RecorderDataPtr->absTimeLastEvent;
if (RecorderDataPtr->frequency == 0)
{
/* If HWTC_PERIOD is mapped to the timer reload register,
such as in the Cortex M port, it is not initialized before
FreeRTOS has been started. We therefore store the frequency
of the timer at the first timestamped event after the
scheduler has started. (Note that this function is called
also by vTraceStart and uiTraceStart, which might be
called before the scheduler has been started.) */
#if (SELECTED_PORT == PORT_Win32)
RecorderDataPtr->frequency = 100000;
#elif (SELECTED_PORT == PORT_HWIndependent)
RecorderDataPtr->frequency = configTICK_RATE_HZ;
#else
if (xTaskGetSchedulerState() != 0) /* Has the scheduler started? */
{
RecorderDataPtr->frequency =
HWTC_PERIOD * configTICK_RATE_HZ / 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.
**************************************************************************/
if (RecorderDataPtr->frequency > 0)
{
RecorderDataPtr->absTimeLastEvent =
uiTracePortGetTimeStamp() % RecorderDataPtr->frequency;
}
else
{
/* 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();
}
dts = (int32_t)(RecorderDataPtr->absTimeLastEvent - old_ts);
if (dts < 0) /* when the modulo operation wraps around (after 1 second) */
{
if (RecorderDataPtr->frequency == 0)
{
/* 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;
}
dts = (int32_t)(RecorderDataPtr->frequency - old_ts + RecorderDataPtr->absTimeLastEvent);
/* This is good for 136 years (incremented every 1 second) */
RecorderDataPtr->absTimeLastEventSecond++;
}
/* If the dts (time since last event) does not fit in event->dts (only 8 or 16 bits) */
if (dts > (int32_t)param_maxDTS)
{
/* Create an XTS event (eXtended TimeStamp) containing the higher dts bits*/
xts = (XTSEvent*) xTraceNextFreeEventBufferSlot();
if (xts != NULL)
{
if (param_maxDTS == 0xFFFF)
{
xts->type = XTS16;
xts->xts_16 = (uint16_t)((dts / 0x10000) & 0xFFFF);
xts->xts_8 = 0;
}
else if (param_maxDTS == 0xFF)
{
xts->type = XTS8;
xts->xts_16 = (uint16_t)((dts / 0x100) & 0xFFFF);
xts->xts_8 = (uint8_t)((dts / 0x1000000) & 0xFF);
}
else
{
vTraceError("Bad param_maxDTS in prvTraceGetDTS");
}
prvTraceUpdateCounters();
}
}
return dts % (param_maxDTS + 1);
}
/*******************************************************************************
* prvTraceLookupSymbolTableEntry
*
* Find an entry in the symbol table, return 0 if not present.
*
* The strings are stored in a byte pool, with four bytes of "meta-data" for
* every string.
* byte 0-1: index of next entry with same checksum (for fast lookup).
* byte 2-3: reference to a symbol table entry, a label for vTracePrintF
* format strings only (the handle of the destination channel).
* byte 4..(4 + length): the string (object name or user event label), with
* zero-termination
******************************************************************************/
traceLabel prvTraceLookupSymbolTableEntry(const char* name,
uint8_t crc6,
uint8_t len,
traceLabel chn)
{
uint16_t i = RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ];
while (i != 0)
{
if (RecorderDataPtr->SymbolTable.symbytes[i + 2] == (chn & 0x00FF))
{
if (RecorderDataPtr->SymbolTable.symbytes[i + 3] == (chn / 0x100))
{
if (RecorderDataPtr->SymbolTable.symbytes[i + 4 + len] == '\0')
{
if (strncmp((char*)(& RecorderDataPtr->SymbolTable.symbytes[i + 4]), name, len) == 0)
{
break; /* found */
}
}
}
}
i = (uint16_t)(RecorderDataPtr->SymbolTable.symbytes[i] + (RecorderDataPtr->SymbolTable.symbytes[i + 1] * 0x100));
}
return i;
}
/*******************************************************************************
* prvTraceCreateSymbolTableEntry
*
* Creates an entry in the symbol table, independent if it exists already.
*
* The strings are stored in a byte pool, with four bytes of "meta-data" for
* every string.
* byte 0-1: index of next entry with same checksum (for fast lookup).
* byte 2-3: reference to a symbol table entry, a label for vTracePrintF
* format strings only (the handle of the destination channel).
* byte 4..(4 + length): the string (object name or user event label), with
* zero-termination
******************************************************************************/
uint16_t prvTraceCreateSymbolTableEntry(const char* name,
uint8_t crc6,
uint8_t len,
traceLabel channel)
{
uint16_t ret = 0;
if (RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + len + 4 >= SYMBOL_TABLE_SIZE)
{
vTraceError("Symbol table full. Increase SYMBOL_TABLE_SIZE in trcConfig.h");
ret = 0;
}
else
{
RecorderDataPtr->SymbolTable.symbytes
[ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex] =
(uint8_t)(RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ] & 0x00FF);
RecorderDataPtr->SymbolTable.symbytes
[ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 1] =
(uint8_t)(RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ] / 0x100);
RecorderDataPtr->SymbolTable.symbytes
[ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 2] =
(uint8_t)(channel & 0x00FF);
RecorderDataPtr->SymbolTable.symbytes
[ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 3] =
(uint8_t)(channel / 0x100);
/* set name (bytes 4...4+len-1) */
(void)strncpy((char*)&( RecorderDataPtr->SymbolTable.symbytes
[ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 4] ), name, len);
/* Set zero termination (at offest 4+len) */
RecorderDataPtr->SymbolTable.symbytes
[RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 4 + len] = '\0';
/* store index of entry (for return value, and as head of LL[crc6]) */
RecorderDataPtr->SymbolTable.latestEntryOfChecksum
[ crc6 ] = (uint16_t)RecorderDataPtr->SymbolTable.nextFreeSymbolIndex;
RecorderDataPtr->SymbolTable.nextFreeSymbolIndex += (len + 5);
ret = (uint16_t)(RecorderDataPtr->SymbolTable.nextFreeSymbolIndex -
(len + 5));
}
return ret;
}
/*******************************************************************************
* prvTraceGetChecksum
*
* Calculates a simple 6-bit checksum from a string, used to index the string
* for fast symbol table lookup.
******************************************************************************/
void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength)
{
char c;
int32_t length = 0;
int32_t crc = 0;
if ( pname != (const char *) 0 )
{
for ( ; (c = *pname++) != '\0'; )
{
crc += (int32_t)c;
length++;
}
}
*pcrc = (uint8_t)(crc % 64);
*plength = (uint8_t)length;
}
#endif

View file

@ -0,0 +1,374 @@
/*******************************************************************************
* FreeRTOS+Trace v2.2.3 Recorder Library
* Percepio AB, www.percepio.se
*
* trcKernel.c
*
* Functions for integration of the trace recorder library in the FreeRTOS
* kernel (requires FreeRTOS v7.1.0 or later).
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* 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
*
* Copyright Percepio AB, 2012.
* www.percepio.se
******************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "trcKernel.h"
#if (configUSE_TRACE_FACILITY == 1)
/******************************************************************************
* TraceObjectClassTable
* Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).
* This was added since we want to map both types of Mutex and both types of
* Semaphores on common classes for all Mutexes and all Semaphores respectively.
*
* FreeRTOS Queue types
* #define queueQUEUE_TYPE_BASE ( 0U ) => TRACE_CLASS_QUEUE
* #define queueQUEUE_TYPE_MUTEX ( 1U ) => TRACE_CLASS_MUTEX
* #define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( 2U ) => TRACE_CLASS_SEMAPHORE
* #define queueQUEUE_TYPE_BINARY_SEMAPHORE ( 3U ) => TRACE_CLASS_SEMAPHORE
* #define queueQUEUE_TYPE_RECURSIVE_MUTEX ( 4U ) => TRACE_CLASS_MUTEX
******************************************************************************/
traceObjectClass TraceObjectClassTable[5] = {TRACE_CLASS_QUEUE,
TRACE_CLASS_MUTEX,
TRACE_CLASS_SEMAPHORE,
TRACE_CLASS_SEMAPHORE,
TRACE_CLASS_MUTEX };
/* This is defined in FreeRTOS! */
extern volatile void * volatile pxCurrentTCB;
/* Internal variables */
uint8_t nISRactive = 0;
objectHandleType handle_of_last_logged_task = 0;
uint8_t inExcludedTask = 0;
/*******************************************************************************
* 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)
{
KernelCall * kse;
uint16_t dts1;
if (handle_of_last_logged_task == 0)
{
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))
{
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();
}
}
}
}
/*******************************************************************************
* vTraceStoreKernelCallWithParam
*
* 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,
uint8_t param)
{
KernelCallWithParamAndHandle * kse;
uint8_t dts2;
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task &&
(! inExcludedTask || nISRactive))
{
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();
}
}
}
}
/*******************************************************************************
* vTraceStoreKernelCallWithNumericParamOnly
*
* Used for storing kernel calls with numeric parameters only. This is
* only used for traceTASK_DELAY and traceDELAY_UNTIL at the moment.
******************************************************************************/
void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint16_t param)
{
KernelCallWithParam16 * kse;
uint8_t dts6;
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task
&& (! inExcludedTask || nISRactive))
{
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();
}
}
}
}
/*******************************************************************************
* vTraceStoreTaskswitch
* Called by the scheduler, from the SWITCHED_OUT hook.
* At this point interrupts are disabled, so no need to disable interrupts.
******************************************************************************/
void vTraceStoreTaskswitch(void)
{
uint16_t dts3;
TSEvent* ts;
static objectHandleType handle_of_running_task = 0;
int8_t skipEvent = 0;
if (xTaskGetSchedulerState() == 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 */
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);
}
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;
}
/* 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;
}
/* 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;
ts = (TSEvent*)xTraceNextFreeEventBufferSlot();
if (ts != NULL)
{
if (uiTraceGetObjectState(TRACE_CLASS_TASK,
handle_of_last_logged_task) == TASK_STATE_INSTANCE_ACTIVE)
{
ts->type = TS_TASK_RESUME;
}
else
{
ts->type = TS_TASK_BEGIN;
}
ts->dts = dts3;
ts->objHandle = handle_of_last_logged_task;
vTraceSetObjectState(TRACE_CLASS_TASK,
handle_of_last_logged_task,
TASK_STATE_INSTANCE_ACTIVE);
prvTraceUpdateCounters();
}
}
}
}
/*******************************************************************************
* vTraceStoreNameCloseEvent
*
* Updates the symbol table with the name of this object from the dynamic
* objects table and stores a "close" event, holding the mapping between handle
* and name (a symbol table handle). The stored name-handle mapping is thus the
* "old" one, valid up until this point.
******************************************************************************/
#if (INCLUDE_OBJECT_DELETE == 1)
void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass)
{
ObjCloseNameEvent * ce;
const char * name;
traceLabel idx;
name = PROPERTY_NAME_GET(objectclass, handle);
idx = prvTraceOpenSymbol(name, 0);
ce = (ObjCloseNameEvent*) xTraceNextFreeEventBufferSlot();
if (ce != NULL)
{
ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass;
ce->objHandle = handle;
ce->symbolIndex = idx;
prvTraceUpdateCounters();
}
}
void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass)
{
ObjClosePropEvent * pe;
if (objectclass == TRACE_CLASS_ISR)
{
/* ISR handles should not be closed - never called for ISR */
return;
}
pe = (ObjClosePropEvent*) xTraceNextFreeEventBufferSlot();
if (pe != NULL)
{
if (objectclass == TRACE_CLASS_TASK)
{
pe->arg1 = PROPERTY_ACTOR_PRIORITY(objectclass, handle);
pe->arg2 = PROPERTY_TASK_IFE_SERVICECODE(handle);
pe->arg3 = PROPERTY_TASK_IFE_OBJHANDLE(handle);
PROPERTY_TASK_IFE_SERVICECODE(handle) = 0;
PROPERTY_TASK_IFE_OBJHANDLE(handle) = 0;
}else{
pe->arg1 = PROPERTY_OBJECT_STATE(objectclass, handle);
}
pe->type = EVENTGROUP_OBJCLOSE_PROP + objectclass;
prvTraceUpdateCounters();
}
}
#endif
void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value)
{
PROPERTY_ACTOR_PRIORITY(objectclass, id) = value;
}
uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id)
{
return PROPERTY_ACTOR_PRIORITY(objectclass, id);
}
void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value)
{
PROPERTY_OBJECT_STATE(objectclass, id) = value;
}
void vTraceSetTaskInstanceFinished(objectHandleType handle)
{
#if (USE_IMPLICIT_IFE_RULES == 1)
if (PROPERTY_TASK_IFE_SERVICECODE(handle) == 0)
{
PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle) = 0;
}
#endif
}
uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id)
{
return PROPERTY_OBJECT_STATE(objectclass, id);
}
#endif

View file

@ -0,0 +1,185 @@
/*******************************************************************************
* FreeRTOS+Trace v2.2.3 Recorder Library
* Percepio AB, www.percepio.se
*
* trcPort.c
*
* Contains all portability issues of the trace recorder library.
* See also trcPort.h, where port-specific macros are defined.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* 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.
*
* 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
*
* Copyright Percepio AB, 2012.
* www.percepio.se
******************************************************************************/
#include "FreeRTOS.h"
#include "trcPort.h"
#include "trcUser.h"
#if (configUSE_TRACE_FACILITY == 1)
#if (INCLUDE_SAVE_TO_FILE == 1)
static char* prvFileName = NULL;
#endif
/*******************************************************************************
* uiTraceTickCount
*
* This variable is updated by the traceTASK_INCREMENT_TICK macro in the
* FreeRTOS tick handler. This does not need to be modified when developing a
* new timer port. It is prefered to keep any timer port changes in the HWTC
* macro definitions, which typically give sufficient flexibility.
******************************************************************************/
uint32_t uiTraceTickCount = 0;
/******************************************************************************
* uiTracePortGetTimeStamp
*
* Returns the current time based on the HWTC macros which provide a hardware
* isolation layer towards the hardware timer/counter.
*
* The HWTC macros and uiTracePortGetTimeStamp is the main porting issue
* or the trace recorder library. Typically you should not need to change
* the code of uiTracePortGetTimeStamp if using the HWTC macros.
*
* 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.
******************************************************************************/
uint32_t uiTracePortGetTimeStamp()
{
/* Keep these static to avoid using more stack than necessary */
static uint32_t last_timestamp = 0;
static uint32_t timestamp;
#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;
#else
Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly!
Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING
#endif
#endif
/* May occur due to overflow, if the update of uiTraceTickCount has been
delayed due to disabled interrupts. */
if (timestamp < last_timestamp)
{
timestamp += (HWTC_PERIOD / HWTC_DIVISOR);
}
last_timestamp = timestamp;
return timestamp;
}
/*******************************************************************************
* vTracePortEnd
*
* This function is called by the monitor when a recorder stop is detected.
* This is used by the Win32 port to store the trace to a file. The file path is
* set using vTracePortSetOutFile.
******************************************************************************/
void vTracePortEnd()
{
vTraceConsoleMessage("\n\r[FreeRTOS+Trace] Running vTracePortEnd.\n\r");
#if (WIN32_PORT_SAVE_WHEN_STOPPED == 1)
vTracePortSave();
#endif
#if (WIN32_PORT_EXIT_WHEN_STOPPED == 1)
/* In the FreeRTOS/Win32 demo, this allows for killing the application
when the recorder is stopped (e.g., when the buffer is full) */
system("pause");
exit(0);
#endif
}
#if (INCLUDE_SAVE_TO_FILE == 1)
/*******************************************************************************
* vTracePortSetOutFile
*
* Sets the filename/path used in vTracePortSave.
* This is set in a separate function, since the Win32 port calls vTracePortSave
* in vTracePortEnd if WIN32_PORT_SAVE_WHEN_STOPPED is set.
******************************************************************************/
void vTracePortSetOutFile(char* path)
{
prvFileName = path;
}
/*******************************************************************************
* vTracePortSave
*
* Saves the trace to a file on a local file system. The path is set in a
* separate function, vTracePortSetOutFile, since the Win32 port calls
* vTracePortSave in vTracePortEnd if WIN32_PORT_SAVE_WHEN_STOPPED is set.
******************************************************************************/
void vTracePortSave()
{
char buf[180];
FILE* f;
if (prvFileName == NULL)
{
prvFileName = "FreeRTOSPlusTrace.dump";
sprintf(buf, "No filename specified, using default \"%s\".", prvFileName);
vTraceConsoleMessage(buf);
}
fopen_s(&f, prvFileName, "wb");
if (f)
{
fwrite(RecorderDataPtr, sizeof(RecorderDataType), 1, f);
fclose(f);
sprintf(buf, "\n\r[FreeRTOS+Trace] Saved in: %s\n\r", prvFileName);
vTraceConsoleMessage(buf);
}
else
{
sprintf(buf, "\n\r[FreeRTOS+Trace] Failed to write to output file!\n\r");
vTraceConsoleMessage(buf);
}
}
#endif
#endif

File diff suppressed because it is too large Load diff