+ New feature added: Task notifications.

+ Optimise Cortex-M4F ports by inlining some critical section macros.
+ Original ports used a #define to set the path to portmacro.h - that method has been obsolete for years and now all the old definitions have been moved into a separate header files called deprecated_definitions.h.
+ Cortex-M port now check the active vector bits against 0xff when determining if a function is called from an interrupt - previously only a subset of the bits (0x1f) were checked.
+ Add in new standard demo/test files TaskNotify.c/h and include the files in the simulator demos.
+ Update trace recorder code, and some demos to use the new version (more to do).
+ Introduce uxTaskPriorityGetFromISR().
+ Minor typo corrections.
+ Update MingW simulator demo to match the MSVC simulator demo.
This commit is contained in:
Richard Barry 2014-12-15 14:13:03 +00:00
parent ca22607d14
commit 85fb1cc024
65 changed files with 5524 additions and 4527 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcConfig.h
@ -36,16 +36,101 @@
* 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.
*
* Copyright Percepio AB, 2013.
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2014.
* www.percepio.com
******************************************************************************/
#ifndef TRCCONFIG_H
#define TRCCONFIG_H
/******************************************************************************
* SELECTED_PORT
*
* Macro that specifies what hardware port that should be used.
* Available ports are:
*
* Port Name Code Official OS supported
* PORT_APPLICATION_DEFINED -2 - -
* PORT_NOT_SET -1 - -
* PORT_HWIndependent 0 Yes Any
* PORT_Win32 1 Yes FreeRTOS on Win32
* PORT_Atmel_AT91SAM7 2 No Any
* PORT_Atmel_UC3A0 3 No Any
* PORT_ARM_CortexM 4 Yes Any
* PORT_Renesas_RX600 5 Yes Any
* PORT_Microchip_dsPIC_AND_PIC24 6 Yes Any
* PORT_TEXAS_INSTRUMENTS_TMS570 7 No Any
* PORT_TEXAS_INSTRUMENTS_MSP430 8 No Any
* PORT_MICROCHIP_PIC32MX 9 Yes Any
* PORT_XILINX_PPC405 10 No FreeRTOS
* PORT_XILINX_PPC440 11 No FreeRTOS
* PORT_XILINX_MICROBLAZE 12 No Any
* PORT_NXP_LPC210X 13 No Any
* PORT_MICROCHIP_PIC32MZ 14 Yes Any
* PORT_ARM_CORTEX_A9 15 No Any
*****************************************************************************/
#ifndef WIN32
// Set the port setting here!
#define SELECTED_PORT PORT_NOT_SET
#if (SELECTED_PORT == PORT_NOT_SET)
#error "You need to define SELECTED_PORT here!"
#endif
#else
// For Win32 demo projects this is set automatically
#define SELECTED_PORT PORT_Win32
#endif
/******************************************************************************
* FREERTOS_VERSION
*
* Specify what version of FreeRTOS that is used. This is necessary compensate
* for renamed symbols in the FreeRTOS kernel (does not build if incorrect).
*
* FREERTOS_VERSION_7_3_OR_7_4 (= 1) If using FreeRTOS v7.3.0 - v7.4.2
* FREERTOS_VERSION_7_5_OR_7_6 (= 2) If using FreeRTOS v7.5.0 - v7.6.0
* FREERTOS_VERSION_8_0_OR_LATER (= 3) If using FreeRTOS v8.0.0 or later
*****************************************************************************/
#define FREERTOS_VERSION FREERTOS_VERSION_8_0_OR_LATER
/******************************************************************************
* TRACE_RECORDER_STORE_MODE
*
* Macro which should be defined as one of:
* - TRACE_STORE_MODE_RING_BUFFER
* - TRACE_STORE_MODE_STOP_WHEN_FULL
* Default is TRACE_STORE_MODE_RING_BUFFER.
*
* With TRACE_RECORDER_STORE_MODE set to TRACE_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
* to store the whole run since startup.
*
* When TRACE_RECORDER_STORE_MODE is TRACE_STORE_MODE_STOP_WHEN_FULL, the
* recording is stopped when the buffer becomes full. This is useful for
* recording events following a specific state, e.g., the startup sequence.
*****************************************************************************/
#define TRACE_RECORDER_STORE_MODE TRACE_STORE_MODE_STOP_WHEN_FULL
/*******************************************************************************
* CONFIGURATION RELATED TO CAPACITY AND ALLOCATION
* TRACE_SCHEDULING_ONLY
*
* Macro which should be defined as an integer value.
*
* If this setting is enabled (= 1), only scheduling events are recorded.
* If disabled (= 0), all events are recorded.
*
* Users of FreeRTOS+Trace Free Edition only displays scheduling events, so this
* option can be used to avoid storing unsupported events.
*
* Default value is 0 (store all enabled events).
*
******************************************************************************/
#define TRACE_SCHEDULING_ONLY 0
/*******************************************************************************
* EVENT_BUFFER_SIZE
@ -53,14 +138,221 @@
* 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.
* it may store. Most events use one record (4 byte), although some events
* require multiple 4-byte records. You should adjust this to the amount of RAM
* available in the target system.
*
* Default value is 1000, which means that 4000 bytes is allocated for the
* event buffer.
******************************************************************************/
#define EVENT_BUFFER_SIZE 4000 /* Adjust wrt. to available RAM */
#define EVENT_BUFFER_SIZE 1000
/*******************************************************************************
* NTask, NISR, NQueue, NSemaphore, NMutex
*
* A group of macros which should be defined as integer values, zero or larger.
*
* These define the capacity of the Object Property Table, i.e., the maximum
* number of objects active at any given point, within each object class (e.g.,
* task, queue, semaphore, ...).
*
* If tasks or other other objects are deleted in your system, this
* setting does not limit the total amount of objects created, only the number
* of objects that have been successfully created but not yet deleted.
*
* Using too small values will cause vTraceError to be called, which stores an
* error message in the trace that is shown when opening the trace file.
*
* It can be wise to start with large values for these constants,
* unless you are very confident on these numbers. Then do a recording and
* check the actual usage by selecting View menu -> Trace Details ->
* Resource Usage -> Object Table.
******************************************************************************/
#define NTask 15
#define NISR 5
#define NQueue 10
#define NSemaphore 10
#define NMutex 10
#define NTimer 2
#define NEventGroup 2
/******************************************************************************
* INCLUDE_MEMMANG_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* This controls if malloc and free calls should be traced. Set this to zero to
* exclude malloc/free calls, or one (1) to include such events in the trace.
*
* Default value is 1.
*****************************************************************************/
#define INCLUDE_MEMMANG_EVENTS 1
/******************************************************************************
* INCLUDE_USER_EVENTS
*
* Macro which should be defined as either zero (0) or one (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
*
* Default value is 1.
*
* Note that User Events are only displayed in Professional Edition.
*****************************************************************************/
#define INCLUDE_USER_EVENTS 1
/*****************************************************************************
* INCLUDE_ISR_TRACING
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (0), the code for recording Interrupt Service Routines is
* excluded to reduce code size.
*
* Default value is 1.
*
* Note, if the kernel has no central interrupt dispatcher, recording ISRs
* require that you insert calls to vTraceStoreISRBegin and vTraceStoreISREnd
* in your interrupt handlers.
*****************************************************************************/
#define INCLUDE_ISR_TRACING 1
/*****************************************************************************
* INCLUDE_READY_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If one (1), events are recorded when tasks enter scheduling state "ready".
* This uses a lot of space in the event buffer, so excluding "ready events"
* will allow for longer traces. Including ready events however allows for
* showing the initial pending time before tasks enter the execution state, and
* for presenting accurate response times.
*
* Default value is 1.
*****************************************************************************/
#define INCLUDE_READY_EVENTS 1
/*****************************************************************************
* INCLUDE_NEW_TIME_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (1), events will be generated whenever the OS clock is
* increased.
*
* Default value is 0.
*****************************************************************************/
#define INCLUDE_NEW_TIME_EVENTS 0
/******************************************************************************
* INCLUDE_FLOAT_SUPPORT
*
* Macro which should be defined as either zero (0) or one (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) arguments.
*
* vTracePrintF can be used with integer and string arguments in either case.
*
* Default value is 1.
*****************************************************************************/
#define INCLUDE_FLOAT_SUPPORT 1
/******************************************************************************
* INCLUDE_OBJECT_DELETE
*
* Macro which should be defined as either zero (0) or one (1).
*
* This must be enabled (1) if tasks, queues or other
* traced kernel objects are deleted at runtime. If no deletes are made, this
* can be set to 0 in order to exclude the delete-handling code.
*
* Default value is 1.
*****************************************************************************/
#define INCLUDE_OBJECT_DELETE 1
/*******************************************************************************
* 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. If you don't use User Events or delete any kernel
* objects you set this to a very low value. The minimum recommended value is 4.
* A size of zero (0) is not allowed since a zero-sized array may result in a
* 32-bit pointer, i.e., using 4 bytes rather than 0.
*
* Default value is 800.
******************************************************************************/
#define SYMBOL_TABLE_SIZE 800
#if (SYMBOL_TABLE_SIZE == 0)
#error "SYMBOL_TABLE_SIZE may not be zero!"
#endif
/******************************************************************************
* NameLenTask, NameLenQueue, ...
*
* Macros that specify the maximum lengths (number of characters) for names of
* kernel objects, such as tasks and queues. If longer names are used, they will
* be truncated when stored in the recorder.
*****************************************************************************/
#define NameLenTask 15
#define NameLenISR 15
#define NameLenQueue 15
#define NameLenSemaphore 15
#define NameLenMutex 15
#define NameLenTimer 15
#define NameLenEventGroup 15
/******************************************************************************
* 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
/******************************************************************************
*** ADVANCED SETTINGS ********************************************************
******************************************************************************
* The remaining settings are not necessary to modify but allows for optimizing
* the recorder setup for your specific needs, e.g., to exclude events that you
* are not interested in, in order to get longer traces.
*****************************************************************************/
/******************************************************************************
* HEAP_SIZE_BELOW_16M
*
* An integer constant that can be used to reduce the buffer usage of memory
* allocation events (malloc/free). This value should be 1 if the heap size is
* below 16 MB (2^24 byte), and you can live with reported addresses showing the
* lower 24 bits only. If 0, you get the full 32-bit addresses.
*
* Default value is 0.
******************************************************************************/
#define HEAP_SIZE_BELOW_16M 0
/******************************************************************************
* USE_LINKER_PRAGMA
*
* Macro which should be defined as an integer value, default is 0.
@ -78,36 +370,77 @@
*
* Note that this only applies if using static allocation, see below.
******************************************************************************/
#define USE_LINKER_PRAGMA 0
/*******************************************************************************
* SYMBOL_TABLE_SIZE
/******************************************************************************
* USE_IMPLICIT_IFE_RULES
*
* Macro which should be defined as an integer value.
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* 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 a very low value, e.g. 4, but not zero (0) since
* this causes a declaration of a zero-sized array, for which the C compiler
* behavior is not standardized and may cause misaligned data.
******************************************************************************/
#define SYMBOL_TABLE_SIZE 800
* Tracealyzer groups the events into actor instances, based on context-switches
* and a definition of "Instance Finish Events", or IFEs. These are kernel calls
* considered to be the last event in a task instance. Some kernel calls are
* considered IFEs by default (e.g., delay functions), but it is also possible
* to specify this individually for each task (see vTraceTaskInstanceFinish).
*
* If USE_IMPLICIT_IFE_RULES is one (1), the default IFEs will be enabled, which
* gives a "typical" grouping of events into instances. You can combine this
* with calls to vTraceTaskInstanceFinish for specific tasks.
*
* If USE_IMPLICIT_IFE_RULES is zero (0), the implicit IFEs are disabled and all
* events withing each task is then shown as a single instance, unless you call
* vTraceTaskInstanceFinish() at suitable locations to mark the IFEs.
*****************************************************************************/
#define USE_IMPLICIT_IFE_RULES 1
#if (SYMBOL_TABLE_SIZE == 0)
#error "SYMBOL_TABLE_SIZE may not be zero!"
#endif
/******************************************************************************
* USE_16BIT_OBJECT_HANDLES
*
* Macro which should be defined as either zero (0) or one (1).
*
* If set to 0 (zero), the recorder uses 8-bit handles to identify kernel
* objects such as tasks and queues. This limits the supported number of
* concurrently active objects to 255 of each type (object class).
*
* If set to 1 (one), the recorder uses 16-bit handles to identify kernel
* objects such as tasks and queues. This limits the supported number of
* concurrent objects to 65535 of each type (object class). However, since the
* object property table is limited to 64 KB, the practical limit is about
* 3000 objects in total.
*
* Default is 0.
*
* NOTE: An object with handle above 255 will use an extra 4-byte record in
* the event buffer whenever referenced. Moreover, some internal tables in the
* recorder gets larger when using 16-bit handles. The additional RAM usage is
* 5-10 byte plus 1 byte per kernel object i.e., task, queue, mutex, etc.
*****************************************************************************/
#define USE_16BIT_OBJECT_HANDLES 0
/******************************************************************************
* USE_TRACE_ASSERT
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* If this is one (1), the TRACE_ASSERT macro will verify that a condition is
* true. If the condition is false, vTraceError() will be called.
* This is used on several places in the recorder code for sanity checks on
* parameters. Can be switched off to reduce CPU usage of the tracing.
*****************************************************************************/
#define USE_TRACE_ASSERT 1
/*******************************************************************************
* USE_SEPARATE_USER_EVENT_BUFFER
*
* Macro which should be defined as an integer value.
* Default is zero (0).
*
* This enables and disables the use of the separate user event buffer.
* This enables and disables the use of the separate user event buffer. Using
* this separate buffer has the benefit of not overwriting the user events with
* kernel events (usually generated at a much higher rate), i.e., when using
* ring-buffer mode.
*
* Note: When using the separate user event buffer, you may get an artificial
* task instance named "Unknown actor". This is added as a placeholder when the
@ -138,393 +471,5 @@
******************************************************************************/
#define CHANNEL_FORMAT_PAIRS 32
/*******************************************************************************
* 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 Tracealyzer. 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).
*
* It can be wise to start with very large values for these constants,
* unless you are very confident on these numbers. Then do a recording and
* check the actual usage in Tracealyzer. This is shown by selecting
* View -> Trace Details -> Resource Usage -> Object Table
*
* NOTE 2: Remember to account for all tasks and other objects created by
* the kernel, such as the IDLE task, any timer tasks, 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 fictive
* task that represent the time before the scheduler starts.
* NTask should thus be at least 2-3 slots larger than your application task count.
*
******************************************************************************/
#define NTask 15
#define NISR 5
#define NQueue 10
#define NSemaphore 10
#define NMutex 10
#define NTimer 2
#define NEventGroup 2
/* Maximum object name length for each class (includes zero termination) */
#define NameLenTask 15
#define NameLenISR 15
#define NameLenQueue 15
#define NameLenSemaphore 15
#define NameLenMutex 15
#define NameLenTimer 15
#define NameLenEventGroup 15
/******************************************************************************
* TRACE_DESCRIPTION
*
* Macro which should be defined as a string.
*
* This string is stored in the trace and displayed in Tracealyzer. 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 "Tracealyzer Recorder Test Program"
/******************************************************************************
* 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
*****************************************************************************/
/******************************************************************************
* USE_TRACE_ASSERT
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 0.
*
* If this is one (1), the TRACE_ASSERT macro will verify that a condition is
* true. If the condition is false, vTraceError() will be called.
*****************************************************************************/
#define USE_TRACE_ASSERT 1
/******************************************************************************
* 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 User Events are not displayed in FreeRTOS+Trace Free Edition.
*****************************************************************************/
#define INCLUDE_USER_EVENTS 1
/*****************************************************************************
* INCLUDE_READY_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* If this is zero (0), the code for recording Ready events is
* excluded. Note, this will make it impossible to calculate the correct
* response times.
*****************************************************************************/
#define INCLUDE_READY_EVENTS 1
/*****************************************************************************
* INCLUDE_NEW_TIME_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 0.
*
* If this is zero (1), events will be generated whenever the os clock is
* increased.
*****************************************************************************/
#define INCLUDE_NEW_TIME_EVENTS 0
/*****************************************************************************
* 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, if the kernel has no central interrupt dispatcher, recording ISRs
* require that you insert calls to vTraceStoreISRBegin and vTraceStoreISREnd
* in your interrupt handlers.
*****************************************************************************/
#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. If no deletes are made, this
* can be set to 0 in order to exclude the delete-handling code.
*****************************************************************************/
#define INCLUDE_OBJECT_DELETE 1
/******************************************************************************
* INCLUDE_MEMMANG_EVENTS
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* This controls if malloc and free calls should be traced. Set this to zero to
* exclude malloc/free calls from the tracing.
*****************************************************************************/
#define INCLUDE_MEMMANG_EVENTS 1
/******************************************************************************
* CONFIGURATION RELATED TO BEHAVIOR
*****************************************************************************/
/******************************************************************************
* TRACE_RECORDER_STORE_MODE
*
* Macro which should be defined as one of:
* - TRACE_STORE_MODE_RING_BUFFER
* - TRACE_STORE_MODE_STOP_WHEN_FULL
* Default is TRACE_STORE_MODE_RING_BUFFER.
*
* With TRACE_RECORDER_STORE_MODE set to TRACE_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 TRACE_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
* 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 TRACE_RECORDER_STORE_MODE is TRACE_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.
*****************************************************************************/
#define TRACE_RECORDER_STORE_MODE TRACE_STORE_MODE_RING_BUFFER
/******************************************************************************
* 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. Tracealyzer 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 kernel macros (trcKernelPort.h)
* will define what kernel calls are considered by default to be IFEs.
*
* However, Implicit IFEs only applies to blocking kernel calls. If a
* service 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. 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, 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
/******************************************************************************
* USE_16BIT_OBJECT_HANDLES
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 0.
*
* If set to 0 (zero), the recorder uses 8-bit handles to identify kernel
* objects such as tasks and queues. This limits the supported number of
* concurrently active objects to 255 of each type (object class).
*
* If set to 1 (one), the recorder uses 16-bit handles to identify kernel
* objects such as tasks and queues. This limits the supported number of
* concurrent objects to 65535 of each type (object class). However, since the
* object property table is limited to 64 KB, the practical limit is about
* 3000 objects in total.
*
* NOTE: An object with a high ID (> 255) will generate an extra event
* (= 4 byte) in the event buffer.
*
* NOTE: Some internal tables in the recorder gets larger when using 16-bit
* handles. The additional RAM usage is 5-10 byte plus 1 byte per kernel object
*, i.e., task, queue, semaphore, mutex, etc.
*****************************************************************************/
#define USE_16BIT_OBJECT_HANDLES 0
/****** Port Name ******************** Code ** Official ** OS Platform ******
* PORT_APPLICATION_DEFINED -2 - -
* PORT_NOT_SET -1 - -
* PORT_HWIndependent 0 Yes Any
* PORT_Win32 1 Yes FreeRTOS Win32
* PORT_Atmel_AT91SAM7 2 No Any
* PORT_Atmel_UC3A0 3 No Any
* PORT_ARM_CortexM 4 Yes Any
* PORT_Renesas_RX600 5 Yes Any
* PORT_Microchip_dsPIC_AND_PIC24 6 Yes Any
* PORT_TEXAS_INSTRUMENTS_TMS570 7 No Any
* PORT_TEXAS_INSTRUMENTS_MSP430 8 No Any
* PORT_MICROCHIP_PIC32 9 No Any
* PORT_XILINX_PPC405 10 No FreeRTOS
* PORT_XILINX_PPC440 11 No FreeRTOS
* PORT_XILINX_MICROBLAZE 12 No Any
* PORT_NXP_LPC210X 13 No Any
*****************************************************************************/
#define SELECTED_PORT PORT_ARM_CortexM
#if (SELECTED_PORT == PORT_NOT_SET)
#error "You need to define SELECTED_PORT here!"
#endif
/******************************************************************************
* USE_PRIMASK_CS (for Cortex M devices only)
*
* An integer constant that selects between two options for the critical
* sections of the recorder library.
*
* 0: The default FreeRTOS critical section (BASEPRI) - default setting
* 1: Always disable ALL interrupts (using PRIMASK)
*
* Option 0 uses the standard FreeRTOS macros for critical sections.
* However, on Cortex-M devices they only disable interrupts with priorities
* below a certain configurable level, while higher priority ISRs remain active.
* Such high-priority ISRs may not use the recorder functions in this mode.
*
* Option 1 allows you to safely call the recorder from any ISR, independent of
* the interrupt priority. This mode may however cause higher IRQ latencies
* (some microseconds) since ALL configurable interrupts are disabled during
* the recorder's critical sections in this mode, using the PRIMASK register.
******************************************************************************/
#define USE_PRIMASK_CS 0
/******************************************************************************
* HEAP_SIZE_BELOW_16M
*
* An integer constant that can be used to reduce the buffer usage of memory
* allocation events (malloc/free). This value should be 1 if the heap size is
* below 16 MB (2^24 byte), and you can live with addresses truncated to the
* lower 24 bit. Otherwise set it to 0 to get the full 32-bit addresses.
******************************************************************************/
#define HEAP_SIZE_BELOW_16M 0
#endif

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcBase.h
@ -31,7 +31,9 @@
* 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.
*
* Copyright Percepio AB, 2013.
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2014.
* www.percepio.com
******************************************************************************/
@ -99,20 +101,20 @@ extern uint8_t excludedEventCodes[NEventCodes / 8 + 1];
*****************************************************************************/
typedef struct
{
/* For each object class, the index of the next handle to allocate */
uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ];
/* For each object class, the index of the next handle to allocate */
uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ];
/* The lowest index of this class (constant) */
uint16_t lowestIndexOfClass[ TRACE_NCLASSES ];
/* The lowest index of this class (constant) */
uint16_t lowestIndexOfClass[ TRACE_NCLASSES ];
/* The highest index of this class (constant) */
uint16_t highestIndexOfClass[ TRACE_NCLASSES ];
/* The highest index of this class (constant) */
uint16_t highestIndexOfClass[ TRACE_NCLASSES ];
/* The highest use count for this class (for statistics) */
uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ];
/* The highest use count for this class (for statistics) */
uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ];
/* The free object handles - a set of stacks within this array */
objectHandleType objectHandles[ TRACE_KERNEL_OBJECT_COUNT ];
/* The free object handles - a set of stacks within this array */
objectHandleType objectHandles[ TRACE_KERNEL_OBJECT_COUNT ];
} objectHandleStackType;
@ -136,47 +138,47 @@ extern objectHandleStackType objectHandleStacks;
typedef struct
{
/* = NCLASSES */
uint32_t NumberOfObjectClasses;
/* = NCLASSES */
uint32_t NumberOfObjectClasses;
uint32_t ObjectPropertyTableSizeInBytes;
uint32_t ObjectPropertyTableSizeInBytes;
/* This is used to calculate the index in the dynamic object table
(handle - 1 - nofStaticObjects = index)*/
/* This is used to calculate the index in the dynamic object table
(handle - 1 - nofStaticObjects = index)*/
#if (USE_16BIT_OBJECT_HANDLES == 1)
objectHandleType NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)];
objectHandleType NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)];
#else
objectHandleType NumberOfObjectsPerClass[4*((TRACE_NCLASSES+3)/4)];
#endif
/* Allocation size rounded up to the closest multiple of 4 */
uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/4) ];
/* Allocation size rounded up to the closest multiple of 4 */
uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/4) ];
uint8_t TotalPropertyBytesPerClass[ 4*((TRACE_NCLASSES+3)/4) ];
uint8_t TotalPropertyBytesPerClass[ 4*((TRACE_NCLASSES+3)/4) ];
/* Allocation size rounded up to the closest multiple of 2 */
uint16_t StartIndexOfClass[ 2*((TRACE_NCLASSES+1)/2) ];
/* Allocation size rounded up to the closest multiple of 2 */
uint16_t StartIndexOfClass[ 2*((TRACE_NCLASSES+1)/2) ];
/* The actual handles issued, should be Initiated to all zeros */
uint8_t objbytes[ 4*((TRACE_OBJECT_TABLE_SIZE+3)/4) ];
/* The actual handles issued, should be Initiated to all zeros */
uint8_t objbytes[ 4*((TRACE_OBJECT_TABLE_SIZE+3)/4) ];
} ObjectPropertyTableType;
/* Symbol table data structure */
typedef struct
{
/* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */
uint32_t symTableSize;
/* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */
uint32_t symTableSize;
/* Entry 0 is reserved. Any reference to entry 0 implies NULL*/
uint32_t nextFreeSymbolIndex;
/* 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)];
/* 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];
/* 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;
@ -186,72 +188,80 @@ typedef struct
typedef struct
{
uint8_t type;
uint8_t objHandle;
uint16_t dts; /* differential timestamp - time since last event */
uint8_t type;
uint8_t objHandle;
uint16_t dts; /* differential timestamp - time since last event */
} TSEvent, TREvent;
typedef struct
{
uint8_t type;
uint8_t dummy;
uint16_t dts; /* differential timestamp - time since last event */
uint16_t dts; /* differential timestamp - time since last event */
} LPEvent;
typedef struct
{
uint8_t type;
uint8_t objHandle;
uint16_t dts; /* differential timestamp - time since last event */
uint8_t type;
uint8_t objHandle;
uint16_t dts; /* differential timestamp - time since last event */
} KernelCall;
typedef struct
{
uint8_t type;
uint8_t objHandle;
uint8_t param;
uint8_t dts; /* differential timestamp - time since last event */
uint8_t type;
uint8_t objHandle;
uint8_t param;
uint8_t dts; /* differential timestamp - time since last event */
} KernelCallWithParamAndHandle;
typedef struct
{
uint8_t type;
uint8_t dts; /* differential timestamp - time since last event */
uint16_t param;
uint8_t type;
uint8_t dts; /* differential timestamp - time since last event */
uint16_t param;
} KernelCallWithParam16;
typedef struct
{
uint8_t type;
uint8_t objHandle; /* the handle of the closed object */
uint16_t symbolIndex; /* the name of the closed object */
uint8_t type;
uint8_t 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;
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 */
uint8_t type;
uint8_t unused1;
uint8_t unused2;
uint8_t dts;
} TaskInstanceStatusEvent;
typedef struct
{
uint8_t type;
uint8_t dts;
uint16_t payload; /* the name of the user event */
} UserEvent;
typedef struct
{
uint8_t type;
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;
/* 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;
/* 16 bits extra for storing DTS, if it does not fit in ordinary event. */
uint16_t xts_16;
} XTSEvent;
typedef struct
@ -309,110 +319,108 @@ typedef struct
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;
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;
/* Used to determine Kernel and Endianess */
uint16_t version;
/* Used to determine Kernel and Endianess */
uint16_t version;
/* Currently 3, since v2.6.0 */
uint8_t minor_version;
/* Currently 3, since v2.6.0 */
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;
/* 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;
/* sizeof(RecorderDataType) - just for control */
uint32_t filesize;
/* Current number of events recorded */
uint32_t numEvents;
/* Current number of events recorded */
uint32_t numEvents;
/* The buffer size, in number of event records */
uint32_t maxEvents;
/* The buffer size, in number of event records */
uint32_t maxEvents;
/* The event buffer index, where to write the next event */
uint32_t nextFreeIndex;
/* The event buffer index, where to write the next event */
uint32_t nextFreeIndex;
/* 1 if the buffer is full, 0 otherwise */
uint32_t bufferIsFull;
/* 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 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 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;
/* 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;
/* 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;
/* Not used, remains for compatibility and future use */
uint8_t notused[28];
/* The amount of heap memory remaining at the last malloc or free event */
/* Not used, remains for compatibility and future use */
uint8_t notused[28];
/* The amount of heap memory remaining at the last malloc or free event */
uint32_t heapMemUsage;
/* 0xF0F0F0F0 - for control only */
int32_t debugMarker0;
/* 0xF0F0F0F0 - for control only */
int32_t debugMarker0;
/* Set to value of USE_16BIT_OBJECT_HANDLES */
uint32_t isUsing16bitHandles;
/* 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;
/* 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;
/* 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;
/* 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 inclusion of float support, and for endian detection of floats.
The value should be (float)1 or (uint32_t)0 */
/* For inclusion 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;
float exampleFloatEncoding;
#else
uint32_t exampleFloatEncoding;
uint32_t exampleFloatEncoding;
#endif
/* This is non-zero if an internal error occurred 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;
/* This is non-zero if an internal error occurred 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;
/* 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];
/* Error messages from the recorder. */
char systemInfo[80];
/* 0xF3F3F3F3 - for control only */
int32_t debugMarker3;
/* 0xF3F3F3F3 - for control only */
int32_t debugMarker3;
/* The event data, in 4-byte records */
uint8_t eventData[ EVENT_BUFFER_SIZE * 4 ];
/* The event data, in 4-byte records */
uint8_t eventData[ EVENT_BUFFER_SIZE * 4 ];
#if (USE_SEPARATE_USER_EVENT_BUFFER == 1)
UserEventBuffer userEventBuffer;
@ -421,18 +429,18 @@ typedef struct
/* This should always be 0 */
uint32_t endOfSecondaryBlocks;
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;
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;
@ -444,14 +452,14 @@ uint16_t prvTraceGetDTS(uint16_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);
uint8_t crc6,
uint8_t len,
traceLabel channel);
traceLabel prvTraceLookupSymbolTableEntry(const char* name,
uint8_t crc6,
uint8_t len,
traceLabel channel);
uint8_t crc6,
uint8_t len,
traceLabel channel);
traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel);
@ -462,11 +470,11 @@ void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nEntries);
objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass);
void vTraceFreeObjectHandle(traceObjectClass objectclass,
objectHandleType handle);
objectHandleType handle);
void vTraceSetObjectName(traceObjectClass objectclass,
objectHandleType handle,
const char* name);
objectHandleType handle,
const char* name);
void* xTraceNextFreeEventBufferSlot(void);
@ -478,7 +486,7 @@ unsigned char prvTraceGet8BitHandle(objectHandleType handle);
uint16_t uiIndexOfObject(objectHandleType objecthandle,
uint8_t objectclass);
uint8_t objectclass);
/*******************************************************************************
* vTraceError
@ -519,9 +527,6 @@ RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclas
#define TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)
#define TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_GET_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)
#define TRACE_INCR_HEAP_USAGE(change) {if (RecorderDataPtr != NULL) RecorderDataPtr->heapMemUsage += change;}
#define TRACE_DECR_HEAP_USAGE(change) {if (RecorderDataPtr != NULL) RecorderDataPtr->heapMemUsage -= change;}
/* DEBUG ASSERTS */
#if defined USE_TRACE_ASSERT && USE_TRACE_ASSERT != 0
#define TRACE_ASSERT(eval, msg, defRetVal) \
@ -536,4 +541,8 @@ if (!(eval)) \
#endif
#endif
#endif

View file

@ -1,10 +1,10 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
/*******************************************************************************
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcHardwarePort.h
*
* Contains together with trcHardwarePort.c all hardware portability issues of
* Contains together with trcHardwarePort.c all hardware portability issues of
* the trace recorder library.
*
* Terms of Use
@ -12,27 +12,29 @@
* 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
* 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
* 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.
*
* Copyright Percepio AB, 2013.
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2014.
* www.percepio.com
******************************************************************************/
@ -43,21 +45,21 @@
/* If Win32 port */
#ifdef WIN32
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
/* Standard includes. */
#include <stdio.h>
#include <windows.h>
#include <direct.h>
/* 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
#define WIN32_PORT_SAVE_WHEN_STOPPED 1
#define WIN32_PORT_EXIT_WHEN_STOPPED 1
#endif
@ -66,104 +68,106 @@
/******************************************************************************
* Supported ports
*
*
* PORT_HWIndependent
* A hardware independent fallback option for event timestamping. Provides low
* 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. 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
* This may be used on the Win32 port, but may also be used on embedded hardware
* platforms. 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 execution time of zero.
*
* PORT_APPLICATION_DEFINED
* Allows for defining the port macros in other source code files.
*
* PORT_Win32
* "Accurate" timestamping based on the Windows performance counter for Win32
* "Accurate" timestamping based on the Windows performance counter for Win32
* builds. Note that this gives the host machine time, not the kernel time.
*
* Hardware specific ports
* To get accurate timestamping, a hardware timer is necessary. Below are the
* available ports. Some of these are "unofficial", meaning that
* they have not yet been verified by Percepio but have been contributed by
* external developers. They should work, otherwise let us know by emailing
* support@percepio.com. Some work on any OS platform, while other are specific
* To get accurate timestamping, a hardware timer is necessary. Below are the
* available ports. Some of these are "unofficial", meaning that
* they have not yet been verified by Percepio but have been contributed by
* external developers. They should work, otherwise let us know by emailing
* support@percepio.com. Some work on any OS platform, while other are specific
* to a certain operating system.
*****************************************************************************/
/****** Port Name ******************** Code ** Official ** OS Platform *******/
#define PORT_APPLICATION_DEFINED -2 /* - - */
#define PORT_NOT_SET -1 /* - - */
#define PORT_HWIndependent 0 /* Yes Any */
#define PORT_Win32 1 /* Yes Windows (FreeRTOS)*/
#define PORT_Atmel_AT91SAM7 2 /* No Any */
#define PORT_Atmel_UC3A0 3 /* No Any */
#define PORT_ARM_CortexM 4 /* Yes Any */
#define PORT_Renesas_RX600 5 /* Yes Any */
#define PORT_Microchip_dsPIC_AND_PIC24 6 /* Yes Any */
#define PORT_TEXAS_INSTRUMENTS_TMS570 7 /* No Any */
#define PORT_TEXAS_INSTRUMENTS_MSP430 8 /* No Any */
#define PORT_MICROCHIP_PIC32 9 /* No Any */
#define PORT_XILINX_PPC405 10 /* No FreeRTOS */
#define PORT_XILINX_PPC440 11 /* No FreeRTOS */
#define PORT_XILINX_MICROBLAZE 12 /* No Any */
#define PORT_NXP_LPC210X 13 /* No Any */
/****** Port Name ********************** Code ***** Official ** OS Platform *********/
#define PORT_APPLICATION_DEFINED -2 /* - - */
#define PORT_NOT_SET -1 /* - - */
#define PORT_HWIndependent 0 /* Yes Any */
#define PORT_Win32 1 /* Yes FreeRTOS on Win32 */
#define PORT_Atmel_AT91SAM7 2 /* No Any */
#define PORT_Atmel_UC3A0 3 /* No Any */
#define PORT_ARM_CortexM 4 /* Yes Any */
#define PORT_Renesas_RX600 5 /* Yes Any */
#define PORT_Microchip_dsPIC_AND_PIC24 6 /* Yes Any */
#define PORT_TEXAS_INSTRUMENTS_TMS570 7 /* No Any */
#define PORT_TEXAS_INSTRUMENTS_MSP430 8 /* No Any */
#define PORT_MICROCHIP_PIC32MX 9 /* Yes Any */
#define PORT_XILINX_PPC405 10 /* No FreeRTOS */
#define PORT_XILINX_PPC440 11 /* No FreeRTOS */
#define PORT_XILINX_MICROBLAZE 12 /* No Any */
#define PORT_NXP_LPC210X 13 /* No Any */
#define PORT_MICROCHIP_PIC32MZ 14 /* Yes Any */
#define PORT_ARM_CORTEX_A9 15 /* No Any */
#include "trcConfig.h" // Where SELECTED_PORT is defined
#include "trcConfig.h"
/*******************************************************************************
* 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.,
* 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
* 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.
*
******************************************************************************
*
* HWTC Macros
* HWTC Macros
*
* These four HWTC macros provides a hardware isolation layer representing a
* generic hardware timer/counter used for driving the operating system tick,
* such as the SysTick feature of ARM Cortex M3/M4, or the PIT of the Atmel
* These four HWTC macros provides a hardware isolation layer representing a
* generic hardware timer/counter used for driving the operating system tick,
* such as the SysTick feature of ARM Cortex M3/M4, or the PIT of the Atmel
* AT91SAM7X.
*
* 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
* 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.
* 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.
* 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 OS tick interrupts. This should preferably be mapped to the reload
* register of the hardware timer, to make it more portable between chips in the
* 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).
* For FreeRTOS, this can in most cases be defined as
* For FreeRTOS, this can in most cases be defined as
* #define HWTC_PERIOD (configCPU_CLOCK_HZ / configTICK_RATE_HZ)
*
* 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 longer
* (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 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.
* 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 vTracePortGetTimeStamp is the main porting issue
* or the trace recorder library. Typically you should not need to change
@ -172,164 +176,172 @@
******************************************************************************/
#if (SELECTED_PORT == PORT_Win32)
// This can be used as a template for any free-running 32-bit counter
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (ulGetRunTimeCounterValue())
#define HWTC_PERIOD 0
#define HWTC_DIVISOR 1
// This can be used as a template for any free-running 32-bit counter
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (ulGetRunTimeCounterValue())
#define HWTC_PERIOD 0
#define HWTC_DIVISOR 1
// Please update according to your system...
#define IRQ_PRIORITY_ORDER 1
#elif (SELECTED_PORT == PORT_HWIndependent)
// OS Tick only (typically 1 ms resolution)
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT 0
#define HWTC_PERIOD 1
#define HWTC_DIVISOR 1
// Please update according to your system...
#define IRQ_PRIORITY_ORDER NOT_SET
#define IRQ_PRIORITY_ORDER 1
#elif (SELECTED_PORT == PORT_HWIndependent)
// OS Tick only (typically 1 ms resolution)
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT 0
#define HWTC_PERIOD 1
#define HWTC_DIVISOR 1
// Please update according to your system...
#define IRQ_PRIORITY_ORDER NOT_SET
#elif (SELECTED_PORT == PORT_ARM_CortexM)
void prvTraceSetIRQMask(uint32_t priMask);
uint32_t prvTraceGetIRQMask(void);
void prvTraceEnableIRQ(void);
void prvTraceDisableIRQ(void);
void prvTraceInitCortexM(void);
#define PORT_SPECIFIC_INIT() prvTraceInitCortexM()
extern uint32_t DWT_CYCLES_ADDED;
#define DWT_CTRL_REG (*((uint32_t*)0xE0001000))
#define DWT_CYCLE_COUNTER (*((uint32_t*)0xE0001004))
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (DWT_CYCLE_COUNTER + DWT_CYCLES_ADDED)
#define HWTC_PERIOD 0
#define HWTC_DIVISOR 4
#define REG_DEMCR (*(volatile unsigned int*)0xE000EDFC)
#define REG_DWT_CTRL (*(volatile unsigned int*)0xE0001000)
#define REG_DWT_CYCCNT (*(volatile unsigned int*)0xE0001004)
#define REG_DWT_EXCCNT (*(volatile unsigned int*)0xE000100C)
/* Bit mask for TRCENA bit in DEMCR - Global enable for DWT and ITM */
#define DEMCR_TRCENA (1 << 24)
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
/* Bit mask for NOPRFCNT bit in DWT_CTRL. If 1, DWT_EXCCNT is not supported */
#define DWT_CTRL_NOPRFCNT (1 << 24)
#elif (SELECTED_PORT == PORT_Renesas_RX600)
/* Bit mask for NOCYCCNT bit in DWT_CTRL. If 1, DWT_CYCCNT is not supported */
#define DWT_CTRL_NOCYCCNT (1 << 25)
#include "iodefine.h"
/* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_EXCCNT */
#define DWT_CTRL_EXCEVTENA (1 << 18)
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (CMT0.CMCNT)
#define HWTC_PERIOD (CMT0.CMCOR + 1)
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
/* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_CYCCNT */
#define DWT_CTRL_CYCCNTENA (1)
#define PORT_SPECIFIC_INIT() prvTraceInitCortexM()
extern uint32_t DWT_CYCLES_ADDED;
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (REG_DWT_CYCCNT + DWT_CYCLES_ADDED)
#define HWTC_PERIOD 0
#define HWTC_DIVISOR 4
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_Renesas_RX600)
#include "iodefine.h"
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (CMT0.CMCNT)
#define HWTC_PERIOD (CMT0.CMCOR + 1)
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_MICROCHIP_PIC32MX || PORT_MICROCHIP_PIC32MZ)
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (TMR1)
#define HWTC_PERIOD (PR1 + 1)
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_Microchip_dsPIC_AND_PIC24)
/* For Microchip PIC24 and dsPIC (16 bit) */
/* For Microchip PIC24 and dsPIC (16 bit) */
/* Note: The trace library is designed for 32-bit MCUs and is slower than
intended on 16-bit MCUs. Storing an event on a PIC24 takes about 70 usec.
In comparison, 32-bit MCUs are often 10-20 times faster. If recording overhead
becomes a problem on PIC24, use the filters to exclude less interesting tasks
or system calls. */
/* Note: The trace library is designed for 32-bit MCUs and is slower than
intended on 16-bit MCUs. Storing an event on a PIC24 takes about 70 usec.
In comparison, this is 10-20 times faster on a 32-bit MCU... */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (TMR1)
#define HWTC_PERIOD (PR1+1)
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (TMR1)
#define HWTC_PERIOD (PR1+1)
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_Atmel_AT91SAM7)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT ((uint32_t)(AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF))
#define HWTC_PERIOD ((uint32_t)(AT91C_BASE_PITC->PITC_PIMR + 1))
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT ((uint32_t)(AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF))
#define HWTC_PERIOD ((uint32_t)(AT91C_BASE_PITC->PITC_PIMR + 1))
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_Atmel_UC3A0)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* For Atmel AVR32 (AT32UC3A).*/
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT ((uint32_t)sysreg_read(AVR32_COUNT))
#define HWTC_PERIOD ((uint32_t)(sysreg_read(AVR32_COMPARE) + 1))
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* For Atmel AVR32 (AT32UC3A).*/
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT ((uint32_t)sysreg_read(AVR32_COUNT))
#define HWTC_PERIOD ((uint32_t)(sysreg_read(AVR32_COMPARE) + 1))
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_NXP_LPC210X)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* Tested with LPC2106, but should work with most LPC21XX chips. */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT *((uint32_t *)0xE0004008 )
#define HWTC_PERIOD *((uint32_t *)0xE0004018 )
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* Tested with LPC2106, but should work with most LPC21XX chips. */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT *((uint32_t *)0xE0004008 )
#define HWTC_PERIOD *((uint32_t *)0xE0004018 )
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_TMS570)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define RTIFRC0 *((uint32_t *)0xFFFFFC10)
#define RTICOMP0 *((uint32_t *)0xFFFFFC50)
#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
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#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
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_MSP430)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (TA0R)
#define HWTC_PERIOD (((uint16_t)TACCR0)+1)
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_MICROCHIP_PIC32)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (ReadTimer1()) /* Should be available in BSP */
#define HWTC_PERIOD (ReadPeriod1()+1) /* Should be available in BSP */
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (TA0R)
#define HWTC_PERIOD (((uint16_t)TACCR0)+1)
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_XILINX_PPC405)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT mfspr(0x3db)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT mfspr(0x3db)
#if (defined configCPU_CLOCK_HZ && defined configTICK_RATE_HZ) // Check if FreeRTOS
/* For FreeRTOS only - found no generic OS independent solution for the PPC405 architecture. */
#define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) // Same as in port.c for PPC405
/* For FreeRTOS only - found no generic OS independent solution for the PPC405 architecture. */
#define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) // Same as in port.c for PPC405
#else
/* Not defined for other operating systems yet */
#error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick.
#endif
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
/* Not defined for other operating systems yet */
#error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick.
#endif
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_XILINX_PPC440)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* This should work with most PowerPC chips */
/* This should work with most PowerPC chips */
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT mfspr(0x016)
#define HWTC_COUNT mfspr(0x016)
#if (defined configCPU_CLOCK_HZ && defined configTICK_RATE_HZ) // Check if FreeRTOS
/* For FreeRTOS only - found no generic OS independent solution for the PPC440 architecture. */
#define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) // Same as in port.c for PPC440
@ -337,23 +349,49 @@
/* Not defined for other operating systems yet */
#error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick.
#endif
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_XILINX_MICROBLAZE)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* This should work with most Microblaze configurations.
* It uses the AXI Timer 0 - the tick interrupt source.
* If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required.
*/
#include "xtmrctr_l.h"
/* This should work with most Microblaze configurations.
* It uses the AXI Timer 0 - the tick interrupt source.
* If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required.
*/
#include "xtmrctr_l.h"
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 )
#define HWTC_PERIOD (XTmrCtr_mGetLoadReg( XPAR_TMRCTR_0_BASEADDR, 0) + 1)
#define HWTC_DIVISOR 16
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_ARM_CORTEX_A9)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_MASK 0x0000FF00
#define CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_SHIFT 8
#define CA9_MPCORE_PRIVCTR_PERIOD_REG (*(volatile uint32_t*)(0xF8F00600 + 0))
#define CA9_MPCORE_PRIVCTR_COUNTER_REG (*(volatile uint32_t*)(0xF8F00600 + 4))
#define CA9_MPCORE_PRIVCTR_CONTROL_REG (*(volatile uint32_t*)(0xF8F00600 + 8))
#define CA9_MPCORE_PRIVCTR_PRESCALER (((CA9_MPCORE_PRIVCTR_CONTROL_REG & CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_MASK) >> CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_SHIFT) + 1)
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT CA9_MPCORE_PRIVCTR_COUNTER_REG
#define HWTC_PERIOD ((CA9_MPCORE_PRIVCTR_PERIOD_REG * CA9_MPCORE_PRIVCTR_PRESCALER) + 1)
//NOTE: The private timer ticks with a very high frequency (half the core-clock usually),
//but offers the possibility to apply a prescaler. Depending on the prescaler you set the
//HWTC_DIVISOR may need to be raised. Refer to the notes at the beginning of this file
//for more information.
#define HWTC_DIVISOR 1
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 )
#define HWTC_PERIOD (XTmrCtr_mGetLoadReg( XPAR_TMRCTR_0_BASEADDR, 0) + 1)
#define HWTC_DIVISOR 16
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_APPLICATION_DEFINED)
@ -364,47 +402,47 @@
#elif (SELECTED_PORT != PORT_NOT_SET)
#error "SELECTED_PORT had unsupported value!"
#define SELECTED_PORT PORT_NOT_SET
#error "SELECTED_PORT had unsupported value!"
#define SELECTED_PORT PORT_NOT_SET
#endif
#if (SELECTED_PORT != PORT_NOT_SET)
#ifndef HWTC_COUNT_DIRECTION
#error "HWTC_COUNT_DIRECTION is not set!"
#endif
#ifndef HWTC_COUNT
#error "HWTC_COUNT is not set!"
#endif
#ifndef HWTC_PERIOD
#error "HWTC_PERIOD is not set!"
#endif
#ifndef HWTC_DIVISOR
#error "HWTC_DIVISOR is not set!"
#endif
#ifndef IRQ_PRIORITY_ORDER
#error "IRQ_PRIORITY_ORDER is not set!"
#elif (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1)
#error "IRQ_PRIORITY_ORDER has bad value!"
#endif
#if (HWTC_DIVISOR < 1)
#error "HWTC_DIVISOR must be a non-zero positive value!"
#endif
#ifndef HWTC_COUNT_DIRECTION
#error "HWTC_COUNT_DIRECTION is not set!"
#endif
#ifndef HWTC_COUNT
#error "HWTC_COUNT is not set!"
#endif
#ifndef HWTC_PERIOD
#error "HWTC_PERIOD is not set!"
#endif
#ifndef HWTC_DIVISOR
#error "HWTC_DIVISOR is not set!"
#endif
#ifndef IRQ_PRIORITY_ORDER
#error "IRQ_PRIORITY_ORDER is not set!"
#elif (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1)
#error "IRQ_PRIORITY_ORDER has bad value!"
#endif
#if (HWTC_DIVISOR < 1)
#error "HWTC_DIVISOR must be a non-zero positive value!"
#endif
#endif
/*******************************************************************************
* vTraceConsoleMessage
*
* A wrapper for your system-specific console "printf" console output function.
* This needs to be correctly defined to see status reports from the trace
* 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)
/*******************************************************************************
@ -420,14 +458,4 @@
******************************************************************************/
void vTracePortGetTimeStamp(uint32_t *puiTimestamp);
/*******************************************************************************
* 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);
#endif

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernel.h
@ -55,10 +55,10 @@ void vTraceStoreTaskswitch(objectHandleType task_handle);
void vTraceStoreKernelCall(uint32_t eventcode, traceObjectClass objectClass, uint32_t byteParam);
void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode,
uint32_t param);
uint32_t param);
void vTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass,
uint32_t objectNumber, uint32_t param);
uint32_t objectNumber, uint32_t param);
void vTraceSetTaskInstanceFinished(objectHandleType handle);
@ -73,18 +73,19 @@ uint8_t uiTraceGetObjectState(uint8_t objectclass, objectHandleType id);
#if (INCLUDE_OBJECT_DELETE == 1)
void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass);
traceObjectClass objectclass);
void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass);
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
#endif
#endif
#endif

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernelHooks.h
@ -12,7 +12,7 @@
* compile-time errors.
*
* #ifdef __ICCARM__
* #include "percepio/Include/trcKernelHooks.h"
* #include "trcKernelPort.h"
* #endif
*
* Terms of Use
@ -207,4 +207,7 @@ vTraceStoreObjectNameOnCloseEvent(TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_CLASS_T
vTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_CLASS_TIMER); \
vTraceFreeObjectHandle(TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer));
#endif /* TRCKERNELHOOKS_H */
#endif /* TRCKERNELHOOKS_H */

View file

@ -1,10 +1,10 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernelPort.h
*
* Kernel-specific functionality for FreeRTOS, used by the recorder library.
* Wrapper for kernel-specific port (trcKernelPort<KERNEL>.h)
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
@ -31,947 +31,13 @@
* 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.
*
* Copyright Percepio AB, 2013.
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2014.
* www.percepio.com
******************************************************************************/
/* Change the included file below, if using the recorder with other kernels */
#ifndef TRCKERNELPORT_H_
#define TRCKERNELPORT_H_
#include "FreeRTOS.h" // Defines configUSE_TRACE_FACILITY
#include "trcHardwarePort.h"
extern int uiInEventGroupSetBitsFromISR;
#define USE_TRACEALYZER_RECORDER configUSE_TRACE_FACILITY
#if (USE_TRACEALYZER_RECORDER == 1)
/* Defines that must be set for the recorder to work properly */
#define TRACE_KERNEL_VERSION 0x1AA1
#define TRACE_TICK_RATE_HZ configTICK_RATE_HZ /* Defined in "FreeRTOS.h" */
#define TRACE_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOSConfig.h" */
#if ((SELECTED_PORT == PORT_ARM_CortexM) && (USE_PRIMASK_CS == 1))
#define TRACE_SR_ALLOC_CRITICAL_SECTION() int __irq_status;
#define TRACE_ENTER_CRITICAL_SECTION() { __irq_status = prvTraceGetIRQMask(); prvTraceDisableIRQ(); }
#define TRACE_EXIT_CRITICAL_SECTION() { prvTraceSetIRQMask(__irq_status); }
#define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_BEGIN
#define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_END
#else
#define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL()
#define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL()
#define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY() recorder_busy++;
#define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--;
#endif
/************************************************************************/
/* KERNEL SPECIFIC OBJECT CONFIGURATION */
/************************************************************************/
#define TRACE_NCLASSES 7
#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)
#define TRACE_CLASS_TIMER ((traceObjectClass)5)
#define TRACE_CLASS_EVENTGROUP ((traceObjectClass)6)
#define TRACE_KERNEL_OBJECT_COUNT (NQueue + NSemaphore + NMutex + NTask + NISR + NTimer + NEventGroup)
/* 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: legacy, not used
Byte 3: legacy, not used */
#define PropertyTableSizeTask (NameLenTask + 4)
/* ISR properties: Byte 0: priority
Byte 1: state (if already active) */
#define PropertyTableSizeISR (NameLenISR + 2)
/* NTimer properties: Byte 0: state (unused for now) */
#define PropertyTableSizeTimer (NameLenTimer + 1)
/* NEventGroup properties: Byte 0-3: state (unused for now)*/
#define PropertyTableSizeEventGroup (NameLenEventGroup + 4)
/* 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 StartIndexTimer StartIndexISR + NISR * PropertyTableSizeISR
#define StartIndexEventGroup StartIndexTimer + NTimer * PropertyTableSizeTimer
/* Number of bytes used by the object table */
#define TRACE_OBJECT_TABLE_SIZE StartIndexEventGroup + NEventGroup * PropertyTableSizeEventGroup
/* Includes */
#include "trcConfig.h" /* Must be first, even before trcTypes.h */
#include "trcHardwarePort.h"
#include "trcTypes.h"
#include "trcKernelHooks.h"
#include "trcBase.h"
#include "trcKernel.h"
#include "trcUser.h"
#if (INCLUDE_NEW_TIME_EVENTS == 1 && configUSE_TICKLESS_IDLE != 0)
#error "NewTime events can not be used in combination with tickless idle!"
#endif
/* Initialization of the object property table */
void vTraceInitObjectPropertyTable(void);
/* Initialization of the handle mechanism, see e.g, xTraceGetObjectHandle */
void vTraceInitObjectHandleStack(void);
/* Returns the "Not enough handles" error message for the specified object class */
const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
/*******************************************************************************
* 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*/
/*******************************************************************************
* EVENTGROUP_DIV
*
* Miscellaneous events.
******************************************************************************/
#define EVENTGROUP_DIV (NULL_EVENT + 1) /*0x01*/
#define DIV_XPS (EVENTGROUP_DIV + 0) /*0x01*/
#define DIV_TASK_READY (EVENTGROUP_DIV + 1) /*0x02*/
#define DIV_NEW_TIME (EVENTGROUP_DIV + 2) /*0x03*/
/*******************************************************************************
* 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 (EVENTGROUP_DIV + 3) /*0x04*/
#define TS_ISR_BEGIN (EVENTGROUP_TS + 0) /*0x04*/
#define TS_ISR_RESUME (EVENTGROUP_TS + 1) /*0x05*/
#define TS_TASK_BEGIN (EVENTGROUP_TS + 2) /*0x06*/
#define TS_TASK_RESUME (EVENTGROUP_TS + 3) /*0x07*/
/*******************************************************************************
* EVENTGROUP_OBJCLOSE_NAME
*
* 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), containing the handle-name mapping and object
* properties valid up to this point.
******************************************************************************/
#define EVENTGROUP_OBJCLOSE_NAME (EVENTGROUP_TS + 4) /*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 preceding 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_OBJ_SUCCESS (EVENTGROUP_OBJCLOSE_PROP + 8) /*0x18*/
/*******************************************************************************
* EVENTGROUP_SEND
*
* The events in this group are used to log Send/Give 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_SEND_SUCCESS (EVENTGROUP_CREATE_OBJ_SUCCESS + 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_SUCCESS (EVENTGROUP_SEND_SUCCESS + 8) /*0x28*/
/* Send/Give operations, from ISR */
#define EVENTGROUP_SEND_FROM_ISR_SUCCESS (EVENTGROUP_RECEIVE_SUCCESS + 8) /*0x30*/
/* Receive/Take operations, from ISR */
#define EVENTGROUP_RECEIVE_FROM_ISR_SUCCESS (EVENTGROUP_SEND_FROM_ISR_SUCCESS + 8) /*0x38*/
/* "Failed" event type versions of above (timeout, failed allocation, etc) */
#define EVENTGROUP_KSE_FAILED (EVENTGROUP_RECEIVE_FROM_ISR_SUCCESS + 8) /*0x40*/
/* Failed create calls - memory allocation failed */
#define EVENTGROUP_CREATE_OBJ_FAILED (EVENTGROUP_KSE_FAILED) /*0x40*/
/* Failed send/give - timeout! */
#define EVENTGROUP_SEND_FAILED (EVENTGROUP_CREATE_OBJ_FAILED + 8) /*0x48*/
/* Failed receive/take - timeout! */
#define EVENTGROUP_RECEIVE_FAILED (EVENTGROUP_SEND_FAILED + 8) /*0x50*/
/* Failed non-blocking send/give - queue full */
#define EVENTGROUP_SEND_FROM_ISR_FAILED (EVENTGROUP_RECEIVE_FAILED + 8) /*0x58*/
/* Failed non-blocking receive/take - queue empty */
#define EVENTGROUP_RECEIVE_FROM_ISR_FAILED \
(EVENTGROUP_SEND_FROM_ISR_FAILED + 8) /*0x60*/
/* Events when blocking on receive/take */
#define EVENTGROUP_RECEIVE_BLOCK \
(EVENTGROUP_RECEIVE_FROM_ISR_FAILED + 8) /*0x68*/
/* Events when blocking on send/give */
#define EVENTGROUP_SEND_BLOCK (EVENTGROUP_RECEIVE_BLOCK + 8) /*0x70*/
/* Events on queue peek (receive) */
#define EVENTGROUP_PEEK_SUCCESS (EVENTGROUP_SEND_BLOCK + 8) /*0x78*/
/* Events on object delete (vTaskDelete or vQueueDelete) */
#define EVENTGROUP_DELETE_OBJ_SUCCESS (EVENTGROUP_PEEK_SUCCESS + 8) /*0x80*/
/* Other events - object class is implied: TASK */
#define EVENTGROUP_OTHERS (EVENTGROUP_DELETE_OBJ_SUCCESS + 8) /*0x88*/
#define TASK_DELAY_UNTIL (EVENTGROUP_OTHERS + 0) /*0x88*/
#define TASK_DELAY (EVENTGROUP_OTHERS + 1) /*0x89*/
#define TASK_SUSPEND (EVENTGROUP_OTHERS + 2) /*0x8A*/
#define TASK_RESUME (EVENTGROUP_OTHERS + 3) /*0x8B*/
#define TASK_RESUME_FROM_ISR (EVENTGROUP_OTHERS + 4) /*0x8C*/
#define TASK_PRIORITY_SET (EVENTGROUP_OTHERS + 5) /*0x8D*/
#define TASK_PRIORITY_INHERIT (EVENTGROUP_OTHERS + 6) /*0x8E*/
#define TASK_PRIORITY_DISINHERIT (EVENTGROUP_OTHERS + 7) /*0x8F*/
#define EVENTGROUP_MISC_PLACEHOLDER (EVENTGROUP_OTHERS + 8) /*0x90*/
#define PEND_FUNC_CALL (EVENTGROUP_MISC_PLACEHOLDER+0) /*0x90*/
#define PEND_FUNC_CALL_FROM_ISR (EVENTGROUP_MISC_PLACEHOLDER+1) /*0x91*/
#define PEND_FUNC_CALL_FAILED (EVENTGROUP_MISC_PLACEHOLDER+2) /*0x92*/
#define PEND_FUNC_CALL_FROM_ISR_FAILED (EVENTGROUP_MISC_PLACEHOLDER+3) /*0x93*/
#define MEM_MALLOC_SIZE (EVENTGROUP_MISC_PLACEHOLDER+4) /*0x94*/
#define MEM_MALLOC_ADDR (EVENTGROUP_MISC_PLACEHOLDER+5) /*0x95*/
#define MEM_FREE_SIZE (EVENTGROUP_MISC_PLACEHOLDER+6) /*0x96*/
#define MEM_FREE_ADDR (EVENTGROUP_MISC_PLACEHOLDER+7) /*0x97*/
/* User events */
#define EVENTGROUP_USEREVENT (EVENTGROUP_MISC_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) /*0xA7*/
/*******************************************************************************
* XTS Event - eXtended TimeStamp events
* The timestamps used in the recorder are "differential timestamps" (DTS), i.e.
* the time since the last stored event. The DTS fields are either 1 or 2 bytes
* 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 immediately
* 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*/
#define LOW_POWER_BEGIN (EVENTGROUP_SYS + 4) /*0xAC*/
#define LOW_POWER_END (EVENTGROUP_SYS + 5) /*0xAD*/
#define XID (EVENTGROUP_SYS + 6) /*0xAE*/
#define XTS16L (EVENTGROUP_SYS + 7) /*0xAF*/
#define EVENTGROUP_TIMER (EVENTGROUP_SYS + 8) /*0xB0*/
#define TIMER_CREATE (EVENTGROUP_TIMER + 0) /*0xB0*/
#define TIMER_START (EVENTGROUP_TIMER + 1) /*0xB0*/
#define TIMER_RESET (EVENTGROUP_TIMER + 2) /*0xB1*/
#define TIMER_STOP (EVENTGROUP_TIMER + 3) /*0xB2*/
#define TIMER_CHANGE_PERIOD (EVENTGROUP_TIMER + 4) /*0xB3*/
#define TIMER_DELETE (EVENTGROUP_TIMER + 5) /*0xB4*/
#define TIMER_START_FROM_ISR (EVENTGROUP_TIMER + 6) /*0xB6*/
#define TIMER_RESET_FROM_ISR (EVENTGROUP_TIMER + 7) /*0xB7*/
#define TIMER_STOP_FROM_ISR (EVENTGROUP_TIMER + 8) /*0xB8*/
#define TIMER_CREATE_FAILED (EVENTGROUP_TIMER + 9) /*0xB9*/
#define TIMER_START_FAILED (EVENTGROUP_TIMER + 10) /*0xBA*/
#define TIMER_RESET_FAILED (EVENTGROUP_TIMER + 11) /*0xBB*/
#define TIMER_STOP_FAILED (EVENTGROUP_TIMER + 12) /*0xBC*/
#define TIMER_CHANGE_PERIOD_FAILED (EVENTGROUP_TIMER + 13) /*0xBD*/
#define TIMER_DELETE_FAILED (EVENTGROUP_TIMER + 14) /*0xBE*/
#define TIMER_START_FROM_ISR_FAILED (EVENTGROUP_TIMER + 15) /*0xBF*/
#define TIMER_RESET_FROM_ISR_FAILED (EVENTGROUP_TIMER + 16) /*0xC0*/
#define TIMER_STOP_FROM_ISR_FAILED (EVENTGROUP_TIMER + 17) /*0xC1*/
#define EVENTGROUP_EG (EVENTGROUP_TIMER + 18) /*0xC2*/
#define EVENT_GROUP_CREATE (EVENTGROUP_EG + 0) /*0xC2*/
#define EVENT_GROUP_CREATE_FAILED (EVENTGROUP_EG + 1) /*0xC3*/
#define EVENT_GROUP_SYNC_BLOCK (EVENTGROUP_EG + 2) /*0xC4*/
#define EVENT_GROUP_SYNC_END (EVENTGROUP_EG + 3) /*0xC5*/
#define EVENT_GROUP_WAIT_BITS_BLOCK (EVENTGROUP_EG + 4) /*0xC6*/
#define EVENT_GROUP_WAIT_BITS_END (EVENTGROUP_EG + 5) /*0xC7*/
#define EVENT_GROUP_CLEAR_BITS (EVENTGROUP_EG + 6) /*0xC8*/
#define EVENT_GROUP_CLEAR_BITS_FROM_ISR (EVENTGROUP_EG + 7) /*0xC9*/
#define EVENT_GROUP_SET_BITS (EVENTGROUP_EG + 8) /*0xCA*/
#define EVENT_GROUP_DELETE (EVENTGROUP_EG + 9) /*0xCB*/
#define EVENT_GROUP_SYNC_END_FAILED (EVENTGROUP_EG + 10) /*0xCC*/
#define EVENT_GROUP_WAIT_BITS_END_FAILED (EVENTGROUP_EG + 11) /*0xCD*/
#define EVENT_GROUP_SET_BITS_FROM_ISR (EVENTGROUP_EG + 12) /*0xCE*/
#define EVENT_GROUP_SET_BITS_FROM_ISR_FAILED (EVENTGROUP_EG + 13) /*0xCF*/
/************************************************************************/
/* KERNEL SPECIFIC DATA AND FUNCTIONS NEEDED TO PROVIDE THE */
/* FUNCTIONALITY REQUESTED BY THE TRACE RECORDER */
/************************************************************************/
/******************************************************************************
* 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
******************************************************************************/
extern traceObjectClass TraceObjectClassTable[5];
/* These functions are implemented in the .c file since certain header files must not be included in this one */
objectHandleType prvTraceGetObjectNumber(void* handle);
unsigned char prvTraceGetObjectType(void* handle);
objectHandleType prvTraceGetTaskNumber(void* handle);
unsigned char prvTraceIsSchedulerActive(void);
unsigned char prvTraceIsSchedulerSuspended(void);
unsigned char prvTraceIsSchedulerStarted(void);
void* prvTraceGetCurrentTaskHandle(void);
#if (configUSE_TIMERS == 1)
#undef INCLUDE_xTimerGetTimerDaemonTaskHandle
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1
#endif
/************************************************************************/
/* KERNEL SPECIFIC MACROS USED BY THE TRACE RECORDER */
/************************************************************************/
#define TRACE_MALLOC(size) pvPortMalloc(size)
#define TRACE_IS_SCHEDULER_ACTIVE() prvTraceIsSchedulerActive()
#define TRACE_IS_SCHEDULER_STARTED() prvTraceIsSchedulerStarted()
#define TRACE_IS_SCHEDULER_SUSPENDED() prvTraceIsSchedulerSuspended()
#define TRACE_GET_CURRENT_TASK() prvTraceGetCurrentTaskHandle()
#define TRACE_GET_TASK_PRIORITY(pxTCB) ((uint8_t)pxTCB->uxPriority)
#define TRACE_GET_TASK_NAME(pxTCB) ((char*)pxTCB->pcTaskName)
#define TRACE_GET_TASK_NUMBER(pxTCB) (prvTraceGetTaskNumber(pxTCB))
#define TRACE_SET_TASK_NUMBER(pxTCB) pxTCB->uxTaskNumber = xTraceGetObjectHandle(TRACE_CLASS_TASK);
#define TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass) TraceObjectClassTable[kernelClass]
#define TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject) TRACE_GET_CLASS_TRACE_CLASS(CLASS, prvTraceGetObjectType(pxObject))
#define TRACE_GET_TIMER_NUMBER(tmr) ( ( objectHandleType ) ((Timer_t*)tmr)->uxTimerNumber )
#define TRACE_SET_TIMER_NUMBER(tmr) ((Timer_t*)tmr)->uxTimerNumber = xTraceGetObjectHandle(TRACE_CLASS_TIMER);
#define TRACE_GET_TIMER_NAME(pxTimer) pxTimer->pcTimerName
#define TRACE_GET_TIMER_PERIOD(pxTimer) pxTimer->xTimerPeriodInTicks
#define TRACE_GET_EVENTGROUP_NUMBER(eg) ( ( objectHandleType ) uxEventGroupGetNumber(eg) )
#define TRACE_SET_EVENTGROUP_NUMBER(eg) ((EventGroup_t*)eg)->uxEventGroupNumber = xTraceGetObjectHandle(TRACE_CLASS_EVENTGROUP);
#define TRACE_GET_OBJECT_NUMBER(CLASS, pxObject) (prvTraceGetObjectNumber(pxObject))
#define TRACE_SET_OBJECT_NUMBER(CLASS, pxObject) pxObject->uxQueueNumber = xTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject));
#define TRACE_GET_CLASS_EVENT_CODE(SERVICE, RESULT, CLASS, kernelClass) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass))
#define TRACE_GET_OBJECT_EVENT_CODE(SERVICE, RESULT, CLASS, pxObject) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject))
#define TRACE_GET_TASK_EVENT_CODE(SERVICE, RESULT, CLASS, pxTCB) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_CLASS_TASK)
/************************************************************************/
/* KERNEL SPECIFIC WRAPPERS THAT SHOULD BE CALLED BY THE KERNEL */
/************************************************************************/
#if (configUSE_TICKLESS_IDLE != 0)
#undef traceLOW_POWER_IDLE_BEGIN
#define traceLOW_POWER_IDLE_BEGIN() \
{ \
extern uint32_t trace_disable_timestamp; \
vTraceStoreLowPower(0); \
trace_disable_timestamp = 1; \
}
#undef traceLOW_POWER_IDLE_END
#define traceLOW_POWER_IDLE_END() \
{ \
extern uint32_t trace_disable_timestamp; \
trace_disable_timestamp = 0; \
vTraceStoreLowPower(1); \
}
#endif
/* A macro that will update the tick count when returning from tickless idle */
#undef traceINCREASE_TICK_COUNT
/* Note: This can handle time adjustments of max 2^32 ticks, i.e., 35 seconds at 120 MHz. Thus, tick-less idle periods longer than 2^32 ticks will appear "compressed" on the time line.*/
#define traceINCREASE_TICK_COUNT( xCount ) { DWT_CYCLES_ADDED += (xCount * (TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ)); }
/* Called for each task that becomes ready */
#undef traceMOVED_TASK_TO_READY_STATE
#define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB);
/* Called on each OS tick. Will call uiPortGetTimestamp to make sure it is called at least once every OS tick. */
#undef traceTASK_INCREMENT_TICK
#define traceTASK_INCREMENT_TICK( xTickCount ) \
if (uxSchedulerSuspended == ( UBaseType_t ) pdTRUE || uxPendedTicks == 0) { trcKERNEL_HOOKS_INCREMENT_TICK(); } \
if (uxSchedulerSuspended == ( UBaseType_t ) pdFALSE) { trcKERNEL_HOOKS_NEW_TIME(DIV_NEW_TIME, xTickCount + 1); }
/* Called on each task-switch */
#undef traceTASK_SWITCHED_IN
#define traceTASK_SWITCHED_IN() \
trcKERNEL_HOOKS_TASK_SWITCH(TRACE_GET_CURRENT_TASK());
/* Called on vTaskSuspend */
#undef traceTASK_SUSPEND
#define traceTASK_SUSPEND( pxTaskToSuspend ) \
trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend);
/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */
#undef traceTASK_DELAY
#define traceTASK_DELAY() \
trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY, pxCurrentTCB, xTicksToDelay); \
trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */
#undef traceTASK_DELAY_UNTIL
#define traceTASK_DELAY_UNTIL() \
trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \
trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
#if (INCLUDE_OBJECT_DELETE == 1)
/* Called on vTaskDelete */
#undef traceTASK_DELETE
#define traceTASK_DELETE( pxTaskToDelete ) \
{ TRACE_SR_ALLOC_CRITICAL_SECTION(); \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_TASK_DELETE(DELETE_OBJ, pxTaskToDelete); \
TRACE_EXIT_CRITICAL_SECTION(); }
#endif
#if (INCLUDE_OBJECT_DELETE == 1)
/* Called on vQueueDelete */
#undef traceQUEUE_DELETE
#define traceQUEUE_DELETE( pxQueue ) \
{ TRACE_SR_ALLOC_CRITICAL_SECTION(); \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_OBJECT_DELETE(DELETE_OBJ, UNUSED, pxQueue); \
TRACE_EXIT_CRITICAL_SECTION(); }
#endif
/* Called on vTaskCreate */
#undef traceTASK_CREATE
#define traceTASK_CREATE(pxNewTCB) \
if (pxNewTCB != NULL) \
{ \
trcKERNEL_HOOKS_TASK_CREATE(CREATE_OBJ, UNUSED, pxNewTCB); \
}
/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */
#undef traceTASK_CREATE_FAILED
#define traceTASK_CREATE_FAILED() \
trcKERNEL_HOOKS_TASK_CREATE_FAILED(CREATE_OBJ, UNUSED);
/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */
#undef traceQUEUE_CREATE
#define traceQUEUE_CREATE( pxNewQueue )\
trcKERNEL_HOOKS_OBJECT_CREATE(CREATE_OBJ, UNUSED, pxNewQueue);
/* Called in xQueueCreate, if the queue creation fails */
#undef traceQUEUE_CREATE_FAILED
#define traceQUEUE_CREATE_FAILED( queueType ) \
trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE_OBJ, UNUSED, queueType);
/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */
#undef traceCREATE_MUTEX
#define traceCREATE_MUTEX( pxNewQueue ) \
trcKERNEL_HOOKS_OBJECT_CREATE(CREATE_OBJ, UNUSED, pxNewQueue);
/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */
#undef traceCREATE_MUTEX_FAILED
#define traceCREATE_MUTEX_FAILED() \
trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE_OBJ, UNUSED, queueQUEUE_TYPE_MUTEX);
/* Called when the Mutex can not be given, since not holder */
#undef traceGIVE_MUTEX_RECURSIVE_FAILED
#define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxMutex);
/* Called when a message is sent to a queue */ /* CS IS NEW ! */
#undef traceQUEUE_SEND
#define traceQUEUE_SEND( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, SUCCESS, UNUSED, pxQueue); \
trcKERNEL_HOOKS_SET_OBJECT_STATE(UNUSED, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, pxQueue) == TRACE_CLASS_MUTEX ? (uint8_t)0 : (uint8_t)(pxQueue->uxMessagesWaiting + 1));
/* Called when a message failed to be sent to a queue (timeout) */
#undef traceQUEUE_SEND_FAILED
#define traceQUEUE_SEND_FAILED( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxQueue);
/* 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 ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, BLOCK, UNUSED, pxQueue);
/* Called when a message is received from a queue */
#undef traceQUEUE_RECEIVE
#define traceQUEUE_RECEIVE( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, SUCCESS, UNUSED, pxQueue); \
trcKERNEL_HOOKS_SET_OBJECT_STATE(UNUSED, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, pxQueue) == TRACE_CLASS_MUTEX ? TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()) : (uint8_t)(pxQueue->uxMessagesWaiting - 1));
/* Called when a receive operation on a queue fails (timeout) */
#undef traceQUEUE_RECEIVE_FAILED
#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, FAILED, UNUSED, pxQueue);
/* 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 ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, BLOCK, UNUSED, pxQueue); \
if (TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, pxQueue) != TRACE_CLASS_MUTEX) \
{trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();}
/* Called on xQueuePeek */
#undef traceQUEUE_PEEK
#define traceQUEUE_PEEK( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(PEEK, SUCCESS, UNUSED, pxQueue);
/* Called when a message is sent from interrupt context, e.g., using xQueueSendFromISR */
#undef traceQUEUE_SEND_FROM_ISR
#define traceQUEUE_SEND_FROM_ISR( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND_FROM_ISR, SUCCESS, UNUSED, pxQueue); \
trcKERNEL_HOOKS_SET_OBJECT_STATE(UNUSED, pxQueue, (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 ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND_FROM_ISR, FAILED, UNUSED, pxQueue);
/* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */
#undef traceQUEUE_RECEIVE_FROM_ISR
#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE_FROM_ISR, SUCCESS, UNUSED, pxQueue); \
trcKERNEL_HOOKS_SET_OBJECT_STATE(UNUSED, pxQueue, (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 ) \
trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE_FROM_ISR, FAILED, UNUSED, pxQueue);
/* Called in vTaskPrioritySet */
#undef traceTASK_PRIORITY_SET
#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \
trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_SET, pxTask, uxNewPriority);
/* Called in vTaskPriorityInherit, which is called by Mutex operations */
#undef traceTASK_PRIORITY_INHERIT
#define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \
trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_INHERIT, pxTask, uxNewPriority);
/* Called in vTaskPriorityDisinherit, which is called by Mutex operations */
#undef traceTASK_PRIORITY_DISINHERIT
#define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \
trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(TASK_PRIORITY_DISINHERIT, pxTask, uxNewPriority);
/* Called in vTaskResume */
#undef traceTASK_RESUME
#define traceTASK_RESUME( pxTaskToResume ) \
trcKERNEL_HOOKS_TASK_RESUME(TASK_RESUME, pxTaskToResume);
/* Called in vTaskResumeFromISR */
#undef traceTASK_RESUME_FROM_ISR
#define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) \
trcKERNEL_HOOKS_TASK_RESUME(TASK_RESUME_FROM_ISR, pxTaskToResume);
/* Called in timer.c - xTimerCreate */
#undef traceTIMER_CREATE
#define traceTIMER_CREATE(tmr) \
trcKERNEL_HOOKS_TIMER_CREATE(TIMER_CREATE, tmr);
#undef traceTIMER_CREATE_FAILED
#define traceTIMER_CREATE_FAILED() \
trcKERNEL_HOOKS_TIMER_EVENT(TIMER_CREATE_FAILED, 0);
/* Note that xCommandID can never be tmrCOMMAND_EXECUTE_CALLBACK (-1) since the trace macro is not called in that case */
#undef traceTIMER_COMMAND_SEND
#define traceTIMER_COMMAND_SEND(tmr, xCommandID, xOptionalValue, xReturn) \
if (xCommandID > tmrCOMMAND_START_DONT_TRACE){\
if (xCommandID == tmrCOMMAND_CHANGE_PERIOD) vTraceStoreKernelCallWithParam((xReturn == pdPASS) ? TIMER_CHANGE_PERIOD : TIMER_CHANGE_PERIOD_FAILED, TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(tmr), xOptionalValue);\
else if ((xCommandID == tmrCOMMAND_DELETE) && (xReturn == pdPASS)){ trcKERNEL_HOOKS_TIMER_DELETE(TIMER_DELETE, tmr); } \
else {trcKERNEL_HOOKS_TIMER_EVENT(EVENTGROUP_TIMER + xCommandID + ((xReturn == pdPASS)?0:(TIMER_CREATE_FAILED - TIMER_CREATE)), tmr); }\
}
#undef tracePEND_FUNC_CALL
#define tracePEND_FUNC_CALL(func, arg1, arg2, ret) \
if (ret == pdPASS) \
vTraceStoreKernelCall(PEND_FUNC_CALL, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTimerGetTimerDaemonTaskHandle()) ); \
else \
vTraceStoreKernelCall(PEND_FUNC_CALL_FAILED, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTimerGetTimerDaemonTaskHandle()) );
#undef tracePEND_FUNC_CALL_FROM_ISR
#define tracePEND_FUNC_CALL_FROM_ISR(func, arg1, arg2, ret) \
if (! uiInEventGroupSetBitsFromISR) vTraceStoreKernelCall(PEND_FUNC_CALL_FROM_ISR, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTimerGetTimerDaemonTaskHandle()) ); \
uiInEventGroupSetBitsFromISR = 0;
#undef traceEVENT_GROUP_CREATE
#define traceEVENT_GROUP_CREATE(eg) \
TRACE_SET_EVENTGROUP_NUMBER(eg); \
vTraceStoreKernelCall(EVENT_GROUP_CREATE, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg));
#undef traceEVENT_GROUP_DELETE
#define traceEVENT_GROUP_DELETE(eg) \
vTraceStoreKernelCall(EVENT_GROUP_DELETE, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg)); \
vTraceStoreObjectNameOnCloseEvent(TRACE_GET_EVENTGROUP_NUMBER(eg), TRACE_CLASS_EVENTGROUP); \
vTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_EVENTGROUP_NUMBER(eg), TRACE_CLASS_EVENTGROUP); \
vTraceFreeObjectHandle(TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg));
#undef traceEVENT_GROUP_CREATE_FAILED
#define traceEVENT_GROUP_CREATE_FAILED() \
vTraceStoreKernelCall(EVENT_GROUP_CREATE_FAILED, TRACE_CLASS_EVENTGROUP, 0);
#undef traceEVENT_GROUP_SYNC_BLOCK
#define traceEVENT_GROUP_SYNC_BLOCK(eg, bitsToSet, bitsToWaitFor) \
vTraceStoreKernelCallWithParam(EVENT_GROUP_SYNC_BLOCK, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor);
#undef traceEVENT_GROUP_SYNC_END
#define traceEVENT_GROUP_SYNC_END(eg, bitsToSet, bitsToWaitFor, wasTimeout) \
if (wasTimeout){ vTraceStoreKernelCallWithParam(EVENT_GROUP_SYNC_END_FAILED, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor);} \
else{ vTraceStoreKernelCallWithParam(EVENT_GROUP_SYNC_END, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); }
#undef traceEVENT_GROUP_WAIT_BITS_BLOCK
#define traceEVENT_GROUP_WAIT_BITS_BLOCK(eg, bitsToWaitFor) \
vTraceStoreKernelCallWithParam(EVENT_GROUP_WAIT_BITS_BLOCK, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); \
trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
#undef traceEVENT_GROUP_WAIT_BITS_END
#define traceEVENT_GROUP_WAIT_BITS_END(eg, bitsToWaitFor, wasTimeout) \
if (wasTimeout){ vTraceStoreKernelCallWithParam(EVENT_GROUP_WAIT_BITS_END_FAILED, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); } \
else{ vTraceStoreKernelCallWithParam(EVENT_GROUP_WAIT_BITS_END, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToWaitFor); }
#undef traceEVENT_GROUP_CLEAR_BITS
#define traceEVENT_GROUP_CLEAR_BITS(eg, bitsToClear) \
if (bitsToClear) vTraceStoreKernelCallWithParam(EVENT_GROUP_CLEAR_BITS, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToClear);
#undef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR
#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(eg, bitsToClear) \
if (bitsToClear) vTraceStoreKernelCallWithParam(EVENT_GROUP_CLEAR_BITS_FROM_ISR, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToClear);
#undef traceEVENT_GROUP_SET_BITS
#define traceEVENT_GROUP_SET_BITS(eg, bitsToSet) \
vTraceStoreKernelCallWithParam(EVENT_GROUP_SET_BITS, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToSet);
#undef traceEVENT_GROUP_SET_BITS_FROM_ISR
#define traceEVENT_GROUP_SET_BITS_FROM_ISR(eg, bitsToSet) \
vTraceStoreKernelCallWithParam(EVENT_GROUP_SET_BITS_FROM_ISR, TRACE_CLASS_EVENTGROUP, TRACE_GET_EVENTGROUP_NUMBER(eg), bitsToSet); \
uiInEventGroupSetBitsFromISR = 1;
#if (INCLUDE_MEMMANG_EVENTS == 1)
extern void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, uint32_t size);
#undef traceMALLOC
#define traceMALLOC( pvAddress, uiSize ) {vTraceStoreMemMangEvent(MEM_MALLOC_SIZE, ( uint32_t ) pvAddress, uiSize); TRACE_INCR_HEAP_USAGE(uiSize);}
#undef traceFREE
#define traceFREE( pvAddress, uiSize ) {vTraceStoreMemMangEvent(MEM_FREE_SIZE, ( uint32_t ) pvAddress, uiSize); TRACE_DECR_HEAP_USAGE(uiSize);}
#endif
/************************************************************************/
/* KERNEL SPECIFIC MACROS TO EXCLUDE OR INCLUDE THINGS IN TRACE */
/************************************************************************/
/* Returns the exclude state of the object */
uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, objectHandleType handle);
#define TRACE_SET_QUEUE_FLAG_ISEXCLUDED(queueIndex) TRACE_SET_FLAG_ISEXCLUDED(excludedObjects, queueIndex)
#define TRACE_CLEAR_QUEUE_FLAG_ISEXCLUDED(queueIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, queueIndex)
#define TRACE_GET_QUEUE_FLAG_ISEXCLUDED(queueIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, queueIndex)
#define TRACE_SET_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreIndex) TRACE_SET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+semaphoreIndex)
#define TRACE_CLEAR_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+semaphoreIndex)
#define TRACE_GET_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+semaphoreIndex)
#define TRACE_SET_MUTEX_FLAG_ISEXCLUDED(mutexIndex) TRACE_SET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+mutexIndex)
#define TRACE_CLEAR_MUTEX_FLAG_ISEXCLUDED(mutexIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+mutexIndex)
#define TRACE_GET_MUTEX_FLAG_ISEXCLUDED(mutexIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+mutexIndex)
#define TRACE_SET_TASK_FLAG_ISEXCLUDED(taskIndex) TRACE_SET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+taskIndex)
#define TRACE_CLEAR_TASK_FLAG_ISEXCLUDED(taskIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+taskIndex)
#define TRACE_GET_TASK_FLAG_ISEXCLUDED(taskIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+taskIndex)
#define TRACE_SET_TIMER_FLAG_ISEXCLUDED(timerIndex) TRACE_SET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+timerIndex)
#define TRACE_CLEAR_TIMER_FLAG_ISEXCLUDED(timerIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+timerIndex)
#define TRACE_GET_TIMER_FLAG_ISEXCLUDED(timerIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+timerIndex)
#define TRACE_SET_EVENTGROUP_FLAG_ISEXCLUDED(egIndex) TRACE_SET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+NTimer+1+egIndex)
#define TRACE_CLEAR_EVENTGROUP_FLAG_ISEXCLUDED(egIndex) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+NTimer+1+egIndex)
#define TRACE_GET_EVENTGROUP_FLAG_ISEXCLUDED(egIndex) TRACE_GET_FLAG_ISEXCLUDED(excludedObjects, NQueue+1+NSemaphore+1+NMutex+1+NTask+1+NTimer+1+egIndex)
#define TRACE_CLEAR_OBJECT_FLAG_ISEXCLUDED(objectclass, handle) \
switch (objectclass) \
{ \
case TRACE_CLASS_QUEUE: \
TRACE_CLEAR_QUEUE_FLAG_ISEXCLUDED(handle); \
break; \
case TRACE_CLASS_SEMAPHORE: \
TRACE_CLEAR_SEMAPHORE_FLAG_ISEXCLUDED(handle); \
break; \
case TRACE_CLASS_MUTEX: \
TRACE_CLEAR_MUTEX_FLAG_ISEXCLUDED(handle); \
break; \
case TRACE_CLASS_TASK: \
TRACE_CLEAR_TASK_FLAG_ISEXCLUDED(handle); \
break; \
case TRACE_CLASS_TIMER: \
TRACE_CLEAR_TIMER_FLAG_ISEXCLUDED(handle); \
break; \
case TRACE_CLASS_EVENTGROUP: \
TRACE_CLEAR_EVENTGROUP_FLAG_ISEXCLUDED(handle); \
break; \
}
#define TRACE_SET_OBJECT_FLAG_ISEXCLUDED(objectclass, handle) \
switch (objectclass) \
{ \
case TRACE_CLASS_QUEUE: \
TRACE_SET_QUEUE_FLAG_ISEXCLUDED(handle); \
break; \
case TRACE_CLASS_SEMAPHORE: \
TRACE_SET_SEMAPHORE_FLAG_ISEXCLUDED(handle); \
break; \
case TRACE_CLASS_MUTEX: \
TRACE_SET_MUTEX_FLAG_ISEXCLUDED(handle); \
break; \
case TRACE_CLASS_TASK: \
TRACE_SET_TASK_FLAG_ISEXCLUDED(handle); \
break; \
case TRACE_CLASS_TIMER: \
TRACE_SET_TIMER_FLAG_ISEXCLUDED(handle); \
break; \
case TRACE_CLASS_EVENTGROUP: \
TRACE_SET_EVENTGROUP_FLAG_ISEXCLUDED(handle); \
break; \
}
/* Task */
#define vTraceExcludeTaskFromTrace(handle) \
TRACE_SET_TASK_FLAG_ISEXCLUDED(TRACE_GET_TASK_NUMBER(handle));
#define vTraceIncludeTaskInTrace(handle) \
TRACE_CLEAR_TASK_FLAG_ISEXCLUDED(TRACE_GET_TASK_NUMBER(handle));
/* Queue */
#define vTraceExcludeQueueFromTrace(handle) \
TRACE_SET_QUEUE_FLAG_ISEXCLUDED(TRACE_GET_OBJECT_NUMBER(UNUSED, handle));
#define vTraceIncludeQueueInTrace(handle) \
TRACE_CLEAR_QUEUE_FLAG_ISEXCLUDED(TRACE_GET_OBJECT_NUMBER(UNUSED, handle));
/* Semaphore */
#define vTraceExcludeSemaphoreFromTrace(handle) \
TRACE_SET_SEMAPHORE_FLAG_ISEXCLUDED(TRACE_GET_OBJECT_NUMBER(UNUSED, handle));
#define vTraceIncludeSemaphoreInTrace(handle) \
TRACE_CLEAR_QUEUE_FLAG_ISEXCLUDED(TRACE_GET_OBJECT_NUMBER(UNUSED, handle));
/* Mutex */
#define vTraceExcludeMutexFromTrace(handle) \
TRACE_SET_MUTEX_FLAG_ISEXCLUDED(TRACE_GET_OBJECT_NUMBER(UNUSED, handle));
#define vTraceIncludeMutexInTrace(handle) \
TRACE_CLEAR_QUEUE_FLAG_ISEXCLUDED(TRACE_GET_OBJECT_NUMBER(UNUSED, handle));
/* Timer */
#define vTraceExcludeTimerFromTrace(handle) \
TRACE_SET_TIMER_FLAG_ISEXCLUDED(TRACE_GET_TIMER_NUMBER(handle));
#define vTraceIncludeTimerInTrace(handle) \
TRACE_CLEAR_QUEUE_FLAG_ISEXCLUDED(TRACE_GET_TIMER_NUMBER(handle));
/* Event Group */
#define vTraceExcludeEventGroupFromTrace(handle) \
TRACE_SET_EVENTGROUP_FLAG_ISEXCLUDED(TRACE_GET_EVENTGROUP_NUMBER(handle));
#define vTraceIncludeEventGroupInTrace(handle) \
TRACE_CLEAR_EVENTGROUP_FLAG_ISEXCLUDED(TRACE_GET_EVENTGROUP_NUMBER(handle));
/* Kernel Services */
#define vTraceExcludeKernelServiceDelayFromTrace() \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY); \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY_UNTIL);
#define vTraceIncludeKernelServiceDelayInTrace() \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY); \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(TASK_DELAY_UNTIL);
/* HELPER MACROS FOR KERNEL SERVICES FOR OBJECTS */
#define vTraceExcludeKernelServiceSendFromTrace_HELPER(class) \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_SUCCESS + class); \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_BLOCK + class); \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FAILED + class); \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR_SUCCESS + class); \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR_FAILED + class);
#define vTraceIncludeKernelServiceSendInTrace_HELPER(class) \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_SUCCESS + class); \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_BLOCK + class); \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FAILED + class); \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR_SUCCESS + class); \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_SEND_FROM_ISR_FAILED + class);
#define vTraceExcludeKernelServiceReceiveFromTrace_HELPER(class) \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_SUCCESS + class); \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_BLOCK + class); \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FAILED + class); \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR_SUCCESS + class); \
TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR_FAILED + class);
#define vTraceIncludeKernelServiceReceiveInTrace_HELPER(class) \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_SUCCESS + class); \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_BLOCK + class); \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FAILED + class); \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR_SUCCESS + class); \
TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(EVENTGROUP_RECEIVE_FROM_ISR_FAILED + class);
/* EXCLUDE AND INCLUDE FOR QUEUE */
#define vTraceExcludeKernelServiceQueueSendFromTrace() \
vTraceExcludeKernelServiceSendFromTrace_HELPER(TRACE_CLASS_QUEUE);
#define vTraceIncludeKernelServiceQueueSendInTrace() \
vTraceIncludeKernelServiceSendInTrace_HELPER(TRACE_CLASS_QUEUE);
#define vTraceExcludeKernelServiceQueueReceiveFromTrace() \
vTraceExcludeKernelServiceReceiveFromTrace_HELPER(TRACE_CLASS_QUEUE);
#define vTraceIncludeKernelServiceQueueReceiveInTrace() \
vTraceIncludeKernelServiceReceiveInTrace_HELPER(TRACE_CLASS_QUEUE);
/* EXCLUDE AND INCLUDE FOR SEMAPHORE */
#define vTraceExcludeKernelServiceSemaphoreSendFromTrace() \
vTraceExcludeKernelServiceSendFromTrace_HELPER(TRACE_CLASS_SEMAPHORE);
#define vTraceIncludeKernelServicSemaphoreSendInTrace() \
vTraceIncludeKernelServiceSendInTrace_HELPER(TRACE_CLASS_SEMAPHORE);
#define vTraceExcludeKernelServiceSemaphoreReceiveFromTrace() \
vTraceExcludeKernelServiceReceiveFromTrace_HELPER(TRACE_CLASS_SEMAPHORE);
#define vTraceIncludeKernelServiceSemaphoreReceiveInTrace() \
vTraceIncludeKernelServiceReceiveInTrace_HELPER(TRACE_CLASS_SEMAPHORE);
/* EXCLUDE AND INCLUDE FOR MUTEX */
#define vTraceExcludeKernelServiceMutexSendFromTrace() \
vTraceExcludeKernelServiceSendFromTrace_HELPER(TRACE_CLASS_MUTEX);
#define vTraceIncludeKernelServiceMutexSendInTrace() \
vTraceIncludeKernelServiceSendInTrace_HELPER(TRACE_CLASS_MUTEX);
#define vTraceExcludeKernelServiceMutexReceiveFromTrace() \
vTraceExcludeKernelServiceReceiveFromTrace_HELPER(TRACE_CLASS_MUTEX);
#define vTraceIncludeKernelServiceMutexReceiveInTrace() \
vTraceIncludeKernelServiceReceiveInTrace_HELPER(TRACE_CLASS_MUTEX);
/************************************************************************/
/* KERNEL SPECIFIC MACROS TO NAME OBJECTS, IF NECESSARY */
/************************************************************************/
#define vTraceSetQueueName(object, name) \
vTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, object), TRACE_GET_OBJECT_NUMBER(UNUSED, object), name);
#define vTraceSetSemaphoreName(object, name) \
vTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, object), TRACE_GET_OBJECT_NUMBER(UNUSED, object), name);
#define vTraceSetMutexName(object, name) \
vTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, object), TRACE_GET_OBJECT_NUMBER(UNUSED, object), name);
#define vTraceSetEventGroupName(object, name) \
vTraceSetObjectName(TRACE_CLASS_EVENTGROUP, uxEventGroupGetNumber(object), name);
#undef traceQUEUE_REGISTRY_ADD
#define traceQUEUE_REGISTRY_ADD(object, name) vTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(UNUSED, object), TRACE_GET_OBJECT_NUMBER(UNUSED, object), name);
#endif
#endif /* TRCKERNELPORT_H_ */
#include "trcKernelPortFreeRTOS.h"
/* #include "trcKernelPort<OTHERKERNEL>.h" */

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcTypes.h
@ -31,7 +31,9 @@
* 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.
*
* Copyright Percepio AB, 2013.
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2014.
* www.percepio.com
******************************************************************************/

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcUser.h
@ -30,7 +30,9 @@
* 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.
*
* Copyright Percepio AB, 2013.
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2014.
* www.percepio.com
******************************************************************************/
@ -82,6 +84,13 @@ void vTraceInitTraceData(void);
void vTraceSetRecorderData(void* pRecorderData);
#endif
/*******************************************************************************
* vTraceSetStopHook
*
* Sets a function to be called when the recorder is stopped.
******************************************************************************/
void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction);
/*******************************************************************************
* uiTraceStart
*
@ -154,21 +163,17 @@ void vTraceClearError(int resetErrorMessage);
* 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();
* }
* #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()
* {
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
* ...
* vTraceStoreISREnd(0);
* }
******************************************************************************/
void vTraceSetISRProperties(objectHandleType handle, const char* name, char priority);
@ -179,21 +184,17 @@ void vTraceSetISRProperties(objectHandleType handle, const char* name, char prio
* 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();
* }
* #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()
* {
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
* ...
* vTraceStoreISREnd(0);
* }
*
******************************************************************************/
void vTraceStoreISRBegin(objectHandleType id);
@ -203,30 +204,27 @@ void vTraceStoreISRBegin(objectHandleType id);
*
* Registers the end of an Interrupt Service Routine.
*
* If allowing nested ISRs, this must be called with interrupts disabled.
* The parameter pendingISR indicates if the interrupt has requested a
* task-switch (= 1) or if the interrupt returns to the earlier context (= 0)
*
* 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();
* }
* #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()
* {
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
* ...
* vTraceStoreISREnd(0);
* }
*
******************************************************************************/
void vTraceStoreISREnd(void);
void vTraceStoreISREnd(int pendingISR);
#else
/* If not including the ISR recording */
/* If not including the ISR recording */
void vTraceIncreaseISRActive(void);
@ -238,28 +236,59 @@ void vTraceDecreaseISRActive(void);
#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
/******************************************************************************
* vTraceTaskInstanceFinish(void)
*
* 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);
* Marks the current task instance as finished on the next kernel call.
*
* If that kernel call is blocking, the instance ends after the blocking event
* and the corresponding return event is then the start of the next instance.
* If the kernel call is not blocking, the viewer instead splits the current
* fragment right before the kernel call, which makes this call the first event
* of the next instance.
*
* See also USE_IMPLICIT_IFE_RULES in trcConfig.h
*
* Example:
*
* while(1)
* {
* xQueueReceive(CommandQueue, &command, timeoutDuration);
* processCommand(command);
* vTraceInstanceFinish();
* }
*
*****************************************************************************/
void vTraceTaskInstanceFinish(void);
/******************************************************************************
* vTraceTaskInstanceFinishDirect(void)
*
* Marks the current task instance as finished at this very instant.
* This makes the viewer to splits the current fragment at this point and begin
* a new actor instance.
*
* See also USE_IMPLICIT_IFE_RULES in trcConfig.h
*
* Example:
*
* This example will generate two instances for each loop iteration.
* The first instance ends at vTraceInstanceFinishDirect(), while the second
* instance ends at the next xQueueReceive call.
*
* while (1)
* {
* xQueueReceive(CommandQueue, &command, timeoutDuration);
* ProcessCommand(command);
* vTraceInstanceFinishDirect();
* DoSometingElse();
* vTraceInstanceFinish();
* }
*
*
*****************************************************************************/
void vTraceTaskInstanceFinishDirect(void);
/*******************************************************************************
* vTraceGetTraceBuffer
@ -292,7 +321,7 @@ uint32_t uiTraceGetTraceBufferSize(void);
* When logging a user event, a numeric handle (reference) to this string is
* used to identify the event. This is obtained by calling
*
* xTraceOpenLabel()
* xTraceOpenLabel()
*
* whihc adds the string to the symbol table (if not already present)
* and returns the corresponding handle.
@ -302,15 +331,15 @@ uint32_t uiTraceGetTraceBufferSize(void);
* 1. The handle is looked up every time, when storing the user event.
*
* Example:
* vTraceUserEvent(xTraceOpenLabel("MyUserEvent"));
* vTraceUserEvent(xTraceOpenLabel("MyUserEvent"));
*
* 2. The label is registered just once, with the handle stored in an
* application variable - much like using a file handle.
* application variable - much like using a file handle.
*
* Example:
* myEventHandle = xTraceOpenLabel("MyUserEvent");
* ...
* vTraceUserEvent(myEventHandle);
* 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
@ -342,17 +371,17 @@ void vTraceUserEvent(traceLabel eventLabel);
* 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);
* 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);
* 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
@ -360,15 +389,15 @@ void vTraceUserEvent(traceLabel eventLabel);
* 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 (Note! See below...)
* %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 (Note! See below...)
*
* Up to 15 data arguments are allowed, with a total size of maximum 32 byte.
* In case this is exceeded, the user event is changed into an error message.
@ -380,7 +409,7 @@ void vTraceUserEvent(traceLabel eventLabel);
* unless the higher precision is really necessary.
*
* Note that the double-precision float (%lf) assumes a 64 bit double
* representation. This does not seem to be the case on e.g. PIC24F.
* representation. This does not seem to be the case on e.g. PIC24 and PIC32.
* Before using a %lf argument on a 16-bit MCU, please verify that
* "sizeof(double)" actually gives 8 as expected. If not, use %f instead.
******************************************************************************/
@ -417,7 +446,6 @@ void vTraceChannelUserEvent(UserEventChannel channel);
#define vTracePrintF(eventLabel,formatStr,...)
#define vTraceExcludeTaskFromSchedulingTrace(name)
#define vTraceTaskSkipDefaultInstanceFinishedEvents()
#define vTraceSetISRProperties(handle, name, priority)
#define vTraceStoreISRBegin(id)
#define vTraceStoreISREnd()
@ -427,6 +455,7 @@ void vTraceChannelUserEvent(UserEventChannel channel);
#define vTraceSetSemaphoreName(a, b)
#define vTraceSetEventGroupName(a, b)
#define vTraceSetStopHook(a)
#endif
#ifdef __cplusplus

View file

@ -4,21 +4,22 @@ Tracealyzer Trace Recorder Library
Percepio AB
www.percepio.com
This directory contains the a generic trace recorder library for Tracealyzer v2.6.
This directory contains the a generic trace recorder library for Tracealyzer v2.7.
For information on how to upload the trace data from your target system RAM to
Tracealyzer, see "debugger trace upload.txt"
Tracealyzer, see the User Manual (e.g., http://percepio.com/docs/FreeRTOS/manual/Recorder.html)
Files included
--------------
- trcConfig.h - The recorder's configuration file, set your recorder configuration here!
- trcUser.c/.h - The main API towards the application (trcUser.h in the only include necessary).
- trcKernel.c/.h - Internal routines for storing kernel events.
- trcBase.c/.h - Internal routines for manipulating the data structures and calculating timestamps.
- trcHardwarePort.c/.h - The hardware interface, especially for timestamping.
- trcKernelPort.c/.h - Kernel specific implementations of macros and data.
- trcKernelHooks.h - The trace macro defines (OS independent).
- trcTypes.h - Type definitions used.
- trcConfig.h - The recorder's configuration file, set your recorder configuration here!
- trcUser.c/.h - The main API towards the application (trcUser.h in the only include necessary).
- trcKernel.c/.h - Internal routines for storing kernel events.
- trcBase.c/.h - Internal routines for manipulating the data structures and calculating timestamps.
- trcHardwarePort.c/.h - The hardware interface, especially for timestamping.
- trcKernelPort.h - Wrapper for trcKernelPortFreeRTOS.h (for portability).
- trcKernelPortFreeRTOS.c/.h - FreeRTOS-specific trace macros and helper functions.
- trcKernelHooks.h - Generic trace macros (OS independent), used by trcKernelPortFreeRTOS.
- trcTypes.h - Type definitions used.
Hardware Timer Ports
--------------------
@ -29,17 +30,19 @@ This release contains hardware timer ports for the following hardware architectu
- Atmel AT32UC3 (AVR32)
- Renesas RX600 (e.g., RX62N)
- Microchip dsPIC/PIC24
- Microchip PIC32
- Microchip PIC32MX
- Microchip PIC32MZ
- NXP LPC2106
- Texas Instruments TMS570 (Cortex-R4)
- Texas Instruments MSP430
- Xilinx PowerPC 405
- Xilinx PowerPC 440
- Xilinx Microblaze
- ARM Cortex-A9
These are defined in trcHardwarePort.h. Some of these are "unofficial" ports, provided by external contributors.
By unofficial, it means that they are not yet verified by Percepio AB. Please refer to trcHardwarePort.h for detailed information.
If you use an unofficial port and beleive it is incorrect, please let us know! (support@percepio.com)
If you use an unofficial port and believe it is incorrect, please let us know! (support@percepio.com)
In case your MCU is not yet supported directly, developing a new port is quite easy, just a matter of defining a few macros
according to your specific MCU. See trcHardwarePort.h for further information.

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcHardwarePort.c
@ -32,7 +32,9 @@
* 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.
*
* Copyright Percepio AB, 2013.
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2014.
* www.percepio.com
******************************************************************************/
@ -56,36 +58,37 @@ uint32_t last_timestamp = 0;
******************************************************************************/
uint32_t uiTraceTickCount = 0;
uint32_t DWT_CYCLES_ADDED = 0;
uint32_t DWT_CYCLES_ADDED = 0; /* Used on ARM Cortex-M only */
#if (SELECTED_PORT == PORT_ARM_CortexM)
void prvTraceEnableIRQ(void)
{
asm volatile ("cpsie i");
}
void prvTraceDisableIRQ(void)
{
asm volatile ("cpsid i");
}
void prvTraceSetIRQMask(uint32_t priMask)
{
asm volatile ("MSR primask, %0" : : "r" (priMask) );
}
uint32_t prvTraceGetIRQMask(void)
{
uint32_t result;
asm volatile ("MRS %0, primask" : "=r" (result) );
return result;
}
void prvTraceInitCortexM()
{
DWT_CTRL_REG |= 1; /* Enable the cycle counter */
DWT_CYCLE_COUNTER = 0;
/* Make sure DWT is enabled is enabled, if supported */
REG_DEMCR |= DEMCR_TRCENA;
do{
/* Verify that DWT is supported */
if (REG_DEMCR == 0)
{
vTraceError("DWT not supported by this chip!");
break;
}
/* Verify that DWT_CYCCNT is supported */
if (REG_DWT_CTRL & DWT_CTRL_NOCYCCNT)
{
vTraceError("DWT_CYCCNT not supported by this chip!");
break;
}
/* Reset the cycle counter */
REG_DWT_CYCCNT = 0;
/* Enable the cycle counter */
REG_DWT_CTRL |= DWT_CTRL_CYCCNTENA;
}while(0); /* breaks above jump here */
if (RecorderDataPtr->frequency == 0)
{
@ -109,10 +112,10 @@ void prvTraceInitCortexM()
void vTracePortGetTimeStamp(uint32_t *pTimestamp)
{
static uint32_t last_traceTickCount = 0;
static uint32_t last_hwtc_count = 0;
uint32_t traceTickCount = 0;
uint32_t hwtc_count = 0;
static uint32_t last_hwtc_count = 0;
uint32_t traceTickCount = 0;
uint32_t hwtc_count = 0;
if (trace_disable_timestamp == 1)
{
if (pTimestamp)
@ -120,51 +123,64 @@ void vTracePortGetTimeStamp(uint32_t *pTimestamp)
return;
}
/* Retrieve HWTC_COUNT only once since the same value should be used all throughout this function. */
/* Retrieve HWTC_COUNT only once since the same value should be used all throughout this function. */
#if (HWTC_COUNT_DIRECTION == DIRECTION_INCREMENTING)
hwtc_count = HWTC_COUNT;
hwtc_count = HWTC_COUNT;
#elif (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING)
hwtc_count = HWTC_PERIOD - HWTC_COUNT;
hwtc_count = HWTC_PERIOD - HWTC_COUNT;
#else
Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly!
Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING
Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly!
Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING
#endif
if (last_traceTickCount - uiTraceTickCount - 1 < 0x80000000)
{
/* This means last_traceTickCount is higher than uiTraceTickCount,
so we have previously compensated for a missed tick.
Therefore we use the last stored value because that is more accurate. */
traceTickCount = last_traceTickCount;
}
else
{
/* Business as usual */
traceTickCount = uiTraceTickCount;
}
/* Check for overflow. May occur if the update of uiTraceTickCount has been
delayed due to disabled interrupts. */
if (traceTickCount == last_traceTickCount && hwtc_count < last_hwtc_count)
{
/* A trace tick has occurred but not been executed by the kernel, so we compensate manually. */
traceTickCount++;
}
/* Check if the return address is OK, then we perform the calculation. */
if (pTimestamp)
{
/* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */
*pTimestamp = traceTickCount * (HWTC_PERIOD / HWTC_DIVISOR);
/* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / HWTC_DIVISOR. */
*pTimestamp += (hwtc_count + traceTickCount * (HWTC_PERIOD % HWTC_DIVISOR)) / HWTC_DIVISOR;
#if (SELECTED_PORT == PORT_Win32)
/* The Win32 port uses ulGetRunTimeCounterValue for timestamping, which in turn
uses QueryPerformanceCounter. That function is not always reliable when used over
multiple threads. We must therefore handle rare cases where the timestamp is less
than the previous. In practice, the Win32 should "never" roll over since the
performance counter is 64 bit wide. */
if (last_hwtc_count > hwtc_count)
{
hwtc_count = last_hwtc_count;
}
#endif
if (last_traceTickCount - uiTraceTickCount - 1 < 0x80000000)
{
/* This means last_traceTickCount is higher than uiTraceTickCount,
so we have previously compensated for a missed tick.
Therefore we use the last stored value because that is more accurate. */
traceTickCount = last_traceTickCount;
}
else
{
/* Business as usual */
traceTickCount = uiTraceTickCount;
}
/* Check for overflow. May occur if the update of uiTraceTickCount has been
delayed due to disabled interrupts. */
if (traceTickCount == last_traceTickCount && hwtc_count < last_hwtc_count)
{
/* A trace tick has occurred but not been executed by the kernel, so we compensate manually. */
traceTickCount++;
}
/* Check if the return address is OK, then we perform the calculation. */
if (pTimestamp)
{
/* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */
*pTimestamp = traceTickCount * (HWTC_PERIOD / HWTC_DIVISOR);
/* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / HWTC_DIVISOR. */
*pTimestamp += (hwtc_count + traceTickCount * (HWTC_PERIOD % HWTC_DIVISOR)) / HWTC_DIVISOR;
last_timestamp = *pTimestamp;
}
/* Store the previous values. */
last_traceTickCount = traceTickCount;
last_hwtc_count = hwtc_count;
}
/* Store the previous values. */
last_traceTickCount = traceTickCount;
last_hwtc_count = hwtc_count;
}
#endif
#endif

View file

@ -1,10 +1,10 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernel.c
*
* Functions used by trcKernelHooks.h.
* Functions used by trcKernelHooks.h for storing various kernel events.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
@ -31,7 +31,9 @@
* 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.
*
* Copyright Percepio AB, 2013.
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2014.
* www.percepio.com
******************************************************************************/
@ -46,7 +48,12 @@ uint8_t nISRactive = 0;
objectHandleType handle_of_last_logged_task = 0;
uint8_t inExcludedTask = 0;
/* Current heap usage. Always updated. */
static uint32_t heapMemUsage = 0;
#if (TRACE_SCHEDULING_ONLY == 0)
static uint32_t prvTraceGetParam(uint32_t, uint32_t);
#endif
#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1
/*******************************************************************************
@ -56,44 +63,47 @@ static uint32_t prvTraceGetParam(uint32_t, uint32_t);
******************************************************************************/
void vTraceStoreTaskReady(objectHandleType handle)
{
uint16_t dts3;
TREvent* tr;
uint16_t dts3;
TREvent* tr;
uint8_t hnd8;
TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(handle > 0 && handle <= NTask, "vTraceStoreTaskReady: Invalid value for handle", );
if (recorder_busy)
{
/***********************************************************************
* This should never occur, as the tick- and kernel call ISR is on lowest
* interrupt priority and always are disabled during the critical sections
* of the recorder.
***********************************************************************/
if (handle == 0)
{
/* On FreeRTOS v7.3.0, this occurs when creating tasks due to a bad
placement of the trace macro. In that case, the events are ignored. */
return;
}
vTraceError("Recorder busy - high priority ISR using syscall? (1)");
return;
}
TRACE_ASSERT(handle <= NTask, "vTraceStoreTaskReady: Invalid value for handle", );
if (recorder_busy)
{
/***********************************************************************
* This should never occur, as the tick- and kernel call ISR is on lowest
* interrupt priority and always are disabled during the critical sections
* of the recorder.
***********************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (1)");
return;
}
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
if (!TRACE_GET_TASK_FLAG_ISEXCLUDED(handle))
{
dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
hnd8 = prvTraceGet8BitHandle(handle);
tr = (TREvent*)xTraceNextFreeEventBufferSlot();
if (tr != NULL)
{
uint8_t hnd8 = prvTraceGet8BitHandle(handle);
tr = (TREvent*)xTraceNextFreeEventBufferSlot();
if (tr != NULL)
{
tr->type = DIV_TASK_READY;
tr->dts = dts3;
tr->objHandle = hnd8;
prvTraceUpdateCounters();
}
tr->type = DIV_TASK_READY;
tr->dts = dts3;
tr->objHandle = hnd8;
prvTraceUpdateCounters();
}
}
}
@ -108,38 +118,34 @@ void vTraceStoreTaskReady(objectHandleType handle)
******************************************************************************/
void vTraceStoreLowPower(uint32_t flag)
{
uint16_t dts;
LPEvent* lp;
uint16_t dts;
LPEvent* lp;
TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(flag <= 1, "vTraceStoreLowPower: Invalid flag value", );
if (recorder_busy)
{
if (recorder_busy)
{
/***********************************************************************
* This should never occur, as the tick- and kernel call ISR is on lowest
* interrupt priority and always are disabled during the critical sections
* of the recorder.
***********************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (1)");
return;
}
}
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
if (RecorderDataPtr->recorderActive)
{
dts = (uint16_t)prvTraceGetDTS(0xFFFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
lp = (LPEvent*)xTraceNextFreeEventBufferSlot();
if (lp != NULL)
{
lp = (LPEvent*)xTraceNextFreeEventBufferSlot();
if (lp != NULL)
{
lp->type = LOW_POWER_BEGIN + ( uint8_t ) flag; /* BEGIN or END depending on flag */
lp->dts = dts;
prvTraceUpdateCounters();
}
lp->type = LOW_POWER_BEGIN + ( uint8_t ) flag; /* BEGIN or END depending on flag */
lp->dts = dts;
prvTraceUpdateCounters();
}
}
trcCRITICAL_SECTION_END();
@ -149,62 +155,79 @@ void vTraceStoreLowPower(uint32_t flag)
* vTraceStoreMemMangEvent
*
* This function stores malloc and free events. Each call requires two records,
* for size and address respectively. The event code parameter (ecode) is applied
* to the first record (size) and the following address record gets event
* for size and address respectively. The event code parameter (ecode) is applied
* to the first record (size) and the following address record gets event
* code "ecode + 1", so make sure this is respected in the event code table.
* Note: On "free" calls, the signed_size parameter should be negative.
******************************************************************************/
#if (INCLUDE_MEMMANG_EVENTS == 1)
void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, uint32_t size)
{
void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_size)
{
#if (TRACE_SCHEDULING_ONLY == 0)
uint8_t dts1;
MemEventSize * ms;
MemEventAddr * ma;
uint16_t size_low;
uint16_t addr_low;
uint8_t addr_high;
uint32_t size;
if (signed_size < 0)
size = (uint32_t)(- signed_size);
else
size = (uint32_t)(signed_size);
TRACE_SR_ALLOC_CRITICAL_SECTION();
trcCRITICAL_SECTION_BEGIN();
heapMemUsage += signed_size;
if (RecorderDataPtr->recorderActive)
{
/* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */
if (nISRactive || !inExcludedTask)
{
dts1 = (uint8_t)prvTraceGetDTS(0xFF);
size_low = (uint16_t)prvTraceGetParam(0xFFFF, size);
ms = (MemEventSize *)xTraceNextFreeEventBufferSlot();
if (ms != NULL)
{
ms->dts = dts1;
ms->type = (uint8_t)ecode;
ms->type = NULL_EVENT; /* Updated when all events are written */
ms->size = size_low;
prvTraceUpdateCounters();
/* Storing a second record with address (signals "failed" if null) */
#if (HEAP_SIZE_BELOW_16M)
addr_low = address & 0xFFFF;
/* If the heap address range is within 16 MB, i.e., the upper 8 bits
of addresses are constant, this optimization avoids storing an extra
event record by ignoring the upper 8 bit of the address */
addr_low = address & 0xFFFF;
addr_high = (address >> 16) & 0xFF;
#else
/* The whole 32 bit address is stored using a second event record
for the upper 16 bit */
addr_low = (uint16_t)prvTraceGetParam(0xFFFF, address);
addr_high = 0;
#endif
ma = (MemEventAddr *) xTraceNextFreeEventBufferSlot();
if (ma != NULL)
{
ma->addr_low = addr_low;
ma->addr_high = addr_high;
ma->type = ( ( uint8_t) ecode ) + 1; /* Note this! */
prvTraceUpdateCounters();
ma->type = ( ( uint8_t) ecode ) + 1; /* Note this! */
ms->type = (uint8_t)ecode;
prvTraceUpdateCounters();
RecorderDataPtr->heapMemUsage = heapMemUsage;
}
}
}
}
trcCRITICAL_SECTION_END();
trcCRITICAL_SECTION_END();
#endif /* TRACE_SCHEDULING_ONLY */
}
#endif
@ -216,126 +239,123 @@ void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, uint32_t size)
******************************************************************************/
void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber)
{
KernelCall * kse;
uint16_t dts1;
TRACE_SR_ALLOC_CRITICAL_SECTION();
#if (TRACE_SCHEDULING_ONLY == 0)
KernelCall * kse;
uint16_t dts1;
uint8_t hnd8;
TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(ecode < 0xFF, "vTraceStoreKernelCall: ecode >= 0xFF", );
TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCall: objectClass >= TRACE_NCLASSES", );
TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCall: Invalid value for objectNumber", );
TRACE_ASSERT(ecode < 0xFF, "vTraceStoreKernelCall: ecode >= 0xFF", );
TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCall: objectClass >= TRACE_NCLASSES", );
TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCall: Invalid value for objectNumber", );
if (recorder_busy)
{
/*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/
if (recorder_busy)
{
/*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (2)");
return;
}
vTraceError("Recorder busy - high priority ISR using syscall? (2)");
return;
}
if (handle_of_last_logged_task == 0)
{
return;
}
if (handle_of_last_logged_task == 0)
{
return;
}
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive)
{
/* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */
if (nISRactive || !inExcludedTask)
{
/* Check if the referenced object or the event code is excluded */
if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))
{
dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
uint8_t hnd8 = prvTraceGet8BitHandle(objectNumber);
kse = (KernelCall*) xTraceNextFreeEventBufferSlot();
if (kse != NULL)
{
kse->dts = dts1;
kse->type = (uint8_t)ecode;
kse->objHandle = hnd8;
prvTraceUpdateCounters();
}
}
}
}
}
if (RecorderDataPtr->recorderActive)
{
/* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */
if (nISRactive || !inExcludedTask)
{
/* Check if the referenced object or the event code is excluded */
if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))
{
dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);
hnd8 = prvTraceGet8BitHandle(objectNumber);
kse = (KernelCall*) xTraceNextFreeEventBufferSlot();
if (kse != NULL)
{
kse->dts = dts1;
kse->type = (uint8_t)ecode;
kse->objHandle = hnd8;
prvTraceUpdateCounters();
}
}
}
}
trcCRITICAL_SECTION_END();
#endif /* TRACE_SCHEDULING_ONLY */
}
/*******************************************************************************
* vTraceStoreKernelCallWithParam
*
* Used for storing kernel calls with a handle and a numeric parameter. If the
* Used for storing kernel calls with a handle and a numeric parameter. If the
* numeric parameter does not fit in one byte, and extra XPS event is inserted
* before the kernel call event containing the three upper bytes.
******************************************************************************/
void vTraceStoreKernelCallWithParam(uint32_t evtcode,
traceObjectClass objectClass,
uint32_t objectNumber,
uint32_t param)
traceObjectClass objectClass,
uint32_t objectNumber,
uint32_t param)
{
KernelCallWithParamAndHandle * kse;
uint8_t dts2;
TRACE_SR_ALLOC_CRITICAL_SECTION();
#if (TRACE_SCHEDULING_ONLY == 0)
KernelCallWithParamAndHandle * kse;
uint8_t dts2;
uint8_t hnd8;
uint8_t p8;
TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCall: evtcode >= 0xFF", );
TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCallWithParam: objectClass >= TRACE_NCLASSES", );
TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCallWithParam: Invalid value for objectNumber", );
if (recorder_busy)
{
/*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/
{
/*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (3)");
return;
}
vTraceError("Recorder busy - high priority ISR using syscall? (3)");
return;
}
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task &&
(! inExcludedTask || nISRactive))
{
/* Check if the referenced object or the event code is excluded */
if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
{
dts2 = (uint8_t)prvTraceGetDTS(0xFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
uint8_t p8 = (uint8_t) prvTraceGetParam(0xFF, param);
uint8_t hnd8 = prvTraceGet8BitHandle((objectHandleType)objectNumber);
kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot();
if (kse != NULL)
{
kse->dts = dts2;
kse->type = (uint8_t)evtcode;
kse->objHandle = hnd8;
kse->param = p8;
prvTraceUpdateCounters();
}
}
}
}
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && (! inExcludedTask || nISRactive))
{
/* Check if the referenced object or the event code is excluded */
if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) &&
!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
{
dts2 = (uint8_t)prvTraceGetDTS(0xFF);
p8 = (uint8_t) prvTraceGetParam(0xFF, param);
hnd8 = prvTraceGet8BitHandle((objectHandleType)objectNumber);
kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot();
if (kse != NULL)
{
kse->dts = dts2;
kse->type = (uint8_t)evtcode;
kse->objHandle = hnd8;
kse->param = p8;
prvTraceUpdateCounters();
}
}
}
trcCRITICAL_SECTION_END();
#endif /* TRACE_SCHEDULING_ONLY */
}
#if (TRACE_SCHEDULING_ONLY == 0)
/*******************************************************************************
* prvTraceGetParam
*
@ -346,9 +366,10 @@ void vTraceStoreKernelCallWithParam(uint32_t evtcode,
static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)
{
XPSEvent* xps;
TRACE_ASSERT(param_max == 0xFF || param_max == 0xFFFF, "prvTraceGetParam: Invalid value for param_max", param);
TRACE_ASSERT(param_max == 0xFF || param_max == 0xFFFF,
"prvTraceGetParam: Invalid value for param_max", param);
if (param <= param_max)
{
return param;
@ -367,6 +388,7 @@ static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)
return param & param_max;
}
}
#endif
/*******************************************************************************
* vTraceStoreKernelCallWithNumericParamOnly
@ -376,56 +398,51 @@ static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)
******************************************************************************/
void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
{
KernelCallWithParam16 * kse;
uint8_t dts6;
#if (TRACE_SCHEDULING_ONLY == 0)
KernelCallWithParam16 * kse;
uint8_t dts6;
uint16_t restParam;
TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_SR_ALLOC_CRITICAL_SECTION();
restParam = 0;
TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCallWithNumericParamOnly: Invalid value for evtcode", );
TRACE_ASSERT(evtcode < 0xFF,
"vTraceStoreKernelCallWithNumericParamOnly: Invalid value for evtcode", );
if (recorder_busy)
{
/*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/
{
/*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (4)");
return;
}
vTraceError("Recorder busy - high priority ISR using syscall? (4)");
return;
}
trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task
&& (! inExcludedTask || nISRactive))
{
/* Check if the event code is excluded */
if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
{
dts6 = (uint8_t)prvTraceGetDTS(0xFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot();
if (kse != NULL)
{
kse->dts = dts6;
kse->type = (uint8_t)evtcode;
kse->param = restParam;
prvTraceUpdateCounters();
}
}
}
}
}
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task
&& (! inExcludedTask || nISRactive))
{
/* Check if the event code is excluded */
if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
{
dts6 = (uint8_t)prvTraceGetDTS(0xFF);
restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);
kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot();
if (kse != NULL)
{
kse->dts = dts6;
kse->type = (uint8_t)evtcode;
kse->param = restParam;
prvTraceUpdateCounters();
}
}
}
trcCRITICAL_SECTION_END();
#endif /* TRACE_SCHEDULING_ONLY */
}
/*******************************************************************************
@ -435,39 +452,41 @@ void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
******************************************************************************/
void vTraceStoreTaskswitch(objectHandleType task_handle)
{
uint16_t dts3;
TSEvent* ts;
int8_t skipEvent;
uint16_t dts3;
TSEvent* ts;
int8_t skipEvent;
uint8_t hnd8;
TRACE_SR_ALLOC_CRITICAL_SECTION();
skipEvent = 0;
TRACE_ASSERT(task_handle <= NTask, "vTraceStoreTaskswitch: Invalid value for task_handle", );
/***************************************************************************
This is used to detect if a high-priority ISRs is illegally using the
recorder ISR trace functions (vTraceStoreISRBegin and ...End) while the
recorder is busy with a task-level event or lower priority ISR event.
TRACE_ASSERT(task_handle <= NTask,
"vTraceStoreTaskswitch: Invalid value for task_handle", );
If this is detected, it triggers a call to vTraceError with the error
"Illegal call to vTraceStoreISRBegin/End". If you get this error, it means
that the macro trcCRITICAL_SECTION_BEGIN does not disable this ISR, as required.
/***************************************************************************
This is used to detect if a high-priority ISRs is illegally using the
recorder ISR trace functions (vTraceStoreISRBegin and ...End) while the
recorder is busy with a task-level event or lower priority ISR event.
Note: Setting recorder_busy is normally handled in our macros
trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this
function since critical sections should not be used in the context switch
event...)
***************************************************************************/
/* Skip the event if the task has been excluded, using vTraceExcludeTask */
if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle))
{
skipEvent = 1;
inExcludedTask = 1;
}
else
If this is detected, it triggers a call to vTraceError with the error
"Illegal call to vTraceStoreISRBegin/End". If you get this error, it means
that the macro trcCRITICAL_SECTION_BEGIN does not disable this ISR, as required.
Note: Setting recorder_busy is normally handled in our macros
trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this
function since critical sections should not be used in the context switch
event...)
***************************************************************************/
/* Skip the event if the task has been excluded, using vTraceExcludeTask */
if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle))
{
inExcludedTask = 0;
skipEvent = 1;
inExcludedTask = 1;
}
else
{
inExcludedTask = 0;
}
trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY();
@ -477,48 +496,42 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
{
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)
{
skipEvent = 1;
}
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
uint8_t hnd8;
handle_of_last_logged_task = task_handle;
hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task);
/* If this event should be logged, log it! */
if (skipEvent == 0)
{
dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
handle_of_last_logged_task = task_handle;
hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task);
ts = (TSEvent*)xTraceNextFreeEventBufferSlot();
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;
}
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 = hnd8;
ts->dts = dts3;
ts->objHandle = hnd8;
vTraceSetObjectState(TRACE_CLASS_TASK,
handle_of_last_logged_task,
TASK_STATE_INSTANCE_ACTIVE);
vTraceSetObjectState(TRACE_CLASS_TASK,
handle_of_last_logged_task,
TASK_STATE_INSTANCE_ACTIVE);
prvTraceUpdateCounters();
}
}
}
prvTraceUpdateCounters();
}
}
trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY();
}
@ -533,21 +546,21 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
******************************************************************************/
#if (INCLUDE_OBJECT_DELETE == 1)
void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass)
traceObjectClass objectclass)
{
ObjCloseNameEvent * ce;
const char * name;
traceLabel idx;
ObjCloseNameEvent * ce;
const char * name;
traceLabel idx;
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceStoreObjectNameOnCloseEvent: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceStoreObjectNameOnCloseEvent: Invalid value for handle", );
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
"vTraceStoreObjectNameOnCloseEvent: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
"vTraceStoreObjectNameOnCloseEvent: Invalid value for handle", );
if (RecorderDataPtr->recorderActive)
if (RecorderDataPtr->recorderActive)
{
uint8_t hnd8 = prvTraceGet8BitHandle(handle);
name = TRACE_PROPERTY_NAME_GET(objectclass, handle);
idx = prvTraceOpenSymbol(name, 0);
// Interrupt disable not necessary, already done in trcHooks.h macro
@ -555,7 +568,7 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
if (ce != NULL)
{
ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass;
ce->objHandle = hnd8;
ce->objHandle = hnd8;
ce->symbolIndex = idx;
prvTraceUpdateCounters();
}
@ -563,14 +576,16 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
}
void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass)
traceObjectClass objectclass)
{
ObjClosePropEvent * pe;
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceStoreObjectPropertiesOnCloseEvent: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceStoreObjectPropertiesOnCloseEvent: Invalid value for handle", );
ObjClosePropEvent * pe;
if (RecorderDataPtr->recorderActive)
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
"vTraceStoreObjectPropertiesOnCloseEvent: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
"vTraceStoreObjectPropertiesOnCloseEvent: Invalid value for handle", );
if (RecorderDataPtr->recorderActive)
{
// Interrupt disable not necessary, already done in trcHooks.h macro
pe = (ObjClosePropEvent*) xTraceNextFreeEventBufferSlot();
@ -579,9 +594,9 @@ void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
if (objectclass == TRACE_CLASS_TASK)
{
pe->arg1 = TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle);
pe->arg2 = 0; // Legacy - IFE info removed.
pe->arg3 = 0; // Legacy - IFE info removed.
}else{
}
else
{
pe->arg1 = TRACE_PROPERTY_OBJECT_STATE(objectclass, handle);
}
pe->type = EVENTGROUP_OBJCLOSE_PROP + objectclass;
@ -593,43 +608,52 @@ void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
void vTraceSetPriorityProperty(uint8_t objectclass, objectHandleType id, uint8_t value)
{
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceSetPriorityProperty: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceSetPriorityProperty: Invalid value for id", );
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
"vTraceSetPriorityProperty: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
"vTraceSetPriorityProperty: Invalid value for id", );
TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id) = value;
TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id) = value;
}
uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, objectHandleType id)
{
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetPriorityProperty: objectclass >= TRACE_NCLASSES", 0);
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetPriorityProperty: Invalid value for id", 0);
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
"uiTraceGetPriorityProperty: objectclass >= TRACE_NCLASSES", 0);
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
"uiTraceGetPriorityProperty: Invalid value for id", 0);
return TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id);
return TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id);
}
void vTraceSetObjectState(uint8_t objectclass, objectHandleType id, uint8_t value)
{
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceSetObjectState: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceSetObjectState: Invalid value for id", );
TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value;
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
"vTraceSetObjectState: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
"vTraceSetObjectState: Invalid value for id", );
TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value;
}
uint8_t uiTraceGetObjectState(uint8_t objectclass, objectHandleType id)
{
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetObjectState: objectclass >= TRACE_NCLASSES", 0);
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetObjectState: Invalid value for id", 0);
return TRACE_PROPERTY_OBJECT_STATE(objectclass, id);
TRACE_ASSERT(objectclass < TRACE_NCLASSES,
"uiTraceGetObjectState: objectclass >= TRACE_NCLASSES", 0);
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
"uiTraceGetObjectState: Invalid value for id", 0);
return TRACE_PROPERTY_OBJECT_STATE(objectclass, id);
}
void vTraceSetTaskInstanceFinished(objectHandleType handle)
{
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_TASK], "vTraceSetTaskInstanceFinished: Invalid value for handle", );
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_TASK],
"vTraceSetTaskInstanceFinished: Invalid value for handle", );
#if (USE_IMPLICIT_IFE_RULES == 1)
TRACE_PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle) = 0;
TRACE_PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle) = 0;
#endif
}
#endif
#endif

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library
* Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernelPort.c
@ -31,7 +31,9 @@
* 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.
*
* Copyright Percepio AB, 2013.
* Tabs are used for indent in this file (1 tab = 4 spaces)
*
* Copyright Percepio AB, 2014.
* www.percepio.com
******************************************************************************/
@ -56,13 +58,27 @@ traceObjectClass TraceObjectClassTable[5] = {
int uiInEventGroupSetBitsFromISR = 0;
extern unsigned char ucQueueGetQueueType(void*);
extern BaseType_t uxQueueGetQueueNumber(void*);
#if (FREERTOS_VERSION < FREERTOS_VERSION_8_0_OR_LATER)
extern portBASE_TYPE ucQueueGetQueueNumber(void*);
objectHandleType prvTraceGetObjectNumber(void* handle)
{
return ( objectHandleType ) uxQueueGetQueueNumber(handle);
return (objectHandleType) ucQueueGetQueueNumber(handle);
}
#else
extern portBASE_TYPE uxQueueGetQueueNumber(void*);
objectHandleType prvTraceGetObjectNumber(void* handle)
{
return (objectHandleType) uxQueueGetQueueNumber(handle);
}
#endif
unsigned char prvTraceGetObjectType(void* handle)
{
return ucQueueGetQueueType(handle);
@ -139,7 +155,7 @@ void vTraceInitObjectHandleStack()
objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = NQueue + NSemaphore + NMutex + NTask + NISR;
objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer;
objectHandleStacks.highestIndexOfClass[0] = NQueue - 1;
objectHandleStacks.highestIndexOfClass[0] = NQueue - 1;
objectHandleStacks.highestIndexOfClass[1] = NQueue + NSemaphore - 1;
objectHandleStacks.highestIndexOfClass[2] = NQueue + NSemaphore + NMutex - 1;
objectHandleStacks.highestIndexOfClass[3] = NQueue + NSemaphore + NMutex + NTask - 1;

File diff suppressed because it is too large Load diff