+ 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 * Percepio AB, www.percepio.com
* *
* trcConfig.h * trcConfig.h
@ -36,16 +36,101 @@
* damages, or the exclusion of implied warranties or limitations on how long an * 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. * 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 * www.percepio.com
******************************************************************************/ ******************************************************************************/
#ifndef TRCCONFIG_H #ifndef TRCCONFIG_H
#define 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 * EVENT_BUFFER_SIZE
@ -53,14 +138,221 @@
* Macro which should be defined as an integer value. * Macro which should be defined as an integer value.
* *
* This defines the capacity of the event buffer, i.e., the number of records * 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 * it may store. Most events use one record (4 byte), although some events
* vTracePrintF may use multiple records depending on the number of data args. * 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 1000
#define EVENT_BUFFER_SIZE 4000 /* Adjust wrt. to available RAM */
/******************************************************************************* /*******************************************************************************
* 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 * USE_LINKER_PRAGMA
* *
* Macro which should be defined as an integer value, default is 0. * 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. * Note that this only applies if using static allocation, see below.
******************************************************************************/ ******************************************************************************/
#define USE_LINKER_PRAGMA 0 #define USE_LINKER_PRAGMA 0
/******************************************************************************
/******************************************************************************* * USE_IMPLICIT_IFE_RULES
* SYMBOL_TABLE_SIZE
* *
* 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 * Tracealyzer groups the events into actor instances, based on context-switches
* stores User Events labels and names of deleted tasks, queues, or other kernel * and a definition of "Instance Finish Events", or IFEs. These are kernel calls
* objects. Note that the names of active objects not stored here but in the * considered to be the last event in a task instance. Some kernel calls are
* Object Table. Thus, if you don't use User Events or delete any kernel * considered IFEs by default (e.g., delay functions), but it is also possible
* objects you set this to a very low value, e.g. 4, but not zero (0) since * to specify this individually for each task (see vTraceTaskInstanceFinish).
* this causes a declaration of a zero-sized array, for which the C compiler *
* behavior is not standardized and may cause misaligned data. * 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
#define SYMBOL_TABLE_SIZE 800 * 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!" * USE_16BIT_OBJECT_HANDLES
#endif *
* 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 * USE_SEPARATE_USER_EVENT_BUFFER
* *
* Macro which should be defined as an integer value. * Macro which should be defined as an integer value.
* Default is zero (0). * 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 * 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 * task instance named "Unknown actor". This is added as a placeholder when the
@ -138,393 +471,5 @@
******************************************************************************/ ******************************************************************************/
#define CHANNEL_FORMAT_PAIRS 32 #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 #endif

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library * Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcBase.h * trcBase.h
@ -31,7 +31,9 @@
* damages, or the exclusion of implied warranties or limitations on how long an * 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. * 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 * www.percepio.com
******************************************************************************/ ******************************************************************************/
@ -99,20 +101,20 @@ extern uint8_t excludedEventCodes[NEventCodes / 8 + 1];
*****************************************************************************/ *****************************************************************************/
typedef struct typedef struct
{ {
/* For each object class, the index of the next handle to allocate */ /* For each object class, the index of the next handle to allocate */
uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ]; uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ];
/* The lowest index of this class (constant) */ /* The lowest index of this class (constant) */
uint16_t lowestIndexOfClass[ TRACE_NCLASSES ]; uint16_t lowestIndexOfClass[ TRACE_NCLASSES ];
/* The highest index of this class (constant) */ /* The highest index of this class (constant) */
uint16_t highestIndexOfClass[ TRACE_NCLASSES ]; uint16_t highestIndexOfClass[ TRACE_NCLASSES ];
/* The highest use count for this class (for statistics) */ /* The highest use count for this class (for statistics) */
uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ]; uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ];
/* The free object handles - a set of stacks within this array */ /* The free object handles - a set of stacks within this array */
objectHandleType objectHandles[ TRACE_KERNEL_OBJECT_COUNT ]; objectHandleType objectHandles[ TRACE_KERNEL_OBJECT_COUNT ];
} objectHandleStackType; } objectHandleStackType;
@ -136,47 +138,47 @@ extern objectHandleStackType objectHandleStacks;
typedef struct typedef struct
{ {
/* = NCLASSES */ /* = NCLASSES */
uint32_t NumberOfObjectClasses; uint32_t NumberOfObjectClasses;
uint32_t ObjectPropertyTableSizeInBytes; uint32_t ObjectPropertyTableSizeInBytes;
/* This is used to calculate the index in the dynamic object table /* This is used to calculate the index in the dynamic object table
(handle - 1 - nofStaticObjects = index)*/ (handle - 1 - nofStaticObjects = index)*/
#if (USE_16BIT_OBJECT_HANDLES == 1) #if (USE_16BIT_OBJECT_HANDLES == 1)
objectHandleType NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)]; objectHandleType NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)];
#else #else
objectHandleType NumberOfObjectsPerClass[4*((TRACE_NCLASSES+3)/4)]; objectHandleType NumberOfObjectsPerClass[4*((TRACE_NCLASSES+3)/4)];
#endif #endif
/* Allocation size rounded up to the closest multiple of 4 */ /* Allocation size rounded up to the closest multiple of 4 */
uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/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 */ /* Allocation size rounded up to the closest multiple of 2 */
uint16_t StartIndexOfClass[ 2*((TRACE_NCLASSES+1)/2) ]; uint16_t StartIndexOfClass[ 2*((TRACE_NCLASSES+1)/2) ];
/* The actual handles issued, should be Initiated to all zeros */ /* The actual handles issued, should be Initiated to all zeros */
uint8_t objbytes[ 4*((TRACE_OBJECT_TABLE_SIZE+3)/4) ]; uint8_t objbytes[ 4*((TRACE_OBJECT_TABLE_SIZE+3)/4) ];
} ObjectPropertyTableType; } ObjectPropertyTableType;
/* Symbol table data structure */ /* Symbol table data structure */
typedef struct typedef struct
{ {
/* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */ /* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */
uint32_t symTableSize; uint32_t symTableSize;
/* Entry 0 is reserved. Any reference to entry 0 implies NULL*/ /* Entry 0 is reserved. Any reference to entry 0 implies NULL*/
uint32_t nextFreeSymbolIndex; uint32_t nextFreeSymbolIndex;
/* Size rounded up to closest multiple of 4, to avoid alignment issues*/ /* Size rounded up to closest multiple of 4, to avoid alignment issues*/
uint8_t symbytes[4*((SYMBOL_TABLE_SIZE+3)/4)]; uint8_t symbytes[4*((SYMBOL_TABLE_SIZE+3)/4)];
/* Used for lookups - Up to 64 linked lists within the symbol table /* Used for lookups - Up to 64 linked lists within the symbol table
connecting all entries with the same 6 bit checksum. connecting all entries with the same 6 bit checksum.
This field holds the current list heads. Should be initiated to zeros */ This field holds the current list heads. Should be initiated to zeros */
uint16_t latestEntryOfChecksum[64]; uint16_t latestEntryOfChecksum[64];
} symbolTableType; } symbolTableType;
@ -186,72 +188,80 @@ typedef struct
typedef struct typedef struct
{ {
uint8_t type; uint8_t type;
uint8_t objHandle; uint8_t objHandle;
uint16_t dts; /* differential timestamp - time since last event */ uint16_t dts; /* differential timestamp - time since last event */
} TSEvent, TREvent; } TSEvent, TREvent;
typedef struct typedef struct
{ {
uint8_t type; uint8_t type;
uint8_t dummy; uint8_t dummy;
uint16_t dts; /* differential timestamp - time since last event */ uint16_t dts; /* differential timestamp - time since last event */
} LPEvent; } LPEvent;
typedef struct typedef struct
{ {
uint8_t type; uint8_t type;
uint8_t objHandle; uint8_t objHandle;
uint16_t dts; /* differential timestamp - time since last event */ uint16_t dts; /* differential timestamp - time since last event */
} KernelCall; } KernelCall;
typedef struct typedef struct
{ {
uint8_t type; uint8_t type;
uint8_t objHandle; uint8_t objHandle;
uint8_t param; uint8_t param;
uint8_t dts; /* differential timestamp - time since last event */ uint8_t dts; /* differential timestamp - time since last event */
} KernelCallWithParamAndHandle; } KernelCallWithParamAndHandle;
typedef struct typedef struct
{ {
uint8_t type; uint8_t type;
uint8_t dts; /* differential timestamp - time since last event */ uint8_t dts; /* differential timestamp - time since last event */
uint16_t param; uint16_t param;
} KernelCallWithParam16; } KernelCallWithParam16;
typedef struct typedef struct
{ {
uint8_t type; uint8_t type;
uint8_t objHandle; /* the handle of the closed object */ uint8_t objHandle; /* the handle of the closed object */
uint16_t symbolIndex; /* the name of the closed object */ uint16_t symbolIndex; /* the name of the closed object */
} ObjCloseNameEvent; } ObjCloseNameEvent;
typedef struct typedef struct
{ {
uint8_t type; uint8_t type;
uint8_t arg1; uint8_t arg1;
uint8_t arg2; uint8_t arg2;
uint8_t arg3; uint8_t arg3;
} ObjClosePropEvent; } ObjClosePropEvent;
typedef struct typedef struct
{ {
uint8_t type; uint8_t type;
uint8_t dts; uint8_t unused1;
uint16_t payload; /* the name of the user event */ 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; } UserEvent;
typedef struct typedef struct
{ {
uint8_t type; uint8_t type;
/* 8 bits extra for storing DTS, if it does not fit in ordinary event /* 8 bits extra for storing DTS, if it does not fit in ordinary event
(this one is always MSB if used) */ (this one is always MSB if used) */
uint8_t xts_8; uint8_t xts_8;
/* 16 bits extra for storing DTS, if it does not fit in ordinary event. */ /* 16 bits extra for storing DTS, if it does not fit in ordinary event. */
uint16_t xts_16; uint16_t xts_16;
} XTSEvent; } XTSEvent;
typedef struct typedef struct
@ -309,110 +319,108 @@ typedef struct
typedef struct typedef struct
{ {
uint8_t startmarker0; uint8_t startmarker0;
uint8_t startmarker1; uint8_t startmarker1;
uint8_t startmarker2; uint8_t startmarker2;
uint8_t startmarker3; uint8_t startmarker3;
uint8_t startmarker4; uint8_t startmarker4;
uint8_t startmarker5; uint8_t startmarker5;
uint8_t startmarker6; uint8_t startmarker6;
uint8_t startmarker7; uint8_t startmarker7;
uint8_t startmarker8; uint8_t startmarker8;
uint8_t startmarker9; uint8_t startmarker9;
uint8_t startmarker10; uint8_t startmarker10;
uint8_t startmarker11; uint8_t startmarker11;
/* Used to determine Kernel and Endianess */ /* Used to determine Kernel and Endianess */
uint16_t version; uint16_t version;
/* Currently 3, since v2.6.0 */ /* Currently 3, since v2.6.0 */
uint8_t minor_version; uint8_t minor_version;
/* This should be 0 if lower IRQ priority values implies higher priority /* 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., 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. */ if higher IRQ priority values means higher priority, this should be 1. */
uint8_t irq_priority_order; uint8_t irq_priority_order;
/* sizeof(RecorderDataType) - just for control */ /* sizeof(RecorderDataType) - just for control */
uint32_t filesize; uint32_t filesize;
/* Current number of events recorded */ /* Current number of events recorded */
uint32_t numEvents; uint32_t numEvents;
/* The buffer size, in number of event records */ /* The buffer size, in number of event records */
uint32_t maxEvents; uint32_t maxEvents;
/* The event buffer index, where to write the next event */ /* The event buffer index, where to write the next event */
uint32_t nextFreeIndex; uint32_t nextFreeIndex;
/* 1 if the buffer is full, 0 otherwise */ /* 1 if the buffer is full, 0 otherwise */
uint32_t bufferIsFull; uint32_t bufferIsFull;
/* The frequency of the clock/timer/counter used as time base */ /* The frequency of the clock/timer/counter used as time base */
uint32_t frequency; uint32_t frequency;
/* The absolute timestamp of the last stored event, in the native /* The absolute timestamp of the last stored event, in the native
timebase, modulo frequency! */ timebase, modulo frequency! */
uint32_t absTimeLastEvent; uint32_t absTimeLastEvent;
/* The number of seconds in total - lasts for 136 years */ /* The number of seconds in total - lasts for 136 years */
uint32_t absTimeLastEventSecond; uint32_t absTimeLastEventSecond;
/* 1 if the recorder has been started, 0 if not yet started or stopped. /* 1 if the recorder has been started, 0 if not yet started or stopped.
This is a 32 bit variable due to alignment issues. */ This is a 32 bit variable due to alignment issues. */
uint32_t recorderActive; uint32_t recorderActive;
/* Not used, remains for compatibility and future use */ /* Not used, remains for compatibility and future use */
uint8_t notused[28]; uint8_t notused[28];
/* The amount of heap memory remaining at the last malloc or free event */ /* The amount of heap memory remaining at the last malloc or free event */
uint32_t heapMemUsage; uint32_t heapMemUsage;
/* 0xF0F0F0F0 - for control only */ /* 0xF0F0F0F0 - for control only */
int32_t debugMarker0; int32_t debugMarker0;
/* Set to value of USE_16BIT_OBJECT_HANDLES */ /* Set to value of USE_16BIT_OBJECT_HANDLES */
uint32_t isUsing16bitHandles; uint32_t isUsing16bitHandles;
/* The Object Property Table holds information about currently active /* The Object Property Table holds information about currently active
tasks, queues, and other recorded objects. This is updated on each tasks, queues, and other recorded objects. This is updated on each
create call and includes object name and other properties. */ create call and includes object name and other properties. */
ObjectPropertyTableType ObjectPropertyTable; ObjectPropertyTableType ObjectPropertyTable;
/* 0xF1F1F1F1 - for control only */ /* 0xF1F1F1F1 - for control only */
int32_t debugMarker1; int32_t debugMarker1;
/* The Symbol Table stores strings for User Events and is also used to /* 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 store names of deleted objects, which still may be in the trace but no
longer are available. */ longer are available. */
symbolTableType SymbolTable; symbolTableType SymbolTable;
/* For inclusion of float support, and for endian detection of floats. /* For inclusion of float support, and for endian detection of floats.
The value should be (float)1 or (uint32_t)0 */ The value should be (float)1 or (uint32_t)0 */
#if (INCLUDE_FLOAT_SUPPORT == 1) #if (INCLUDE_FLOAT_SUPPORT == 1)
float exampleFloatEncoding; float exampleFloatEncoding;
#else #else
uint32_t exampleFloatEncoding; uint32_t exampleFloatEncoding;
#endif #endif
/* This is non-zero if an internal error occurred in the recorder, e.g., if /* 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 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 contain an error message that is displayed when attempting to view the
trace file. */ trace file. */
uint32_t internalErrorOccured; uint32_t internalErrorOccured;
/* 0xF2F2F2F2 - for control only */ /* 0xF2F2F2F2 - for control only */
int32_t debugMarker2; int32_t debugMarker2;
/* Generic system information string, presented in the tool. Note that this /* Error messages from the recorder. */
is also used for storing any internal error messages from the recorder, so char systemInfo[80];
do not make TRACE_DESCRIPTION_MAX_LENGTH too small. 80 is recommended. */
char systemInfo[TRACE_DESCRIPTION_MAX_LENGTH];
/* 0xF3F3F3F3 - for control only */ /* 0xF3F3F3F3 - for control only */
int32_t debugMarker3; int32_t debugMarker3;
/* The event data, in 4-byte records */ /* The event data, in 4-byte records */
uint8_t eventData[ EVENT_BUFFER_SIZE * 4 ]; uint8_t eventData[ EVENT_BUFFER_SIZE * 4 ];
#if (USE_SEPARATE_USER_EVENT_BUFFER == 1) #if (USE_SEPARATE_USER_EVENT_BUFFER == 1)
UserEventBuffer userEventBuffer; UserEventBuffer userEventBuffer;
@ -421,18 +429,18 @@ typedef struct
/* This should always be 0 */ /* This should always be 0 */
uint32_t endOfSecondaryBlocks; uint32_t endOfSecondaryBlocks;
uint8_t endmarker0; uint8_t endmarker0;
uint8_t endmarker1; uint8_t endmarker1;
uint8_t endmarker2; uint8_t endmarker2;
uint8_t endmarker3; uint8_t endmarker3;
uint8_t endmarker4; uint8_t endmarker4;
uint8_t endmarker5; uint8_t endmarker5;
uint8_t endmarker6; uint8_t endmarker6;
uint8_t endmarker7; uint8_t endmarker7;
uint8_t endmarker8; uint8_t endmarker8;
uint8_t endmarker9; uint8_t endmarker9;
uint8_t endmarker10; uint8_t endmarker10;
uint8_t endmarker11; uint8_t endmarker11;
} RecorderDataType; } RecorderDataType;
extern RecorderDataType* RecorderDataPtr; 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); void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength);
traceLabel prvTraceCreateSymbolTableEntry(const char* name, traceLabel prvTraceCreateSymbolTableEntry(const char* name,
uint8_t crc6, uint8_t crc6,
uint8_t len, uint8_t len,
traceLabel channel); traceLabel channel);
traceLabel prvTraceLookupSymbolTableEntry(const char* name, traceLabel prvTraceLookupSymbolTableEntry(const char* name,
uint8_t crc6, uint8_t crc6,
uint8_t len, uint8_t len,
traceLabel channel); traceLabel channel);
traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel); traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel);
@ -462,11 +470,11 @@ void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nEntries);
objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass); objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass);
void vTraceFreeObjectHandle(traceObjectClass objectclass, void vTraceFreeObjectHandle(traceObjectClass objectclass,
objectHandleType handle); objectHandleType handle);
void vTraceSetObjectName(traceObjectClass objectclass, void vTraceSetObjectName(traceObjectClass objectclass,
objectHandleType handle, objectHandleType handle,
const char* name); const char* name);
void* xTraceNextFreeEventBufferSlot(void); void* xTraceNextFreeEventBufferSlot(void);
@ -478,7 +486,7 @@ unsigned char prvTraceGet8BitHandle(objectHandleType handle);
uint16_t uiIndexOfObject(objectHandleType objecthandle, uint16_t uiIndexOfObject(objectHandleType objecthandle,
uint8_t objectclass); uint8_t objectclass);
/******************************************************************************* /*******************************************************************************
* vTraceError * 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_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_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 */ /* DEBUG ASSERTS */
#if defined USE_TRACE_ASSERT && USE_TRACE_ASSERT != 0 #if defined USE_TRACE_ASSERT && USE_TRACE_ASSERT != 0
#define TRACE_ASSERT(eval, msg, defRetVal) \ #define TRACE_ASSERT(eval, msg, defRetVal) \
@ -536,4 +541,8 @@ if (!(eval)) \
#endif #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 * Percepio AB, www.percepio.com
* *
* trcHardwarePort.h * 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. * the trace recorder library.
* *
* Terms of Use * Terms of Use
@ -12,27 +12,29 @@
* use together with Percepio products. You may distribute the recorder library * use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h * in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications * given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files. * and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be * This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written * sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB. * permission by Percepio AB.
* *
* Disclaimer * Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and * 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 * 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 * not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or * software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or * implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its * fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential, * technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings, * incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility * 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 * 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 * not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an * 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. * 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 * www.percepio.com
******************************************************************************/ ******************************************************************************/
@ -43,21 +45,21 @@
/* If Win32 port */ /* If Win32 port */
#ifdef WIN32 #ifdef WIN32
#undef _WIN32_WINNT #undef _WIN32_WINNT
#define _WIN32_WINNT 0x0600 #define _WIN32_WINNT 0x0600
/* Standard includes. */ /* Standard includes. */
#include <stdio.h> #include <stdio.h>
#include <windows.h> #include <windows.h>
#include <direct.h> #include <direct.h>
/******************************************************************************* /*******************************************************************************
* The Win32 port by default saves the trace to file and then kills the * 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 * program when the recorder is stopped, to facilitate quick, simple tests
* of the recorder. * of the recorder.
******************************************************************************/ ******************************************************************************/
#define WIN32_PORT_SAVE_WHEN_STOPPED 1 #define WIN32_PORT_SAVE_WHEN_STOPPED 1
#define WIN32_PORT_EXIT_WHEN_STOPPED 1 #define WIN32_PORT_EXIT_WHEN_STOPPED 1
#endif #endif
@ -66,104 +68,106 @@
/****************************************************************************** /******************************************************************************
* Supported ports * Supported ports
* *
* PORT_HWIndependent * 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. * resolution timestamps based on the OS tick.
* This may be used on the Win32 port, but may also be used on embedded hardware * 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, * 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 * typically 1 KHz. This means that a task or ISR that executes in less than
* 1 ms get an execution time of zero. * 1 ms get an execution time of zero.
* *
* PORT_APPLICATION_DEFINED * PORT_APPLICATION_DEFINED
* Allows for defining the port macros in other source code files. * Allows for defining the port macros in other source code files.
* *
* PORT_Win32 * 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. * builds. Note that this gives the host machine time, not the kernel time.
* *
* Hardware specific ports * Hardware specific ports
* To get accurate timestamping, a hardware timer is necessary. Below are the * To get accurate timestamping, a hardware timer is necessary. Below are the
* available ports. Some of these are "unofficial", meaning that * available ports. Some of these are "unofficial", meaning that
* they have not yet been verified by Percepio but have been contributed by * they have not yet been verified by Percepio but have been contributed by
* external developers. They should work, otherwise let us know by emailing * external developers. They should work, otherwise let us know by emailing
* support@percepio.com. Some work on any OS platform, while other are specific * support@percepio.com. Some work on any OS platform, while other are specific
* to a certain operating system. * to a certain operating system.
*****************************************************************************/ *****************************************************************************/
/****** Port Name ******************** Code ** Official ** OS Platform *******/ /****** Port Name ********************** Code ***** Official ** OS Platform *********/
#define PORT_APPLICATION_DEFINED -2 /* - - */ #define PORT_APPLICATION_DEFINED -2 /* - - */
#define PORT_NOT_SET -1 /* - - */ #define PORT_NOT_SET -1 /* - - */
#define PORT_HWIndependent 0 /* Yes Any */ #define PORT_HWIndependent 0 /* Yes Any */
#define PORT_Win32 1 /* Yes Windows (FreeRTOS)*/ #define PORT_Win32 1 /* Yes FreeRTOS on Win32 */
#define PORT_Atmel_AT91SAM7 2 /* No Any */ #define PORT_Atmel_AT91SAM7 2 /* No Any */
#define PORT_Atmel_UC3A0 3 /* No Any */ #define PORT_Atmel_UC3A0 3 /* No Any */
#define PORT_ARM_CortexM 4 /* Yes Any */ #define PORT_ARM_CortexM 4 /* Yes Any */
#define PORT_Renesas_RX600 5 /* Yes Any */ #define PORT_Renesas_RX600 5 /* Yes Any */
#define PORT_Microchip_dsPIC_AND_PIC24 6 /* Yes Any */ #define PORT_Microchip_dsPIC_AND_PIC24 6 /* Yes Any */
#define PORT_TEXAS_INSTRUMENTS_TMS570 7 /* No Any */ #define PORT_TEXAS_INSTRUMENTS_TMS570 7 /* No Any */
#define PORT_TEXAS_INSTRUMENTS_MSP430 8 /* No Any */ #define PORT_TEXAS_INSTRUMENTS_MSP430 8 /* No Any */
#define PORT_MICROCHIP_PIC32 9 /* No Any */ #define PORT_MICROCHIP_PIC32MX 9 /* Yes Any */
#define PORT_XILINX_PPC405 10 /* No FreeRTOS */ #define PORT_XILINX_PPC405 10 /* No FreeRTOS */
#define PORT_XILINX_PPC440 11 /* No FreeRTOS */ #define PORT_XILINX_PPC440 11 /* No FreeRTOS */
#define PORT_XILINX_MICROBLAZE 12 /* No Any */ #define PORT_XILINX_MICROBLAZE 12 /* No Any */
#define PORT_NXP_LPC210X 13 /* 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 * IRQ_PRIORITY_ORDER
* *
* Macro which should be defined as an integer of 0 or 1. * Macro which should be defined as an integer of 0 or 1.
* *
* This should be 0 if lower IRQ priority values implies higher priority * 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., * 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. * 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 * interrupts in priority order, in case you record interrupts using
* the vTraceStoreISRBegin and vTraceStoreISREnd routines. * the vTraceStoreISRBegin and vTraceStoreISREnd routines.
* *
****************************************************************************** ******************************************************************************
* *
* HWTC Macros * HWTC Macros
* *
* These four HWTC macros provides a hardware isolation layer representing a * These four HWTC macros provides a hardware isolation layer representing a
* generic hardware timer/counter used for driving the operating system tick, * 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 * such as the SysTick feature of ARM Cortex M3/M4, or the PIT of the Atmel
* AT91SAM7X. * AT91SAM7X.
* *
* HWTC_COUNT: The current value of the counter. This is expected to be reset * 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 * a each tick interrupt. Thus, when the tick handler starts, the counter has
* already wrapped. * already wrapped.
* *
* HWTC_COUNT_DIRECTION: Should be one of: * HWTC_COUNT_DIRECTION: Should be one of:
* - DIRECTION_INCREMENTING - for hardware timer/counters of incrementing type * - DIRECTION_INCREMENTING - for hardware timer/counters of incrementing type
* such as the PIT on Atmel AT91SAM7X. * such as the PIT on Atmel AT91SAM7X.
* When the counter value reach HWTC_PERIOD, it is reset to zero and the * When the counter value reach HWTC_PERIOD, it is reset to zero and the
* interrupt is signaled. * interrupt is signaled.
* - DIRECTION_DECREMENTING - for hardware timer/counters of decrementing type * - DIRECTION_DECREMENTING - for hardware timer/counters of decrementing type
* such as the SysTick on ARM Cortex M3/M4 chips. * such as the SysTick on ARM Cortex M3/M4 chips.
* When the counter value reach 0, it is reset to HWTC_PERIOD and the * When the counter value reach 0, it is reset to HWTC_PERIOD and the
* interrupt is signaled. * interrupt is signaled.
* *
* HWTC_PERIOD: The number of increments or decrements of HWTC_COUNT between * HWTC_PERIOD: The number of increments or decrements of HWTC_COUNT between
* two OS tick interrupts. This should preferably be mapped to the reload * 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). * 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) * #define HWTC_PERIOD (configCPU_CLOCK_HZ / configTICK_RATE_HZ)
* *
* HWTC_DIVISOR: If the timer frequency is very high, like on the Cortex M chips * 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 * (where the SysTick runs at the core clock frequency), the "differential
* timestamping" used in the recorder will more frequently insert extra XTS * timestamping" used in the recorder will more frequently insert extra XTS
* events to store the timestamps, which increases the event buffer usage. * 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 * 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. * 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 * 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 * 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 * Cortex M chip running at 72 MHZ should use a HWTC_DIVISOR of 2, while a
* faster chip require a higher HWTC_DIVISOR value. * faster chip require a higher HWTC_DIVISOR value.
* *
* The HWTC macros and vTracePortGetTimeStamp is the main porting issue * The HWTC macros and vTracePortGetTimeStamp is the main porting issue
* or the trace recorder library. Typically you should not need to change * or the trace recorder library. Typically you should not need to change
@ -172,164 +176,172 @@
******************************************************************************/ ******************************************************************************/
#if (SELECTED_PORT == PORT_Win32) #if (SELECTED_PORT == PORT_Win32)
// This can be used as a template for any free-running 32-bit counter // This can be used as a template for any free-running 32-bit counter
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (ulGetRunTimeCounterValue()) #define HWTC_COUNT (ulGetRunTimeCounterValue())
#define HWTC_PERIOD 0 #define HWTC_PERIOD 0
#define HWTC_DIVISOR 1 #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... // 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) #elif (SELECTED_PORT == PORT_ARM_CortexM)
void prvTraceSetIRQMask(uint32_t priMask);
uint32_t prvTraceGetIRQMask(void);
void prvTraceEnableIRQ(void);
void prvTraceDisableIRQ(void);
void prvTraceInitCortexM(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 REG_DEMCR (*(volatile unsigned int*)0xE000EDFC)
#define HWTC_COUNT (DWT_CYCLE_COUNTER + DWT_CYCLES_ADDED) #define REG_DWT_CTRL (*(volatile unsigned int*)0xE0001000)
#define HWTC_PERIOD 0 #define REG_DWT_CYCCNT (*(volatile unsigned int*)0xE0001004)
#define HWTC_DIVISOR 4 #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 /* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_CYCCNT */
#define HWTC_COUNT (CMT0.CMCNT) #define DWT_CTRL_CYCCNTENA (1)
#define HWTC_PERIOD (CMT0.CMCOR + 1)
#define HWTC_DIVISOR 1 #define PORT_SPECIFIC_INIT() prvTraceInitCortexM()
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
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) #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 /* 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. 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 In comparison, this is 10-20 times faster on a 32-bit MCU... */
becomes a problem on PIC24, use the filters to exclude less interesting tasks
or system calls. */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (TMR1) #define HWTC_COUNT (TMR1)
#define HWTC_PERIOD (PR1+1) #define HWTC_PERIOD (PR1+1)
#define HWTC_DIVISOR 1 #define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant #define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_Atmel_AT91SAM7) #elif (SELECTED_PORT == PORT_Atmel_AT91SAM7)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT ((uint32_t)(AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF)) #define HWTC_COUNT ((uint32_t)(AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF))
#define HWTC_PERIOD ((uint32_t)(AT91C_BASE_PITC->PITC_PIMR + 1)) #define HWTC_PERIOD ((uint32_t)(AT91C_BASE_PITC->PITC_PIMR + 1))
#define HWTC_DIVISOR 1 #define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant #define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_Atmel_UC3A0) #elif (SELECTED_PORT == PORT_Atmel_UC3A0)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* For Atmel AVR32 (AT32UC3A).*/ /* For Atmel AVR32 (AT32UC3A).*/
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT ((uint32_t)sysreg_read(AVR32_COUNT)) #define HWTC_COUNT ((uint32_t)sysreg_read(AVR32_COUNT))
#define HWTC_PERIOD ((uint32_t)(sysreg_read(AVR32_COMPARE) + 1)) #define HWTC_PERIOD ((uint32_t)(sysreg_read(AVR32_COMPARE) + 1))
#define HWTC_DIVISOR 1 #define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant #define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_NXP_LPC210X) #elif (SELECTED_PORT == PORT_NXP_LPC210X)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* Tested with LPC2106, but should work with most LPC21XX chips. */ /* Tested with LPC2106, but should work with most LPC21XX chips. */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT *((uint32_t *)0xE0004008 ) #define HWTC_COUNT *((uint32_t *)0xE0004008 )
#define HWTC_PERIOD *((uint32_t *)0xE0004018 ) #define HWTC_PERIOD *((uint32_t *)0xE0004018 )
#define HWTC_DIVISOR 1 #define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant #define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_TMS570) #elif (SELECTED_PORT == PORT_TEXAS_INSTRUMENTS_TMS570)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define RTIFRC0 *((uint32_t *)0xFFFFFC10) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#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 #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) #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_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (TA0R) #define HWTC_COUNT (TA0R)
#define HWTC_PERIOD (((uint16_t)TACCR0)+1) #define HWTC_PERIOD (((uint16_t)TACCR0)+1)
#define HWTC_DIVISOR 1 #define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant #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
#elif (SELECTED_PORT == PORT_XILINX_PPC405) #elif (SELECTED_PORT == PORT_XILINX_PPC405)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT mfspr(0x3db)
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT mfspr(0x3db)
#if (defined configCPU_CLOCK_HZ && defined configTICK_RATE_HZ) // Check if FreeRTOS #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. */ /* 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 #define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) // Same as in port.c for PPC405
#else #else
/* Not defined for other operating systems yet */ /* Not defined for other operating systems yet */
#error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick. #error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick.
#endif #endif
#define HWTC_DIVISOR 1 #define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant #define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_XILINX_PPC440) #elif (SELECTED_PORT == PORT_XILINX_PPC440)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
/* This should work with most PowerPC chips */ /* This should work with most PowerPC chips */
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING #define HWTC_COUNT_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 #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. */ /* 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 #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 */ /* Not defined for other operating systems yet */
#error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick. #error HWTC_PERIOD must be defined to give the number of hardware timer ticks per OS tick.
#endif #endif
#define HWTC_DIVISOR 1 #define HWTC_DIVISOR 1
#define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant #define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_XILINX_MICROBLAZE) #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. /* This should work with most Microblaze configurations.
* It uses the AXI Timer 0 - the tick interrupt source. * 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. * If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required.
*/ */
#include "xtmrctr_l.h" #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 #define IRQ_PRIORITY_ORDER 0 // lower IRQ priority values are more significant
#elif (SELECTED_PORT == PORT_APPLICATION_DEFINED) #elif (SELECTED_PORT == PORT_APPLICATION_DEFINED)
@ -364,47 +402,47 @@
#elif (SELECTED_PORT != PORT_NOT_SET) #elif (SELECTED_PORT != PORT_NOT_SET)
#error "SELECTED_PORT had unsupported value!" #error "SELECTED_PORT had unsupported value!"
#define SELECTED_PORT PORT_NOT_SET #define SELECTED_PORT PORT_NOT_SET
#endif #endif
#if (SELECTED_PORT != PORT_NOT_SET) #if (SELECTED_PORT != PORT_NOT_SET)
#ifndef HWTC_COUNT_DIRECTION #ifndef HWTC_COUNT_DIRECTION
#error "HWTC_COUNT_DIRECTION is not set!" #error "HWTC_COUNT_DIRECTION is not set!"
#endif #endif
#ifndef HWTC_COUNT #ifndef HWTC_COUNT
#error "HWTC_COUNT is not set!" #error "HWTC_COUNT is not set!"
#endif #endif
#ifndef HWTC_PERIOD #ifndef HWTC_PERIOD
#error "HWTC_PERIOD is not set!" #error "HWTC_PERIOD is not set!"
#endif #endif
#ifndef HWTC_DIVISOR #ifndef HWTC_DIVISOR
#error "HWTC_DIVISOR is not set!" #error "HWTC_DIVISOR is not set!"
#endif #endif
#ifndef IRQ_PRIORITY_ORDER #ifndef IRQ_PRIORITY_ORDER
#error "IRQ_PRIORITY_ORDER is not set!" #error "IRQ_PRIORITY_ORDER is not set!"
#elif (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1) #elif (IRQ_PRIORITY_ORDER != 0) && (IRQ_PRIORITY_ORDER != 1)
#error "IRQ_PRIORITY_ORDER has bad value!" #error "IRQ_PRIORITY_ORDER has bad value!"
#endif #endif
#if (HWTC_DIVISOR < 1) #if (HWTC_DIVISOR < 1)
#error "HWTC_DIVISOR must be a non-zero positive value!" #error "HWTC_DIVISOR must be a non-zero positive value!"
#endif #endif
#endif #endif
/******************************************************************************* /*******************************************************************************
* vTraceConsoleMessage * vTraceConsoleMessage
* *
* A wrapper for your system-specific console "printf" console output function. * 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). * status monitor task (this is defined in trcUser.c).
******************************************************************************/ ******************************************************************************/
#define vTraceConsoleMessage(x) #define vTraceConsoleMessage(x)
/******************************************************************************* /*******************************************************************************
@ -420,14 +458,4 @@
******************************************************************************/ ******************************************************************************/
void vTracePortGetTimeStamp(uint32_t *puiTimestamp); 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 #endif

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library * Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcKernel.h * trcKernel.h
@ -55,10 +55,10 @@ void vTraceStoreTaskswitch(objectHandleType task_handle);
void vTraceStoreKernelCall(uint32_t eventcode, traceObjectClass objectClass, uint32_t byteParam); void vTraceStoreKernelCall(uint32_t eventcode, traceObjectClass objectClass, uint32_t byteParam);
void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode,
uint32_t param); uint32_t param);
void vTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass, void vTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass,
uint32_t objectNumber, uint32_t param); uint32_t objectNumber, uint32_t param);
void vTraceSetTaskInstanceFinished(objectHandleType handle); void vTraceSetTaskInstanceFinished(objectHandleType handle);
@ -73,18 +73,19 @@ uint8_t uiTraceGetObjectState(uint8_t objectclass, objectHandleType id);
#if (INCLUDE_OBJECT_DELETE == 1) #if (INCLUDE_OBJECT_DELETE == 1)
void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle, void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass); traceObjectClass objectclass);
void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle, void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass); traceObjectClass objectclass);
#endif #endif
/* Internal constants for task state */ /* Internal constants for task state */
#define TASK_STATE_INSTANCE_NOT_ACTIVE 0 #define TASK_STATE_INSTANCE_NOT_ACTIVE 0
#define TASK_STATE_INSTANCE_ACTIVE 1 #define TASK_STATE_INSTANCE_ACTIVE 1
#define TASK_STATE_INSTANCE_MARKED_FINISHED 2
#endif #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 * Percepio AB, www.percepio.com
* *
* trcKernelHooks.h * trcKernelHooks.h
@ -12,7 +12,7 @@
* compile-time errors. * compile-time errors.
* *
* #ifdef __ICCARM__ * #ifdef __ICCARM__
* #include "percepio/Include/trcKernelHooks.h" * #include "trcKernelPort.h"
* #endif * #endif
* *
* Terms of Use * 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); \ vTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_TIMER_NUMBER(pxTimer), TRACE_CLASS_TIMER); \
vTraceFreeObjectHandle(TRACE_CLASS_TIMER, TRACE_GET_TIMER_NUMBER(pxTimer)); 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 * Percepio AB, www.percepio.com
* *
* trcKernelPort.h * trcKernelPort.h
* *
* Kernel-specific functionality for FreeRTOS, used by the recorder library. * Wrapper for kernel-specific port (trcKernelPort<KERNEL>.h)
* *
* Terms of Use * Terms of Use
* This software is copyright Percepio AB. The recorder library is free for * 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 * 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. * 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 * www.percepio.com
******************************************************************************/ ******************************************************************************/
/* Change the included file below, if using the recorder with other kernels */
#ifndef TRCKERNELPORT_H_ #include "trcKernelPortFreeRTOS.h"
#define TRCKERNELPORT_H_ /* #include "trcKernelPort<OTHERKERNEL>.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_ */

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library * Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcTypes.h * trcTypes.h
@ -31,7 +31,9 @@
* damages, or the exclusion of implied warranties or limitations on how long an * 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. * 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 * 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 * Percepio AB, www.percepio.com
* *
* trcUser.h * trcUser.h
@ -30,7 +30,9 @@
* damages, or the exclusion of implied warranties or limitations on how long an * 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. * 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 * www.percepio.com
******************************************************************************/ ******************************************************************************/
@ -82,6 +84,13 @@ void vTraceInitTraceData(void);
void vTraceSetRecorderData(void* pRecorderData); void vTraceSetRecorderData(void* pRecorderData);
#endif #endif
/*******************************************************************************
* vTraceSetStopHook
*
* Sets a function to be called when the recorder is stopped.
******************************************************************************/
void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction);
/******************************************************************************* /*******************************************************************************
* uiTraceStart * uiTraceStart
* *
@ -154,21 +163,17 @@ void vTraceClearError(int resetErrorMessage);
* started. * started.
* *
* Example: * Example:
* #define ID_ISR_TIMER1 1 // lowest valid ID is 1 * #define ID_ISR_TIMER1 1 // lowest valid ID is 1
* #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
* ... * ...
* vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1); * vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);
* ... * ...
* void ISR_handler() * void ISR_handler()
* { * {
* portENTER_CRITICAL(); // Required if nested ISRs are allowed * vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1); * ...
* portEXIT_CRITICAL(); * vTraceStoreISREnd(0);
* ... * }
* portENTER_CRITICAL(); // Required if nested ISRs are allowed
* vTraceStoreISREnd();
* portEXIT_CRITICAL();
* }
******************************************************************************/ ******************************************************************************/
void vTraceSetISRProperties(objectHandleType handle, const char* name, char priority); 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. * If allowing nested ISRs, this must be called with interrupts disabled.
* *
* Example: * Example:
* #define ID_ISR_TIMER1 1 // lowest valid ID is 1 * #define ID_ISR_TIMER1 1 // lowest valid ID is 1
* #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
* ... * ...
* vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1); * vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);
* ... * ...
* void ISR_handler() * void ISR_handler()
* { * {
* portENTER_CRITICAL(); // Required if nested ISRs are allowed * vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1); * ...
* portEXIT_CRITICAL(); * vTraceStoreISREnd(0);
* ... * }
* portENTER_CRITICAL(); // Required if nested ISRs are allowed
* vTraceStoreISREnd();
* portEXIT_CRITICAL();
* }
* *
******************************************************************************/ ******************************************************************************/
void vTraceStoreISRBegin(objectHandleType id); void vTraceStoreISRBegin(objectHandleType id);
@ -203,30 +204,27 @@ void vTraceStoreISRBegin(objectHandleType id);
* *
* Registers the end of an Interrupt Service Routine. * 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: * Example:
* #define ID_ISR_TIMER1 1 // lowest valid ID is 1 * #define ID_ISR_TIMER1 1 // lowest valid ID is 1
* #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
* ... * ...
* vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1); * vTraceSetISRProperties(ID_ISR_TIMER1, "ISRTimer1", PRIO_OF_ISR_TIMER1);
* ... * ...
* void ISR_handler() * void ISR_handler()
* { * {
* portENTER_CRITICAL(); // Required if nested ISRs are allowed * vTraceStoreISRBegin(ID_OF_ISR_TIMER1);
* vTraceStoreISRBegin(ID_OF_ISR_TIMER1); * ...
* portEXIT_CRITICAL(); * vTraceStoreISREnd(0);
* ... * }
* portENTER_CRITICAL(); // Required if nested ISRs are allowed
* vTraceStoreISREnd();
* portEXIT_CRITICAL();
* }
* *
******************************************************************************/ ******************************************************************************/
void vTraceStoreISREnd(void); void vTraceStoreISREnd(int pendingISR);
#else #else
/* If not including the ISR recording */ /* If not including the ISR recording */
void vTraceIncreaseISRActive(void); void vTraceIncreaseISRActive(void);
@ -238,28 +236,59 @@ void vTraceDecreaseISRActive(void);
#endif #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 * Marks the current task instance as finished on the next kernel call.
* 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 * If that kernel call is blocking, the instance ends after the blocking event
* should be called right before the api function call considered to be the end * and the corresponding return event is then the start of the next instance.
* of the task instamce, i.e., the Instance Finish Event. * 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
void vTraceTaskInstanceIsFinished(void); * 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 * vTraceGetTraceBuffer
@ -292,7 +321,7 @@ uint32_t uiTraceGetTraceBufferSize(void);
* When logging a user event, a numeric handle (reference) to this string is * When logging a user event, a numeric handle (reference) to this string is
* used to identify the event. This is obtained by calling * used to identify the event. This is obtained by calling
* *
* xTraceOpenLabel() * xTraceOpenLabel()
* *
* whihc adds the string to the symbol table (if not already present) * whihc adds the string to the symbol table (if not already present)
* and returns the corresponding handle. * 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. * 1. The handle is looked up every time, when storing the user event.
* *
* Example: * Example:
* vTraceUserEvent(xTraceOpenLabel("MyUserEvent")); * vTraceUserEvent(xTraceOpenLabel("MyUserEvent"));
* *
* 2. The label is registered just once, with the handle stored in an * 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: * Example:
* myEventHandle = xTraceOpenLabel("MyUserEvent"); * myEventHandle = xTraceOpenLabel("MyUserEvent");
* ... * ...
* vTraceUserEvent(myEventHandle); * vTraceUserEvent(myEventHandle);
* *
* The second option is faster since no lookup is required on each event, and * The second option is faster since no lookup is required on each event, and
* therefore recommended for user events that are frequently * therefore recommended for user events that are frequently
@ -342,17 +371,17 @@ void vTraceUserEvent(traceLabel eventLabel);
* User Event labels are created using xTraceOpenLabel. * User Event labels are created using xTraceOpenLabel.
* Example: * Example:
* *
* traceLabel adc_uechannel = xTraceOpenLabel("ADC User Events"); * traceLabel adc_uechannel = xTraceOpenLabel("ADC User Events");
* ... * ...
* vTracePrint(adc_uechannel, * vTracePrint(adc_uechannel,
* "ADC channel %d: %lf volts", * "ADC channel %d: %lf volts",
* ch, (double)adc_reading/(double)scale); * ch, (double)adc_reading/(double)scale);
* *
* This can be combined into one line, if desired, but this is slower: * This can be combined into one line, if desired, but this is slower:
* *
* vTracePrint(xTraceOpenLabel("ADC User Events"), * vTracePrint(xTraceOpenLabel("ADC User Events"),
* "ADC channel %d: %lf volts", * "ADC channel %d: %lf volts",
* ch, (double)adc_reading/(double)scale); * ch, (double)adc_reading/(double)scale);
* *
* Calling xTraceOpenLabel multiple times will not create duplicate entries, but * 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 * 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. * better to use vTraceUserEvent - it is faster.
* *
* Format specifiers supported: * Format specifiers supported:
* %d - 32 bit signed integer * %d - 32 bit signed integer
* %u - 32 bit unsigned integer * %u - 32 bit unsigned integer
* %f - 32 bit float * %f - 32 bit float
* %s - string (is copied to the recorder symbol table) * %s - string (is copied to the recorder symbol table)
* %hd - 16 bit signed integer * %hd - 16 bit signed integer
* %hu - 16 bit unsigned integer * %hu - 16 bit unsigned integer
* %bd - 8 bit signed integer * %bd - 8 bit signed integer
* %bu - 8 bit unsigned integer * %bu - 8 bit unsigned integer
* %lf - double-precision float (Note! See below...) * %lf - double-precision float (Note! See below...)
* *
* Up to 15 data arguments are allowed, with a total size of maximum 32 byte. * 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. * 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. * unless the higher precision is really necessary.
* *
* Note that the double-precision float (%lf) assumes a 64 bit double * 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 * 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. * "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 vTracePrintF(eventLabel,formatStr,...)
#define vTraceExcludeTaskFromSchedulingTrace(name) #define vTraceExcludeTaskFromSchedulingTrace(name)
#define vTraceTaskSkipDefaultInstanceFinishedEvents()
#define vTraceSetISRProperties(handle, name, priority) #define vTraceSetISRProperties(handle, name, priority)
#define vTraceStoreISRBegin(id) #define vTraceStoreISRBegin(id)
#define vTraceStoreISREnd() #define vTraceStoreISREnd()
@ -427,6 +455,7 @@ void vTraceChannelUserEvent(UserEventChannel channel);
#define vTraceSetSemaphoreName(a, b) #define vTraceSetSemaphoreName(a, b)
#define vTraceSetEventGroupName(a, b) #define vTraceSetEventGroupName(a, b)
#define vTraceSetStopHook(a)
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -4,21 +4,22 @@ Tracealyzer Trace Recorder Library
Percepio AB Percepio AB
www.percepio.com 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 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 Files included
-------------- --------------
- trcConfig.h - The recorder's configuration file, set your recorder configuration here! - 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). - 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. - trcKernel.c/.h - Internal routines for storing kernel events.
- trcBase.c/.h - Internal routines for manipulating the data structures and calculating timestamps. - trcBase.c/.h - Internal routines for manipulating the data structures and calculating timestamps.
- trcHardwarePort.c/.h - The hardware interface, especially for timestamping. - trcHardwarePort.c/.h - The hardware interface, especially for timestamping.
- trcKernelPort.c/.h - Kernel specific implementations of macros and data. - trcKernelPort.h - Wrapper for trcKernelPortFreeRTOS.h (for portability).
- trcKernelHooks.h - The trace macro defines (OS independent). - trcKernelPortFreeRTOS.c/.h - FreeRTOS-specific trace macros and helper functions.
- trcTypes.h - Type definitions used. - trcKernelHooks.h - Generic trace macros (OS independent), used by trcKernelPortFreeRTOS.
- trcTypes.h - Type definitions used.
Hardware Timer Ports Hardware Timer Ports
-------------------- --------------------
@ -29,17 +30,19 @@ This release contains hardware timer ports for the following hardware architectu
- Atmel AT32UC3 (AVR32) - Atmel AT32UC3 (AVR32)
- Renesas RX600 (e.g., RX62N) - Renesas RX600 (e.g., RX62N)
- Microchip dsPIC/PIC24 - Microchip dsPIC/PIC24
- Microchip PIC32 - Microchip PIC32MX
- Microchip PIC32MZ
- NXP LPC2106 - NXP LPC2106
- Texas Instruments TMS570 (Cortex-R4) - Texas Instruments TMS570 (Cortex-R4)
- Texas Instruments MSP430 - Texas Instruments MSP430
- Xilinx PowerPC 405 - Xilinx PowerPC 405
- Xilinx PowerPC 440 - Xilinx PowerPC 440
- Xilinx Microblaze - Xilinx Microblaze
- ARM Cortex-A9
These are defined in trcHardwarePort.h. Some of these are "unofficial" ports, provided by external contributors. 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. 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 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. 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 * Percepio AB, www.percepio.com
* *
* trcHardwarePort.c * trcHardwarePort.c
@ -32,7 +32,9 @@
* damages, or the exclusion of implied warranties or limitations on how long an * 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. * 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 * www.percepio.com
******************************************************************************/ ******************************************************************************/
@ -56,36 +58,37 @@ uint32_t last_timestamp = 0;
******************************************************************************/ ******************************************************************************/
uint32_t uiTraceTickCount = 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) #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() void prvTraceInitCortexM()
{ {
DWT_CTRL_REG |= 1; /* Enable the cycle counter */ /* Make sure DWT is enabled is enabled, if supported */
DWT_CYCLE_COUNTER = 0; 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) if (RecorderDataPtr->frequency == 0)
{ {
@ -109,10 +112,10 @@ void prvTraceInitCortexM()
void vTracePortGetTimeStamp(uint32_t *pTimestamp) void vTracePortGetTimeStamp(uint32_t *pTimestamp)
{ {
static uint32_t last_traceTickCount = 0; static uint32_t last_traceTickCount = 0;
static uint32_t last_hwtc_count = 0; static uint32_t last_hwtc_count = 0;
uint32_t traceTickCount = 0; uint32_t traceTickCount = 0;
uint32_t hwtc_count = 0; uint32_t hwtc_count = 0;
if (trace_disable_timestamp == 1) if (trace_disable_timestamp == 1)
{ {
if (pTimestamp) if (pTimestamp)
@ -120,51 +123,64 @@ void vTracePortGetTimeStamp(uint32_t *pTimestamp)
return; 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) #if (HWTC_COUNT_DIRECTION == DIRECTION_INCREMENTING)
hwtc_count = HWTC_COUNT; hwtc_count = HWTC_COUNT;
#elif (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING) #elif (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING)
hwtc_count = HWTC_PERIOD - HWTC_COUNT; hwtc_count = HWTC_PERIOD - HWTC_COUNT;
#else #else
Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly! Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly!
Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING
#endif #endif
if (last_traceTickCount - uiTraceTickCount - 1 < 0x80000000)
{
/* This means last_traceTickCount is higher than uiTraceTickCount,
so we have previously compensated for a missed tick.
Therefore we use the last stored value because that is more accurate. */
traceTickCount = last_traceTickCount;
}
else
{
/* Business as usual */
traceTickCount = uiTraceTickCount;
}
/* Check for overflow. May occur if the update of uiTraceTickCount has been #if (SELECTED_PORT == PORT_Win32)
delayed due to disabled interrupts. */ /* The Win32 port uses ulGetRunTimeCounterValue for timestamping, which in turn
if (traceTickCount == last_traceTickCount && hwtc_count < last_hwtc_count) uses QueryPerformanceCounter. That function is not always reliable when used over
{ multiple threads. We must therefore handle rare cases where the timestamp is less
/* A trace tick has occurred but not been executed by the kernel, so we compensate manually. */ than the previous. In practice, the Win32 should "never" roll over since the
traceTickCount++; performance counter is 64 bit wide. */
}
if (last_hwtc_count > hwtc_count)
/* Check if the return address is OK, then we perform the calculation. */ {
if (pTimestamp) hwtc_count = last_hwtc_count;
{ }
/* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */ #endif
*pTimestamp = traceTickCount * (HWTC_PERIOD / HWTC_DIVISOR);
/* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / HWTC_DIVISOR. */ if (last_traceTickCount - uiTraceTickCount - 1 < 0x80000000)
*pTimestamp += (hwtc_count + traceTickCount * (HWTC_PERIOD % HWTC_DIVISOR)) / HWTC_DIVISOR; {
/* 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; last_timestamp = *pTimestamp;
} }
/* Store the previous values. */ /* Store the previous values. */
last_traceTickCount = traceTickCount; last_traceTickCount = traceTickCount;
last_hwtc_count = hwtc_count; 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 * Percepio AB, www.percepio.com
* *
* trcKernel.c * trcKernel.c
* *
* Functions used by trcKernelHooks.h. * Functions used by trcKernelHooks.h for storing various kernel events.
* *
* Terms of Use * Terms of Use
* This software is copyright Percepio AB. The recorder library is free for * 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 * 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. * 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 * www.percepio.com
******************************************************************************/ ******************************************************************************/
@ -46,7 +48,12 @@ uint8_t nISRactive = 0;
objectHandleType handle_of_last_logged_task = 0; objectHandleType handle_of_last_logged_task = 0;
uint8_t inExcludedTask = 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); static uint32_t prvTraceGetParam(uint32_t, uint32_t);
#endif
#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1 #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) void vTraceStoreTaskReady(objectHandleType handle)
{ {
uint16_t dts3; uint16_t dts3;
TREvent* tr; TREvent* tr;
uint8_t hnd8;
TRACE_SR_ALLOC_CRITICAL_SECTION(); TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(handle > 0 && handle <= NTask, "vTraceStoreTaskReady: Invalid value for handle", );
if (recorder_busy) if (handle == 0)
{ {
/*********************************************************************** /* On FreeRTOS v7.3.0, this occurs when creating tasks due to a bad
* This should never occur, as the tick- and kernel call ISR is on lowest placement of the trace macro. In that case, the events are ignored. */
* interrupt priority and always are disabled during the critical sections return;
* of the recorder. }
***********************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (1)"); TRACE_ASSERT(handle <= NTask, "vTraceStoreTaskReady: Invalid value for handle", );
return;
} 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(); 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)) if (!TRACE_GET_TASK_FLAG_ISEXCLUDED(handle))
{ {
dts3 = (uint16_t)prvTraceGetDTS(0xFFFF); 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->type = DIV_TASK_READY;
tr->dts = dts3;
tr = (TREvent*)xTraceNextFreeEventBufferSlot(); tr->objHandle = hnd8;
prvTraceUpdateCounters();
if (tr != NULL)
{
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) void vTraceStoreLowPower(uint32_t flag)
{ {
uint16_t dts; uint16_t dts;
LPEvent* lp; LPEvent* lp;
TRACE_SR_ALLOC_CRITICAL_SECTION(); TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(flag <= 1, "vTraceStoreLowPower: Invalid flag value", ); 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 * This should never occur, as the tick- and kernel call ISR is on lowest
* interrupt priority and always are disabled during the critical sections * interrupt priority and always are disabled during the critical sections
* of the recorder. * of the recorder.
***********************************************************************/ ***********************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (1)"); vTraceError("Recorder busy - high priority ISR using syscall? (1)");
return; return;
} }
trcCRITICAL_SECTION_BEGIN(); trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ if (RecorderDataPtr->recorderActive)
{ {
dts = (uint16_t)prvTraceGetDTS(0xFFFF); dts = (uint16_t)prvTraceGetDTS(0xFFFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ lp = (LPEvent*)xTraceNextFreeEventBufferSlot();
if (lp != NULL)
{ {
lp = (LPEvent*)xTraceNextFreeEventBufferSlot(); lp->type = LOW_POWER_BEGIN + ( uint8_t ) flag; /* BEGIN or END depending on flag */
if (lp != NULL) 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(); trcCRITICAL_SECTION_END();
@ -149,62 +155,79 @@ void vTraceStoreLowPower(uint32_t flag)
* vTraceStoreMemMangEvent * vTraceStoreMemMangEvent
* *
* This function stores malloc and free events. Each call requires two records, * This function stores malloc and free events. Each call requires two records,
* for size and address respectively. The event code parameter (ecode) is applied * for size and address respectively. The event code parameter (ecode) is applied
* to the first record (size) and the following address record gets event * 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. * 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) #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; uint8_t dts1;
MemEventSize * ms; MemEventSize * ms;
MemEventAddr * ma; MemEventAddr * ma;
uint16_t size_low; uint16_t size_low;
uint16_t addr_low; uint16_t addr_low;
uint8_t addr_high; 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(); TRACE_SR_ALLOC_CRITICAL_SECTION();
trcCRITICAL_SECTION_BEGIN(); trcCRITICAL_SECTION_BEGIN();
heapMemUsage += signed_size;
if (RecorderDataPtr->recorderActive) if (RecorderDataPtr->recorderActive)
{ {
/* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */ /* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */
if (nISRactive || !inExcludedTask) if (nISRactive || !inExcludedTask)
{ {
dts1 = (uint8_t)prvTraceGetDTS(0xFF); dts1 = (uint8_t)prvTraceGetDTS(0xFF);
size_low = (uint16_t)prvTraceGetParam(0xFFFF, size); size_low = (uint16_t)prvTraceGetParam(0xFFFF, size);
ms = (MemEventSize *)xTraceNextFreeEventBufferSlot(); ms = (MemEventSize *)xTraceNextFreeEventBufferSlot();
if (ms != NULL) if (ms != NULL)
{ {
ms->dts = dts1; ms->dts = dts1;
ms->type = (uint8_t)ecode; ms->type = NULL_EVENT; /* Updated when all events are written */
ms->size = size_low; ms->size = size_low;
prvTraceUpdateCounters(); prvTraceUpdateCounters();
/* Storing a second record with address (signals "failed" if null) */ /* Storing a second record with address (signals "failed" if null) */
#if (HEAP_SIZE_BELOW_16M) #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; addr_high = (address >> 16) & 0xFF;
#else #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_low = (uint16_t)prvTraceGetParam(0xFFFF, address);
addr_high = 0; addr_high = 0;
#endif #endif
ma = (MemEventAddr *) xTraceNextFreeEventBufferSlot(); ma = (MemEventAddr *) xTraceNextFreeEventBufferSlot();
if (ma != NULL) if (ma != NULL)
{ {
ma->addr_low = addr_low; ma->addr_low = addr_low;
ma->addr_high = addr_high; ma->addr_high = addr_high;
ma->type = ( ( uint8_t) ecode ) + 1; /* Note this! */ ma->type = ( ( uint8_t) ecode ) + 1; /* Note this! */
prvTraceUpdateCounters(); ms->type = (uint8_t)ecode;
prvTraceUpdateCounters();
RecorderDataPtr->heapMemUsage = heapMemUsage;
} }
} }
} }
} }
trcCRITICAL_SECTION_END(); trcCRITICAL_SECTION_END();
#endif /* TRACE_SCHEDULING_ONLY */
} }
#endif #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) void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber)
{ {
KernelCall * kse; #if (TRACE_SCHEDULING_ONLY == 0)
uint16_t dts1; KernelCall * kse;
TRACE_SR_ALLOC_CRITICAL_SECTION(); uint16_t dts1;
uint8_t hnd8;
TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(ecode < 0xFF, "vTraceStoreKernelCall: ecode >= 0xFF", ); TRACE_ASSERT(ecode < 0xFF, "vTraceStoreKernelCall: ecode >= 0xFF", );
TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCall: objectClass >= TRACE_NCLASSES", ); TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCall: objectClass >= TRACE_NCLASSES", );
TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCall: Invalid value for objectNumber", ); TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCall: Invalid value for objectNumber", );
if (recorder_busy) if (recorder_busy)
{ {
/************************************************************************* /*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call, * This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event. * or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls * Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY). * or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/ *************************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (2)"); vTraceError("Recorder busy - high priority ISR using syscall? (2)");
return; return;
} }
if (handle_of_last_logged_task == 0) if (handle_of_last_logged_task == 0)
{ {
return; return;
} }
trcCRITICAL_SECTION_BEGIN(); trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive) if (RecorderDataPtr->recorderActive)
{ {
/* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */ /* If it is an ISR or NOT an excluded task, this kernel call will be stored in the trace */
if (nISRactive || !inExcludedTask) if (nISRactive || !inExcludedTask)
{ {
/* Check if the referenced object or the event code is excluded */ /* Check if the referenced object or the event code is excluded */
if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode)) if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))
{ {
dts1 = (uint16_t)prvTraceGetDTS(0xFFFF); dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);
hnd8 = prvTraceGet8BitHandle(objectNumber);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ kse = (KernelCall*) xTraceNextFreeEventBufferSlot();
{ if (kse != NULL)
uint8_t hnd8 = prvTraceGet8BitHandle(objectNumber); {
kse->dts = dts1;
kse = (KernelCall*) xTraceNextFreeEventBufferSlot(); kse->type = (uint8_t)ecode;
if (kse != NULL) kse->objHandle = hnd8;
{ prvTraceUpdateCounters();
kse->dts = dts1; }
kse->type = (uint8_t)ecode; }
kse->objHandle = hnd8; }
prvTraceUpdateCounters(); }
}
}
}
}
}
trcCRITICAL_SECTION_END(); trcCRITICAL_SECTION_END();
#endif /* TRACE_SCHEDULING_ONLY */
} }
/******************************************************************************* /*******************************************************************************
* vTraceStoreKernelCallWithParam * 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 * numeric parameter does not fit in one byte, and extra XPS event is inserted
* before the kernel call event containing the three upper bytes. * before the kernel call event containing the three upper bytes.
******************************************************************************/ ******************************************************************************/
void vTraceStoreKernelCallWithParam(uint32_t evtcode, void vTraceStoreKernelCallWithParam(uint32_t evtcode,
traceObjectClass objectClass, traceObjectClass objectClass,
uint32_t objectNumber, uint32_t objectNumber,
uint32_t param) uint32_t param)
{ {
KernelCallWithParamAndHandle * kse; #if (TRACE_SCHEDULING_ONLY == 0)
uint8_t dts2; KernelCallWithParamAndHandle * kse;
TRACE_SR_ALLOC_CRITICAL_SECTION(); uint8_t dts2;
uint8_t hnd8;
uint8_t p8;
TRACE_SR_ALLOC_CRITICAL_SECTION();
TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCall: evtcode >= 0xFF", ); TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCall: evtcode >= 0xFF", );
TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCallWithParam: objectClass >= TRACE_NCLASSES", ); TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCallWithParam: objectClass >= TRACE_NCLASSES", );
TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCallWithParam: Invalid value for objectNumber", ); TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCallWithParam: Invalid value for objectNumber", );
if (recorder_busy) if (recorder_busy)
{ {
/************************************************************************* /*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call, * This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event. * or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls * Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY). * or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/ *************************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (3)"); vTraceError("Recorder busy - high priority ISR using syscall? (3)");
return; return;
} }
trcCRITICAL_SECTION_BEGIN(); trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && (! inExcludedTask || nISRactive))
(! inExcludedTask || nISRactive)) {
{ /* Check if the referenced object or the event code is excluded */
if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) &&
/* Check if the referenced object or the event code is excluded */ !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
if (!uiTraceIsObjectExcluded(objectClass, (objectHandleType)objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode)) {
{ dts2 = (uint8_t)prvTraceGetDTS(0xFF);
dts2 = (uint8_t)prvTraceGetDTS(0xFF); p8 = (uint8_t) prvTraceGetParam(0xFF, param);
hnd8 = prvTraceGet8BitHandle((objectHandleType)objectNumber);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot();
{ if (kse != NULL)
uint8_t p8 = (uint8_t) prvTraceGetParam(0xFF, param); {
kse->dts = dts2;
uint8_t hnd8 = prvTraceGet8BitHandle((objectHandleType)objectNumber); kse->type = (uint8_t)evtcode;
kse->objHandle = hnd8;
kse = (KernelCallWithParamAndHandle*) xTraceNextFreeEventBufferSlot(); kse->param = p8;
if (kse != NULL) prvTraceUpdateCounters();
{ }
kse->dts = dts2; }
kse->type = (uint8_t)evtcode; }
kse->objHandle = hnd8;
kse->param = p8;
prvTraceUpdateCounters();
}
}
}
}
trcCRITICAL_SECTION_END(); trcCRITICAL_SECTION_END();
#endif /* TRACE_SCHEDULING_ONLY */
} }
#if (TRACE_SCHEDULING_ONLY == 0)
/******************************************************************************* /*******************************************************************************
* prvTraceGetParam * prvTraceGetParam
* *
@ -346,9 +366,10 @@ void vTraceStoreKernelCallWithParam(uint32_t evtcode,
static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param) static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)
{ {
XPSEvent* xps; 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) if (param <= param_max)
{ {
return param; return param;
@ -367,6 +388,7 @@ static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)
return param & param_max; return param & param_max;
} }
} }
#endif
/******************************************************************************* /*******************************************************************************
* vTraceStoreKernelCallWithNumericParamOnly * vTraceStoreKernelCallWithNumericParamOnly
@ -376,56 +398,51 @@ static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)
******************************************************************************/ ******************************************************************************/
void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param) void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
{ {
KernelCallWithParam16 * kse; #if (TRACE_SCHEDULING_ONLY == 0)
uint8_t dts6; KernelCallWithParam16 * kse;
uint8_t dts6;
uint16_t restParam; uint16_t restParam;
TRACE_SR_ALLOC_CRITICAL_SECTION(); TRACE_SR_ALLOC_CRITICAL_SECTION();
restParam = 0; restParam = 0;
TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCallWithNumericParamOnly: Invalid value for evtcode", ); TRACE_ASSERT(evtcode < 0xFF,
"vTraceStoreKernelCallWithNumericParamOnly: Invalid value for evtcode", );
if (recorder_busy) if (recorder_busy)
{ {
/************************************************************************* /*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call, * This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event. * or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls * Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY). * 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(); trcCRITICAL_SECTION_BEGIN();
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task if (RecorderDataPtr->recorderActive && handle_of_last_logged_task
&& (! inExcludedTask || nISRactive)) && (! inExcludedTask || nISRactive))
{ {
/* Check if the event code is excluded */ /* Check if the event code is excluded */
if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode)) if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
{ {
dts6 = (uint8_t)prvTraceGetDTS(0xFF); dts6 = (uint8_t)prvTraceGetDTS(0xFF);
restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot();
{ if (kse != NULL)
restParam = (uint16_t)prvTraceGetParam(0xFFFF, param); {
kse->dts = dts6;
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ kse->type = (uint8_t)evtcode;
{ kse->param = restParam;
kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot(); prvTraceUpdateCounters();
if (kse != NULL) }
{ }
kse->dts = dts6; }
kse->type = (uint8_t)evtcode;
kse->param = restParam;
prvTraceUpdateCounters();
}
}
}
}
}
trcCRITICAL_SECTION_END(); trcCRITICAL_SECTION_END();
#endif /* TRACE_SCHEDULING_ONLY */
} }
/******************************************************************************* /*******************************************************************************
@ -435,39 +452,41 @@ void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
******************************************************************************/ ******************************************************************************/
void vTraceStoreTaskswitch(objectHandleType task_handle) void vTraceStoreTaskswitch(objectHandleType task_handle)
{ {
uint16_t dts3; uint16_t dts3;
TSEvent* ts; TSEvent* ts;
int8_t skipEvent; int8_t skipEvent;
uint8_t hnd8;
TRACE_SR_ALLOC_CRITICAL_SECTION(); TRACE_SR_ALLOC_CRITICAL_SECTION();
skipEvent = 0; skipEvent = 0;
TRACE_ASSERT(task_handle <= NTask, "vTraceStoreTaskswitch: Invalid value for task_handle", ); 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.
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 This is used to detect if a high-priority ISRs is illegally using the
that the macro trcCRITICAL_SECTION_BEGIN does not disable this ISR, as required. 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 If this is detected, it triggers a call to vTraceError with the error
trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this "Illegal call to vTraceStoreISRBegin/End". If you get this error, it means
function since critical sections should not be used in the context switch that the macro trcCRITICAL_SECTION_BEGIN does not disable this ISR, as required.
event...)
***************************************************************************/ Note: Setting recorder_busy is normally handled in our macros
trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this
/* Skip the event if the task has been excluded, using vTraceExcludeTask */ function since critical sections should not be used in the context switch
if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle)) event...)
{ ***************************************************************************/
skipEvent = 1;
inExcludedTask = 1; /* Skip the event if the task has been excluded, using vTraceExcludeTask */
} if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle))
else
{ {
inExcludedTask = 0; skipEvent = 1;
inExcludedTask = 1;
}
else
{
inExcludedTask = 0;
} }
trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY(); trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY();
@ -477,48 +496,42 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
{ {
skipEvent = 1; skipEvent = 1;
} }
if (!RecorderDataPtr->recorderActive)
{
skipEvent = 1;
}
/* If this event should be logged, log it! */ if (!RecorderDataPtr->recorderActive)
if (skipEvent == 0) {
{ skipEvent = 1;
dts3 = (uint16_t)prvTraceGetDTS(0xFFFF); }
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ /* If this event should be logged, log it! */
{ if (skipEvent == 0)
uint8_t hnd8; {
handle_of_last_logged_task = task_handle; dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task); 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) ts->dts = dts3;
{ ts->objHandle = hnd8;
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; vTraceSetObjectState(TRACE_CLASS_TASK,
ts->objHandle = hnd8; handle_of_last_logged_task,
TASK_STATE_INSTANCE_ACTIVE);
vTraceSetObjectState(TRACE_CLASS_TASK, prvTraceUpdateCounters();
handle_of_last_logged_task, }
TASK_STATE_INSTANCE_ACTIVE); }
prvTraceUpdateCounters();
}
}
}
trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY(); trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY();
} }
@ -533,21 +546,21 @@ void vTraceStoreTaskswitch(objectHandleType task_handle)
******************************************************************************/ ******************************************************************************/
#if (INCLUDE_OBJECT_DELETE == 1) #if (INCLUDE_OBJECT_DELETE == 1)
void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle, void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass) traceObjectClass objectclass)
{ {
ObjCloseNameEvent * ce; ObjCloseNameEvent * ce;
const char * name; const char * name;
traceLabel idx; traceLabel idx;
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceStoreObjectNameOnCloseEvent: objectclass >= TRACE_NCLASSES", ); TRACE_ASSERT(objectclass < TRACE_NCLASSES,
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceStoreObjectNameOnCloseEvent: Invalid value for handle", ); "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); uint8_t hnd8 = prvTraceGet8BitHandle(handle);
name = TRACE_PROPERTY_NAME_GET(objectclass, handle); name = TRACE_PROPERTY_NAME_GET(objectclass, handle);
idx = prvTraceOpenSymbol(name, 0); idx = prvTraceOpenSymbol(name, 0);
// Interrupt disable not necessary, already done in trcHooks.h macro // Interrupt disable not necessary, already done in trcHooks.h macro
@ -555,7 +568,7 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
if (ce != NULL) if (ce != NULL)
{ {
ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass; ce->type = EVENTGROUP_OBJCLOSE_NAME + objectclass;
ce->objHandle = hnd8; ce->objHandle = hnd8;
ce->symbolIndex = idx; ce->symbolIndex = idx;
prvTraceUpdateCounters(); prvTraceUpdateCounters();
} }
@ -563,14 +576,16 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
} }
void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle, void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
traceObjectClass objectclass) traceObjectClass objectclass)
{ {
ObjClosePropEvent * pe; ObjClosePropEvent * pe;
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceStoreObjectPropertiesOnCloseEvent: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceStoreObjectPropertiesOnCloseEvent: Invalid value for handle", );
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 // Interrupt disable not necessary, already done in trcHooks.h macro
pe = (ObjClosePropEvent*) xTraceNextFreeEventBufferSlot(); pe = (ObjClosePropEvent*) xTraceNextFreeEventBufferSlot();
@ -579,9 +594,9 @@ void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
if (objectclass == TRACE_CLASS_TASK) if (objectclass == TRACE_CLASS_TASK)
{ {
pe->arg1 = TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle); 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->arg1 = TRACE_PROPERTY_OBJECT_STATE(objectclass, handle);
} }
pe->type = EVENTGROUP_OBJCLOSE_PROP + objectclass; pe->type = EVENTGROUP_OBJCLOSE_PROP + objectclass;
@ -593,43 +608,52 @@ void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
void vTraceSetPriorityProperty(uint8_t objectclass, objectHandleType id, uint8_t value) void vTraceSetPriorityProperty(uint8_t objectclass, objectHandleType id, uint8_t value)
{ {
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceSetPriorityProperty: objectclass >= TRACE_NCLASSES", ); TRACE_ASSERT(objectclass < TRACE_NCLASSES,
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceSetPriorityProperty: Invalid value for id", ); "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) uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, objectHandleType id)
{ {
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetPriorityProperty: objectclass >= TRACE_NCLASSES", 0); TRACE_ASSERT(objectclass < TRACE_NCLASSES,
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetPriorityProperty: Invalid value for id", 0); "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) void vTraceSetObjectState(uint8_t objectclass, objectHandleType id, uint8_t value)
{ {
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceSetObjectState: objectclass >= TRACE_NCLASSES", ); TRACE_ASSERT(objectclass < TRACE_NCLASSES,
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceSetObjectState: Invalid value for id", ); "vTraceSetObjectState: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value; "vTraceSetObjectState: Invalid value for id", );
TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value;
} }
uint8_t uiTraceGetObjectState(uint8_t objectclass, objectHandleType id) uint8_t uiTraceGetObjectState(uint8_t objectclass, objectHandleType id)
{ {
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetObjectState: objectclass >= TRACE_NCLASSES", 0); TRACE_ASSERT(objectclass < TRACE_NCLASSES,
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetObjectState: Invalid value for id", 0); "uiTraceGetObjectState: objectclass >= TRACE_NCLASSES", 0);
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
return TRACE_PROPERTY_OBJECT_STATE(objectclass, id); "uiTraceGetObjectState: Invalid value for id", 0);
return TRACE_PROPERTY_OBJECT_STATE(objectclass, id);
} }
void vTraceSetTaskInstanceFinished(objectHandleType handle) 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) #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 #endif

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library * Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcKernelPort.c * trcKernelPort.c
@ -31,7 +31,9 @@
* damages, or the exclusion of implied warranties or limitations on how long an * 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. * 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 * www.percepio.com
******************************************************************************/ ******************************************************************************/
@ -56,13 +58,27 @@ traceObjectClass TraceObjectClassTable[5] = {
int uiInEventGroupSetBitsFromISR = 0; int uiInEventGroupSetBitsFromISR = 0;
extern unsigned char ucQueueGetQueueType(void*); 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) 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) unsigned char prvTraceGetObjectType(void* handle)
{ {
return ucQueueGetQueueType(handle); return ucQueueGetQueueType(handle);
@ -139,7 +155,7 @@ void vTraceInitObjectHandleStack()
objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = NQueue + NSemaphore + NMutex + NTask + NISR; objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = NQueue + NSemaphore + NMutex + NTask + NISR;
objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = NQueue + NSemaphore + NMutex + NTask + NISR + NTimer; 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[1] = NQueue + NSemaphore - 1;
objectHandleStacks.highestIndexOfClass[2] = NQueue + NSemaphore + NMutex - 1; objectHandleStacks.highestIndexOfClass[2] = NQueue + NSemaphore + NMutex - 1;
objectHandleStacks.highestIndexOfClass[3] = NQueue + NSemaphore + NMutex + NTask - 1; objectHandleStacks.highestIndexOfClass[3] = NQueue + NSemaphore + NMutex + NTask - 1;

File diff suppressed because it is too large Load diff

View file

@ -42,7 +42,7 @@
/***************************************************************************** /*****************************************************************************
* *
* See the following URL for an exaplanation of this file: * See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -42,7 +42,7 @@
/***************************************************************************** /*****************************************************************************
* *
* See the following URL for an exaplanation of this file: * See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -42,7 +42,7 @@
/***************************************************************************** /*****************************************************************************
* *
* See the following URL for an exaplanation of this file: * See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -42,7 +42,7 @@
/***************************************************************************** /*****************************************************************************
* *
* See the following URL for an exaplanation of this file: * See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -42,7 +42,7 @@
/***************************************************************************** /*****************************************************************************
* *
* See the following URL for an exaplanation of this file: * See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -42,7 +42,7 @@
/***************************************************************************** /*****************************************************************************
* *
* See the following URL for an exaplanation of this file: * See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Compiler_Porting.shtml
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -132,7 +132,7 @@ BaseType_t xStatus;
XUartPs_Config *pxConfig; XUartPs_Config *pxConfig;
/* Create the queue used to hold received characters. NOTE THE COMMENTS AT /* Create the queue used to hold received characters. NOTE THE COMMENTS AT
THE TOP OF THIS FILE REGARDING THE QUEUE OF QUEUES FOR THIS PURPSOE. */ THE TOP OF THIS FILE REGARDING THE USE OF QUEUES FOR THIS PURPSOE. */
xRxQueue = xQueueCreate( uxQueueLength, sizeof( char ) ); xRxQueue = xQueueCreate( uxQueueLength, sizeof( char ) );
configASSERT( xRxQueue ); configASSERT( xRxQueue );

View file

@ -1,6 +1,6 @@
/* /*
FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd.
*************************************************************************** ***************************************************************************
* * * *
@ -100,7 +100,7 @@ extern void vRegisterSampleCLICommands( void );
sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY); sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sLocalAddr.sin_port = ntohs( ( ( unsigned short ) 23 ) ); sLocalAddr.sin_port = ntohs( ( ( unsigned short ) 23 ) );
if( lwip_bind( lSocket, ( struct sockaddr *) &sLocalAddr, sizeof( sLocalAddr ) ) < 0 ) if( lwip_bind( lSocket, ( struct sockaddr *) &sLocalAddr, sizeof( sLocalAddr ) ) < 0 )
{ {
lwip_close( lSocket ); lwip_close( lSocket );
vTaskDelete( NULL ); vTaskDelete( NULL );
@ -125,14 +125,14 @@ extern void vRegisterSampleCLICommands( void );
memset( cInputString, 0x00, cmdMAX_INPUT_SIZE ); memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
do do
{ {
lBytes = lwip_recv( lClientFd, &cInChar, sizeof( cInChar ), 0 ); lBytes = lwip_recv( lClientFd, &cInChar, sizeof( cInChar ), 0 );
if( lBytes > 0L ) if( lBytes > 0L )
{ {
if( cInChar == '\n' ) if( cInChar == '\n' )
{ {
/* The input string has been terminated. Was the /* The input string has been terminated. Was the
input a quit command? */ input a quit command? */
if( strcmp( "quit", ( const char * ) cInputString ) == 0 ) if( strcmp( "quit", ( const char * ) cInputString ) == 0 )
{ {
@ -141,18 +141,18 @@ extern void vRegisterSampleCLICommands( void );
} }
else else
{ {
/* The input string was not a quit command. /* The input string was not a quit command.
Pass the string to the command interpreter. */ Pass the string to the command interpreter. */
do do
{ {
/* Get the next output string from the command interpreter. */ /* Get the next output string from the command interpreter. */
xReturned = FreeRTOS_CLIProcessCommand( cInputString, cOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE ); xReturned = FreeRTOS_CLIProcessCommand( cInputString, cOutputString, cmdMAX_INPUT_SIZE );
lwip_send( lClientFd, cOutputString, strlen( ( const char * ) cOutputString ), 0 ); lwip_send( lClientFd, cOutputString, strlen( ( const char * ) cOutputString ), 0 );
} while( xReturned != pdFALSE ); } while( xReturned != pdFALSE );
/* All the strings generated by the input /* All the strings generated by the input
command have been sent. Clear the input command have been sent. Clear the input
string ready to receive the next command. */ string ready to receive the next command. */
lInputIndex = 0; lInputIndex = 0;
@ -168,7 +168,7 @@ extern void vRegisterSampleCLICommands( void );
} }
else if( cInChar == '\b' ) else if( cInChar == '\b' )
{ {
/* Backspace was pressed. Erase the last /* Backspace was pressed. Erase the last
character in the string - if any. */ character in the string - if any. */
if( lInputIndex > 0 ) if( lInputIndex > 0 )
{ {
@ -194,7 +194,7 @@ extern void vRegisterSampleCLICommands( void );
lwip_close( lClientFd ); lwip_close( lClientFd );
} }
} }
} }
/* Will only get here if a listening socket could not be created. */ /* Will only get here if a listening socket could not be created. */

View file

@ -80,7 +80,7 @@
* point registers. To avoid this causing corruption it is necessary to avoid * point registers. To avoid this causing corruption it is necessary to avoid
* their use. For this reason main.c contains very basic C implementations of * their use. For this reason main.c contains very basic C implementations of
* the standard C library functions memset(), memcpy() and memcmp(), which are * the standard C library functions memset(), memcpy() and memcmp(), which are
* are used by FreeRTOS itself. Defining these functions in the project * are used by FreeRTOS itself. Defining these functions in the project
* prevents the linker pulling them in from the library. Any other standard C * prevents the linker pulling them in from the library. Any other standard C
* library functions that are used by the application must likewise be defined * library functions that are used by the application must likewise be defined
* in C. * in C.
@ -145,7 +145,7 @@ static void prvSetupHardware( void );
extern void main_lwIP( void ); extern void main_lwIP( void );
#else #else
#error Invalid mainSELECTED_APPLICATION setting. See the comments at the top of this file and above the mainSELECTED_APPLICATION definition. #error Invalid mainSELECTED_APPLICATION setting. See the comments at the top of this file and above the mainSELECTED_APPLICATION definition.
#endif /* #if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 */ #endif
/* /*
* The Xilinx projects use a BSP that do not allow the start up code to be * The Xilinx projects use a BSP that do not allow the start up code to be

View file

@ -0,0 +1,505 @@
/*
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
/*
* Tests the behaviour of direct task notifications.
*/
/* Standard includes. */
#include <limits.h>
/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
/* Demo program include files. */
#include "TaskNotify.h"
#define notifyTASK_PRIORITY ( tskIDLE_PRIORITY )
/*-----------------------------------------------------------*/
/*
* Implementation of the task that gets notified.
*/
static void prvNotifiedTask( void *pvParameters );
/*
* Performs a few initial tests that can be done prior to creating the second
* task.
*/
static void prvSingleTaskTests( void );
/*
* Software timer callback function from which xTaskNotify() is called.
*/
static void prvNotifyingTimer( TimerHandle_t xTimer );
/*
* Utility function to create pseudo random numbers.
*/
static UBaseType_t prvRand( void );
/*-----------------------------------------------------------*/
/* Used to latch errors during the test's execution. */
static BaseType_t xErrorStatus = pdPASS;
/* Used to ensure the task has not stalled. */
static volatile uint32_t ulNotifyCycleCount = 0;
/* The handle of the task that receives the notifications. */
static TaskHandle_t xTaskToNotify = NULL;
/* Used to count the notifications sent to the task from a software timer and
the number of notifications received by the task from the software timer. The
two should stay synchronised. */
static uint32_t ulTimerNotificationsReceived = 0UL, ulTimerNotificationsSent = 0UL;
/* The timer used to notify the task. */
static TimerHandle_t xTimer = NULL;
/*-----------------------------------------------------------*/
void vStartTaskNotifyTask( void )
{
/* Create the task that performs some tests by itself, then loops around
being notified by both a software timer and an interrupt. */
xTaskCreate( prvNotifiedTask, "Notified", configMINIMAL_STACK_SIZE, NULL, notifyTASK_PRIORITY, &xTaskToNotify );
}
/*-----------------------------------------------------------*/
static void prvSingleTaskTests( void )
{
const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
BaseType_t xReturned;
uint32_t ulNotifiedValue, ulLoop, ulNotifyingValue;
TickType_t xTimeOnEntering;
const uint32_t ulFirstNotifiedConst = 100001UL, ulSecondNotifiedValueConst = 5555UL, ulMaxLoops = 5UL;
const uint32_t ulBit0 = 0x01UL, ulBit1 = 0x02UL;
/* -------------------------------------------------------------------------
Check blocking when there are no notifications. */
xTimeOnEntering = xTaskGetTickCount();
xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, xTicksToWait );
/* Should have blocked for the entire block time. */
if( ( xTaskGetTickCount() - xTimeOnEntering ) < xTicksToWait )
{
xErrorStatus = pdFAIL;
}
configASSERT( xReturned == pdFAIL );
configASSERT( ulNotifiedValue == 0UL );
/* -------------------------------------------------------------------------
Check no blocking when notifications are pending. First notify itself -
this would not be a normal thing to do and is done here for test purposes
only. */
xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
/* Even through the 'without overwrite' action was used the update should
have been successful. */
configASSERT( xReturned == pdPASS );
/* The task should now have a notification pending, and so not time out. */
xTimeOnEntering = xTaskGetTickCount();
xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, xTicksToWait );
if( ( xTaskGetTickCount() - xTimeOnEntering ) >= xTicksToWait )
{
xErrorStatus = pdFAIL;
}
/* The task should have been notified, and the notified value should
be equal to ulFirstNotifiedConst. */
configASSERT( xReturned == pdPASS );
configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
/* Incremented to show the task is still running. */
ulNotifyCycleCount++;
/*--------------------------------------------------------------------------
Check the non-overwriting functionality. The notification is done twice
using two different notification values. The action says don't overwrite so
only the first notification should pass and the value read back should also
be that used with the first notification. */
xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
configASSERT( xReturned == pdPASS );
xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithoutOverwrite );
configASSERT( xReturned == pdFAIL );
/* Waiting for the notification should now return immediately so a block
time of zero is used. */
xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 );
configASSERT( xReturned == pdPASS );
configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
/*--------------------------------------------------------------------------
Do the same again, only this time use the overwriting version. This time
both notifications should pass, and the value written the second time should
overwrite the value written the first time, and so be the value that is read
back. */
xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithOverwrite );
configASSERT( xReturned == pdPASS );
xReturned = xTaskNotify( xTaskToNotify, ulSecondNotifiedValueConst, eSetValueWithOverwrite );
configASSERT( xReturned == pdPASS );
xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 );
configASSERT( xReturned == pdPASS );
configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
/*--------------------------------------------------------------------------
Check notifications with no action pass without updating the value. Even
though ulFirstNotifiedConst is used as the value the value read back should
remain at ulSecondNotifiedConst. */
xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eNoAction );
configASSERT( xReturned == pdPASS );
xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 );
configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
/*--------------------------------------------------------------------------
Check incrementing values. Send ulMaxLoop increment notifications, then
ensure the received value is as expected - which should be
ulSecondNotificationValueConst plus how ever many times to loop iterated. */
for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
{
xReturned = xTaskNotify( xTaskToNotify, 0, eIncrement );
configASSERT( xReturned == pdPASS );
}
xReturned = xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 );
configASSERT( xReturned == pdPASS );
configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) );
/* Should not be any notifications pending now. */
xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );
configASSERT( xReturned == pdFAIL );
/*--------------------------------------------------------------------------
Check all bits can be set by notifying the task with one additional bit set
on each notification, and exiting the loop when all the bits are found to be
set. As there are 32-bits the loop should execute 32 times before all the
bits are found to be set. */
ulNotifyingValue = 0x01;
ulLoop = 0;
/* Start with all bits clear. */
xTaskNotifyWait( ULONG_MAX, 0, &ulNotifiedValue, 0 );
do
{
/* Set the next bit in the task's notified value. */
xTaskNotify( xTaskToNotify, ulNotifyingValue, eSetBits );
/* Wait for the notified value - which of course will already be
available. Don't clear the bits on entry or exit as this loop is exited
when all the bits are set. */
xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );
configASSERT( xReturned == pdPASS );
ulLoop++;
/* Use the next bit on the next iteration around this loop. */
ulNotifyingValue <<= 1UL;
} while ( ulNotifiedValue != ULONG_MAX );
/* As a 32-bit value was used the loop should have executed 32 times before
all the bits were set. */
configASSERT( ulLoop == 32 );
/*--------------------------------------------------------------------------
Check bits are cleared on entry but not on exit when a notification fails
to arrive before timing out - both with and without a timeout value. Wait
for the notification again - but this time it is not given by anything and
should return pdFAIL. The parameters are set to clear bit zero on entry and
bit one on exit. As no notification was received only the bit cleared on
entry should actually get cleared. */
xReturned = xTaskNotifyWait( ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );
configASSERT( xReturned == pdFAIL );
/* Notify the task with no action so as not to update the bits even though
ULONG_MAX is used as the notification value. */
xTaskNotify( xTaskToNotify, ULONG_MAX, eNoAction );
/* Reading back the value should should find bit 0 is clear, as this was
cleared on entry, but bit 1 is not clear as it will not have been cleared on
exit as no notification was received. */
xReturned = xTaskNotifyWait( 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
configASSERT( xReturned == pdPASS );
configASSERT( ulNotifiedValue == ( ULONG_MAX & ~ulBit0 ) );
/*--------------------------------------------------------------------------
Now try clearing the bit on exit. For that to happen a notification must be
received, so the task is notified first. */
xTaskNotify( xTaskToNotify, 0, eNoAction );
xTaskNotifyWait( 0x00, ulBit1, &ulNotifiedValue, 0 );
/* However as the bit is cleared on exit, after the returned notification
value is set, the returned notification value should not have the bit
cleared... */
configASSERT( ulNotifiedValue == ( ULONG_MAX & ~ulBit0 ) );
/* ...but reading the value back again should find that the bit was indeed
cleared internally. The returned value should be pdFAIL however as nothing
has notified the task in the mean time. */
xReturned = xTaskNotifyWait( 0x00, 0x00, &ulNotifiedValue, 0 );
configASSERT( xReturned == pdFAIL );
configASSERT( ulNotifiedValue == ( ULONG_MAX & ~( ulBit0 | ulBit1 ) ) );
/* Incremented to show the task is still running. */
ulNotifyCycleCount++;
/* Leave all bits cleared. */
xTaskNotifyWait( ULONG_MAX, 0, NULL, 0 );
}
/*-----------------------------------------------------------*/
static void prvNotifyingTimer( TimerHandle_t xTimer )
{
( void ) xTimer;
xTaskNotifyGive( xTaskToNotify );
/* This value is also incremented from an interrupt. */
taskENTER_CRITICAL();
{
ulTimerNotificationsSent++;
}
taskEXIT_CRITICAL();
}
/*-----------------------------------------------------------*/
static void prvNotifiedTask( void *pvParameters )
{
const TickType_t xMaxPeriod = pdMS_TO_TICKS( 90 ), xMinPeriod = pdMS_TO_TICKS( 10 ), xDontBlock = 0;
TickType_t xPeriod;
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
/* Run a few tests that can be done from a single task before entering the
main loop. */
prvSingleTaskTests();
/* Create the software timer that is used to send notifications to this
task. Notifications are also received from an interrupt. */
xTimer = xTimerCreate( "Notifier", xMaxPeriod, pdFALSE, NULL, prvNotifyingTimer );
for( ;; )
{
/* Start the timer again with a different period. Sometimes the period
will be higher than the tasks block time, sometimes it will be lower
than the tasks block time. */
xPeriod = prvRand() % xMaxPeriod;
if( xPeriod < xMinPeriod )
{
xPeriod = xMinPeriod;
}
xTimerChangePeriod( xTimer, xPeriod, portMAX_DELAY );
xTimerStart( xTimer, portMAX_DELAY );
/* Block waiting for the notification again with a different period.
Sometimes the period will be higher than the tasks block time, sometimes
it will be lower than the tasks block time. */
xPeriod = prvRand() % xMaxPeriod;
if( xPeriod < xMinPeriod )
{
xPeriod = xMinPeriod;
}
/* Block to wait for a notification but without clearing the
notification count, so only add one to the count of received
notifications as any other notifications will remain pending. */
if( ulTaskNotifyTake( pdFALSE, xPeriod ) != 0 )
{
ulTimerNotificationsReceived++;
}
/* Take a notification without clearing again, but this time without a
block time specified. */
if( ulTaskNotifyTake( pdFALSE, xDontBlock ) != 0 )
{
ulTimerNotificationsReceived++;
}
/* Wait for the next notification from the timer, clearing all
notifications if one is received, so this time adding the total number
of notifications that were pending as none will be left pending after
the function call. */
ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, xPeriod );
/* Wait for the next notification again, clearing all notifications if
one is received, but this time blocking indefinitely. */
ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
/* Incremented to show the task is still running. */
ulNotifyCycleCount++;
}
}
/*-----------------------------------------------------------*/
void xNotifyTaskFromISR( void )
{
static BaseType_t xCallCount = 0;
const BaseType_t xCallInterval = pdMS_TO_TICKS( 50 );
/* The task performs some tests before starting the timer that gives the
notification from this interrupt. If the timer has not been created yet
then the initial tests have not yet completed and the notification should
not be sent. */
if( xTimer != NULL )
{
xCallCount++;
if( xCallCount >= xCallInterval )
{
/* It is time to 'give' the notification again. */
xCallCount = 0;
xTaskNotifyGiveFromISR( xTaskToNotify, NULL );
ulTimerNotificationsSent++;
}
}
}
/*-----------------------------------------------------------*/
/* This is called to check the created tasks are still running and have not
detected any errors. */
BaseType_t xAreTaskNotificationTasksStillRunning( void )
{
static uint32_t ulLastNotifyCycleCount = 0;
const uint32_t ulMaxSendReceiveDeviation = 5UL;
/* Check the cycle count is still incrementing to ensure the task is still
actually running. */
if( ulLastNotifyCycleCount == ulNotifyCycleCount )
{
xErrorStatus = pdFAIL;
}
else
{
ulLastNotifyCycleCount = ulNotifyCycleCount;
}
/* Check the count of 'takes' from the software timer is keeping track with
the amount of 'gives'. */
if( ulTimerNotificationsSent > ulTimerNotificationsSent )
{
if( ( ulTimerNotificationsSent - ulTimerNotificationsReceived ) > ulMaxSendReceiveDeviation )
{
xErrorStatus = pdFAIL;
}
}
return xErrorStatus;
}
/*-----------------------------------------------------------*/
static UBaseType_t prvRand( void )
{
static uint32_t ulNextRand = ( uint32_t ) prvRand;
const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;
/* Utility function to generate a pseudo random number. */
ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
}
/*-----------------------------------------------------------*/

View file

@ -739,11 +739,16 @@ static TickType_t uxTick = ( TickType_t ) -1;
will expire when the kernel's tick count is (100 + xBasePeriod). For this will expire when the kernel's tick count is (100 + xBasePeriod). For this
reason xMargin is used as an allowable margin for premature timer expiries reason xMargin is used as an allowable margin for premature timer expiries
as well as late timer expiries. */ as well as late timer expiries. */
const TickType_t xMargin = 6; #ifdef _WINDOWS_
/* Windows is not real real time. */
const TickType_t xMargin = 20;
#else
const TickType_t xMargin = 6;
#endif /* _WINDOWS_ */
#else #else
#ifdef _WINDOWS_ #ifdef _WINDOWS_
/* Windows is not real real time. */ /* Windows is not real real time. */
const TickType_t xMargin = 10; const TickType_t xMargin = 20;
#else #else
const TickType_t xMargin = 4; const TickType_t xMargin = 4;
#endif /* _WINDOWS_ */ #endif /* _WINDOWS_ */

View file

@ -0,0 +1,76 @@
/*
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
#ifndef TASK_NOTIFY_H
#define TASK_NOTIFY_H
void vStartTaskNotifyTask( void );
BaseType_t xAreTaskNotificationTasksStillRunning( void );
void xNotifyTaskFromISR( void );
#endif /* TASK_NOTIFY_H */

View file

@ -1,7 +1,7 @@
#ifndef CGC_SET_VALUES_H_ #ifndef CGC_SET_VALUES_H_
#define CGC_SET_VALUES_H_ #define CGC_SET_VALUES_H_
/* Do not modify these macros. These values are used to initialise /* Do not modify these macros. These values are used to initialise
the SCKCR and SCKCR2 registers based upon the above values. */ the SCKCR and SCKCR2 registers based upon the above values. */
#if (FCLK_DIV == 64) #if (FCLK_DIV == 64)
#define FCLK_SCKCR 0x60000000L #define FCLK_SCKCR 0x60000000L
@ -40,12 +40,12 @@
#define ICLK_SCKCR 0x01000000L #define ICLK_SCKCR 0x01000000L
#endif #endif
#if (BCLK_PIN == 1) #if (BCLK_PIN == 1)
#define PSTOP1_SCKCR 0x00800000L #define PSTOP1_SCKCR 0x00800000L
#elif #else
#define PSTOP1_SCKCR 0x00000000L #define PSTOP1_SCKCR 0x00000000L
#endif #endif
#if (BCLK_DIV == 64) #if (BCLK_DIV == 64)
@ -120,7 +120,7 @@
#elif (PCLK47_DIV == 1) #elif (PCLK47_DIV == 1)
#define PCLK47_SCKCR 0x00000000L #define PCLK47_SCKCR 0x00000000L
#else #else
#define PCLK47_SCKCR 0x00000010L #define PCLK47_SCKCR 0x00000010L
#endif #endif
@ -139,7 +139,7 @@
#elif (PCLK03_DIV == 1) #elif (PCLK03_DIV == 1)
#define PCLK03_SCKCR 0x00000000L #define PCLK03_SCKCR 0x00000000L
#else #else
#define PCLK03_SCKCR 0x00000001L #define PCLK03_SCKCR 0x00000001L
#endif #endif
@ -173,7 +173,7 @@
#if (CLK_SOURCE == CLK_SOURCE_LOCO) #if (CLK_SOURCE == CLK_SOURCE_LOCO)
/* Internal LOCO circuit - 125kHz*/ /* Internal LOCO circuit - 125kHz*/
#define CLK_FREQUENCY (125000L) #define CLK_FREQUENCY (125000L)
#define FCLK_FREQUENCY (CLK_FREQUENCY / FCLK_DIV) #define FCLK_FREQUENCY (CLK_FREQUENCY / FCLK_DIV)
#define ICLK_FREQUENCY (CLK_FREQUENCY / ICLK_DIV) #define ICLK_FREQUENCY (CLK_FREQUENCY / ICLK_DIV)
#define BCLK_FREQUENCY (CLK_FREQUENCY / BCLK_DIV) #define BCLK_FREQUENCY (CLK_FREQUENCY / BCLK_DIV)
@ -185,7 +185,7 @@
#elif (CLK_SOURCE == CLK_SOURCE_HOCO) #elif (CLK_SOURCE == CLK_SOURCE_HOCO)
/* Internal high speed on-chip oscillator (HOCO) */ /* Internal high speed on-chip oscillator (HOCO) */
#define CLK_FREQUENCY (50000000L) #define CLK_FREQUENCY (50000000L)
#define FCLK_FREQUENCY (CLK_FREQUENCY / FCLK_DIV) #define FCLK_FREQUENCY (CLK_FREQUENCY / FCLK_DIV)
#define ICLK_FREQUENCY (CLK_FREQUENCY / ICLK_DIV) #define ICLK_FREQUENCY (CLK_FREQUENCY / ICLK_DIV)
#define BCLK_FREQUENCY (CLK_FREQUENCY / BCLK_DIV) #define BCLK_FREQUENCY (CLK_FREQUENCY / BCLK_DIV)
@ -196,7 +196,7 @@
#elif (CLK_SOURCE == CLK_SOURCE_MAIN) #elif (CLK_SOURCE == CLK_SOURCE_MAIN)
/* External XTAL, but not via the PLL circuit */ /* External XTAL, but not via the PLL circuit */
#define FCLK_FREQUENCY (XTAL_FREQUENCY / FCLK_DIV) #define FCLK_FREQUENCY (XTAL_FREQUENCY / FCLK_DIV)
#define ICLK_FREQUENCY (XTAL_FREQUENCY / ICLK_DIV) #define ICLK_FREQUENCY (XTAL_FREQUENCY / ICLK_DIV)
#define BCLK_FREQUENCY (XTAL_FREQUENCY / BCLK_DIV) #define BCLK_FREQUENCY (XTAL_FREQUENCY / BCLK_DIV)
@ -207,7 +207,7 @@
#elif (CLK_SOURCE == CLK_SOURCE_SUB) #elif (CLK_SOURCE == CLK_SOURCE_SUB)
/* External 32khZ XTAL */ /* External 32khZ XTAL */
#define FCLK_FREQUENCY (SUB_FREQUENCY / FCLK_DIV) #define FCLK_FREQUENCY (SUB_FREQUENCY / FCLK_DIV)
#define ICLK_FREQUENCY (SUB_FREQUENCY / ICLK_DIV) #define ICLK_FREQUENCY (SUB_FREQUENCY / ICLK_DIV)
#define BCLK_FREQUENCY (SUB_FREQUENCY / BCLK_DIV) #define BCLK_FREQUENCY (SUB_FREQUENCY / BCLK_DIV)
@ -219,7 +219,7 @@
#elif (CLK_SOURCE == CLK_SOURCE_PLL) #elif (CLK_SOURCE == CLK_SOURCE_PLL)
/* External XTAL, but using the PLL circuit */ /* External XTAL, but using the PLL circuit */
#define PLL_FREQUENCY (XTAL_FREQUENCY * (PLL_MUL / PLL_INPUT_FREQ_DIV)) #define PLL_FREQUENCY (XTAL_FREQUENCY * (PLL_MUL / PLL_INPUT_FREQ_DIV))
#define FCLK_FREQUENCY (PLL_FREQUENCY / FCLK_DIV) #define FCLK_FREQUENCY (PLL_FREQUENCY / FCLK_DIV)
#define ICLK_FREQUENCY (PLL_FREQUENCY / ICLK_DIV) #define ICLK_FREQUENCY (PLL_FREQUENCY / ICLK_DIV)
#define BCLK_FREQUENCY (PLL_FREQUENCY / BCLK_DIV) #define BCLK_FREQUENCY (PLL_FREQUENCY / BCLK_DIV)

View file

@ -96,8 +96,8 @@
#include "rskrx64mdef.h" #include "rskrx64mdef.h"
/* Set option bytes */ /* Set option bytes */
#pragma address OFS0_location = 0xFFFFFF8CUL #pragma address OFS0_location 0xFFFFFF8CUL
#pragma address OFS1_location = 0xFFFFFF88UL #pragma address OFS1_location 0xFFFFFF88UL
volatile const uint32_t OFS0_location = 0xFFFFFFFFUL; volatile const uint32_t OFS0_location = 0xFFFFFFFFUL;
volatile const uint32_t OFS1_location = 0xFFFFFFFFUL; volatile const uint32_t OFS1_location = 0xFFFFFFFFUL;

View file

@ -83,7 +83,7 @@
#define configUSE_TICK_HOOK 1 #define configUSE_TICK_HOOK 1
#define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */ #define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 50 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */ #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 50 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 22 * 1024 ) ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 23 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 12 ) #define configMAX_TASK_NAME_LEN ( 12 )
#define configUSE_TRACE_FACILITY 1 #define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0 #define configUSE_16_BIT_TICKS 0
@ -97,6 +97,7 @@
#define configUSE_COUNTING_SEMAPHORES 1 #define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_ALTERNATIVE_API 1 #define configUSE_ALTERNATIVE_API 1
#define configUSE_QUEUE_SETS 1 #define configUSE_QUEUE_SETS 1
#define configUSE_TASK_NOTIFICATIONS 1
/* Software timer related configuration options. */ /* Software timer related configuration options. */
#define configUSE_TIMERS 1 #define configUSE_TIMERS 1
@ -104,18 +105,18 @@
#define configTIMER_QUEUE_LENGTH 20 #define configTIMER_QUEUE_LENGTH 20
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) #define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
#define configMAX_PRIORITIES ( 7 ) #define configMAX_PRIORITIES ( 7 )
/* Run time stats gathering configuration options. */ /* Run time stats gathering configuration options. */
unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */
void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */
#define configGENERATE_RUN_TIME_STATS 1 #define configGENERATE_RUN_TIME_STATS 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats() #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() #define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue()
/* Co-routine related configuration options. */ /* Co-routine related configuration options. */
#define configUSE_CO_ROUTINES 1 #define configUSE_CO_ROUTINES 1
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* This demo makes use of one or more example stats formatting functions. These /* This demo makes use of one or more example stats formatting functions. These
format the raw data provided by the uxTaskGetSystemState() function in to human format the raw data provided by the uxTaskGetSystemState() function in to human
@ -148,6 +149,8 @@ extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName )
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __LINE__, __FILE__ ) #define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __LINE__, __FILE__ )
/* Include the FreeRTOS+Trace FreeRTOS trace macro definitions. */ /* Include the FreeRTOS+Trace FreeRTOS trace macro definitions. */
#define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL()
#define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL()
#include "trcKernelPort.h" #include "trcKernelPort.h"
#endif /* FREERTOS_CONFIG_H */ #endif /* FREERTOS_CONFIG_H */

View file

@ -1,14 +1,14 @@
/******************************************************************************* /*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library * Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcConfig.h * trcConfig.h
* *
* Configuration parameters for the trace recorder library. Before using the * Configuration parameters for the trace recorder library. Before using the
* trace recorder library, please check that the default settings are * trace recorder library, please check that the default settings are
* appropriate for your system, and if necessary adjust these. Most likely, you * appropriate for your system, and if necessary adjust these. Most likely, you
* will need to adjust the NTask, NISR, NQueue, NMutex and NSemaphore values to * will need to adjust the NTask, NISR, NQueue, NMutex and NSemaphore values to
* reflect the number of such objects in your system. These may be * reflect the number of such objects in your system. These may be
* over-approximated, although larger values values implies more RAM usage. * over-approximated, although larger values values implies more RAM usage.
* *
* Terms of Use * Terms of Use
@ -16,36 +16,121 @@
* use together with Percepio products. You may distribute the recorder library * use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcHardwarePort.c/.h * in its original form, including modifications in trcHardwarePort.c/.h
* given that these modification are clearly marked as your own modifications * given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files. * and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be * This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written * sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB. * permission by Percepio AB.
* *
* Disclaimer * Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and * 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 * 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 * not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or * software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or * implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its * fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential, * technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings, * incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility * 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 * 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 * not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an * 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. * 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 * www.percepio.com
******************************************************************************/ ******************************************************************************/
#ifndef TRCCONFIG_H #ifndef TRCCONFIG_H
#define 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_RING_BUFFER
/******************************************************************************* /*******************************************************************************
* 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 * EVENT_BUFFER_SIZE
@ -53,47 +138,158 @@
* Macro which should be defined as an integer value. * Macro which should be defined as an integer value.
* *
* This defines the capacity of the event buffer, i.e., the number of records * 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 * it may store. Most events use one record (4 byte), although some events
* vTracePrintF may use multiple records depending on the number of data args. * 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 15000
#define EVENT_BUFFER_SIZE 10000 /* Adjust wrt. to available RAM */
/******************************************************************************* /*******************************************************************************
* USE_LINKER_PRAGMA * NTask, NISR, NQueue, NSemaphore, NMutex
* *
* Macro which should be defined as an integer value, default is 0. * A group of macros which should be defined as integer values, zero or larger.
* *
* If this is 1, the header file "recorderdata_linker_pragma.h" is included just * These define the capacity of the Object Property Table, i.e., the maximum
* before the declaration of RecorderData (in trcBase.c), i.e., the trace data * number of objects active at any given point, within each object class (e.g.,
* structure. This allows the user to specify a pragma with linker options. * task, queue, semaphore, ...).
* *
* Example (for IAR Embedded Workbench and NXP LPC17xx): * If tasks or other other objects are deleted in your system, this
* #pragma location="AHB_RAM_MEMORY" * setting does not limit the total amount of objects created, only the number
* * of objects that have been successfully created but not yet deleted.
* This example instructs the IAR linker to place RecorderData in another RAM *
* bank, the AHB RAM. This can also be used for other compilers with a similar * Using too small values will cause vTraceError to be called, which stores an
* pragmas for linker options. * error message in the trace that is shown when opening the trace file.
* *
* Note that this only applies if using static allocation, see below. * 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 100
#define NISR 60
#define NQueue 60
#define NSemaphore 60
#define NMutex 60
#define NTimer 200
#define NEventGroup 60
#define USE_LINKER_PRAGMA 0 /******************************************************************************
* 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 1
/******************************************************************************
* 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 0
/******************************************************************************
* 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 * SYMBOL_TABLE_SIZE
* *
* Macro which should be defined as an integer value. * Macro which should be defined as an integer value.
* *
* This defines the capacity of the symbol table, in bytes. This symbol table * 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 * 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 * objects. If you don't use User Events or delete any kernel
* Object Table. Thus, 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.
* objects you set this to a very low value, e.g. 4, but not zero (0) since * A size of zero (0) is not allowed since a zero-sized array may result in a
* this causes a declaration of a zero-sized array, for which the C compiler * 32-bit pointer, i.e., using 4 bytes rather than 0.
* behavior is not standardized and may cause misaligned data. *
* Default value is 800.
******************************************************************************/ ******************************************************************************/
#define SYMBOL_TABLE_SIZE 5000 #define SYMBOL_TABLE_SIZE 5000
@ -101,16 +297,153 @@
#error "SYMBOL_TABLE_SIZE may not be zero!" #error "SYMBOL_TABLE_SIZE may not be zero!"
#endif #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.
*
* If this is 1, the header file "recorderdata_linker_pragma.h" is included just
* before the declaration of RecorderData (in trcBase.c), i.e., the trace data
* structure. This allows the user to specify a pragma with linker options.
*
* Example (for IAR Embedded Workbench and NXP LPC17xx):
* #pragma location="AHB_RAM_MEMORY"
*
* This example instructs the IAR linker to place RecorderData in another RAM
* bank, the AHB RAM. This can also be used for other compilers with a similar
* pragmas for linker options.
*
* Note that this only applies if using static allocation, see below.
******************************************************************************/
#define USE_LINKER_PRAGMA 0
/******************************************************************************
* USE_IMPLICIT_IFE_RULES
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* 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
/******************************************************************************
* 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 * USE_SEPARATE_USER_EVENT_BUFFER
* *
* Macro which should be defined as an integer value. * Macro which should be defined as an integer value.
* Default is zero (0). * 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 * 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 * task instance named "Unknown actor". This is added as a placeholder when the
* user event history is longer than the task scheduling history. * user event history is longer than the task scheduling history.
******************************************************************************/ ******************************************************************************/
#define USE_SEPARATE_USER_EVENT_BUFFER 0 #define USE_SEPARATE_USER_EVENT_BUFFER 0
@ -125,7 +458,7 @@
* *
* Only in use if USE_SEPARATE_USER_EVENT_BUFFER is set to 1. * Only in use if USE_SEPARATE_USER_EVENT_BUFFER is set to 1.
******************************************************************************/ ******************************************************************************/
#define USER_EVENT_BUFFER_SIZE 500 #define USER_EVENT_BUFFER_SIZE 10
/******************************************************************************* /*******************************************************************************
* USER_EVENT_CHANNELS * USER_EVENT_CHANNELS
@ -138,393 +471,5 @@
******************************************************************************/ ******************************************************************************/
#define CHANNEL_FORMAT_PAIRS 32 #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 100
#define NISR 20
#define NQueue 60
#define NSemaphore 60
#define NMutex 60
#define NTimer 200
#define NEventGroup 60
/* 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 0
/******************************************************************************
* 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_Win32
#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 #endif

View file

@ -149,6 +149,7 @@
<ClCompile Include="..\Common\Minimal\QueueOverwrite.c" /> <ClCompile Include="..\Common\Minimal\QueueOverwrite.c" />
<ClCompile Include="..\Common\Minimal\QueueSet.c" /> <ClCompile Include="..\Common\Minimal\QueueSet.c" />
<ClCompile Include="..\Common\Minimal\semtest.c" /> <ClCompile Include="..\Common\Minimal\semtest.c" />
<ClCompile Include="..\Common\Minimal\TaskNotify.c" />
<ClCompile Include="..\Common\Minimal\timerdemo.c" /> <ClCompile Include="..\Common\Minimal\timerdemo.c" />
<ClCompile Include="DemosModifiedForLowTickRate\recmutex.c" /> <ClCompile Include="DemosModifiedForLowTickRate\recmutex.c" />
<ClCompile Include="main.c"> <ClCompile Include="main.c">

View file

@ -139,6 +139,9 @@
<ClCompile Include="..\Common\Minimal\IntSemTest.c"> <ClCompile Include="..\Common\Minimal\IntSemTest.c">
<Filter>Demo App Source\Common Demo Tasks</Filter> <Filter>Demo App Source\Common Demo Tasks</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Common\Minimal\TaskNotify.c">
<Filter>Demo App Source\Common Demo Tasks</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="FreeRTOSConfig.h"> <ClInclude Include="FreeRTOSConfig.h">

View file

@ -113,8 +113,8 @@ being used as this demo could easily create one large heap region instead of
multiple smaller heap regions - in which case heap_4.c would be the more multiple smaller heap regions - in which case heap_4.c would be the more
appropriate choice. */ appropriate choice. */
#define mainREGION_1_SIZE 3001 #define mainREGION_1_SIZE 3001
#define mainREGION_2_SIZE 18005 #define mainREGION_2_SIZE 18105
#define mainREGION_3_SIZE 1007 #define mainREGION_3_SIZE 1407
/* /*
* main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1. * main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1.
@ -228,10 +228,10 @@ void vApplicationIdleHook( void )
function, because it is the responsibility of the idle task to clean up function, because it is the responsibility of the idle task to clean up
memory allocated by the kernel to any task that has since been deleted. */ memory allocated by the kernel to any task that has since been deleted. */
/* Uncomment the following code to allow the trace to be stopped with any /* Uncomment the following code to allow the trace to be stopped with any
key press. The code is commented out by default as the kbhit() function key press. The code is commented out by default as the kbhit() function
interferes with the run time behaviour. */ interferes with the run time behaviour. */
/* /*
if( _kbhit() != pdFALSE ) if( _kbhit() != pdFALSE )
{ {
if( xTraceRunning == pdTRUE ) if( xTraceRunning == pdTRUE )
@ -369,4 +369,5 @@ const HeapRegion_t xHeapRegions[] =
vPortDefineHeapRegions( xHeapRegions ); vPortDefineHeapRegions( xHeapRegions );
} }
/*-----------------------------------------------------------*/

View file

@ -128,7 +128,7 @@
/* The rate at which data is sent to the queue. The 200ms value is converted /* The rate at which data is sent to the queue. The 200ms value is converted
to ticks using the portTICK_PERIOD_MS constant. */ to ticks using the portTICK_PERIOD_MS constant. */
#define mainQUEUE_SEND_FREQUENCY_MS ( 200 ) #define mainQUEUE_SEND_FREQUENCY_MS ( 200 / portTICK_PERIOD_MS )
/* The number of items the queue can hold. This is 1 as the receive task /* The number of items the queue can hold. This is 1 as the receive task
will remove items as they are added, meaning the send task should always find will remove items as they are added, meaning the send task should always find

View file

@ -112,10 +112,10 @@
/* Kernel includes. */ /* Kernel includes. */
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include "task.h" #include <task.h>
#include "queue.h" #include <queue.h>
#include "timers.h" #include <timers.h>
#include "semphr.h" #include <semphr.h>
/* Standard demo includes. */ /* Standard demo includes. */
#include "BlockQ.h" #include "BlockQ.h"
@ -134,6 +134,7 @@
#include "QueueOverwrite.h" #include "QueueOverwrite.h"
#include "EventGroupsDemo.h" #include "EventGroupsDemo.h"
#include "IntSemTest.h" #include "IntSemTest.h"
#include "TaskNotify.h"
/* Priorities at which the tasks are created. */ /* Priorities at which the tasks are created. */
#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) #define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )
@ -196,6 +197,7 @@ int main_full( void )
xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
/* Create the standard demo tasks. */ /* Create the standard demo tasks. */
vStartTaskNotifyTask();
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
@ -265,6 +267,11 @@ const TickType_t xCycleFrequency = 2500 / portTICK_PERIOD_MS;
} }
#endif #endif
if( xAreTaskNotificationTasksStillRunning() != pdTRUE )
{
pcStatusMessage = "Error: Notification";
}
if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE ) if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE )
{ {
pcStatusMessage = "Error: IntSem"; pcStatusMessage = "Error: IntSem";
@ -379,7 +386,7 @@ void *pvAllocated;
xMutexToDelete = NULL; xMutexToDelete = NULL;
} }
/* Exercise heap_4 a bit. The malloc failed hook will trap failed /* Exercise heap_5 a bit. The malloc failed hook will trap failed
allocations so there is no need to test here. */ allocations so there is no need to test here. */
pvAllocated = pvPortMalloc( ( rand() % 100 ) + 1 ); pvAllocated = pvPortMalloc( ( rand() % 100 ) + 1 );
vPortFree( pvAllocated ); vPortFree( pvAllocated );
@ -410,6 +417,9 @@ void vFullDemoTickHookFunction( void )
/* Exercise giving mutexes from an interrupt. */ /* Exercise giving mutexes from an interrupt. */
vInterruptSemaphorePeriodicTest(); vInterruptSemaphorePeriodicTest();
/* Exercise using task notifications from an interrupt. */
xNotifyTaskFromISR();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -56,7 +56,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193247</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -65,7 +65,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193247</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -74,7 +74,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193257</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -83,7 +83,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193257</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -92,7 +92,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193267</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -101,7 +101,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193277</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -110,7 +110,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193277</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -119,7 +119,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193287</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -128,7 +128,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193297</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -137,7 +137,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193297</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -146,7 +146,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193308</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -155,7 +155,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193313</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -164,7 +164,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193319</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -173,7 +173,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193325</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -182,7 +182,7 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321193349</id>
<name>Standard_Demo_Tasks</name> <name>Standard_Demo_Tasks</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
@ -190,6 +190,24 @@
<arguments>1.0-name-matches-false-false-timerdemo.c</arguments> <arguments>1.0-name-matches-false-false-timerdemo.c</arguments>
</matcher> </matcher>
</filter> </filter>
<filter>
<id>1418321193369</id>
<name>Standard_Demo_Tasks</name>
<type>5</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-IntSemTest.c</arguments>
</matcher>
</filter>
<filter>
<id>1418321193379</id>
<name>Standard_Demo_Tasks</name>
<type>5</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-TaskNotify.c</arguments>
</matcher>
</filter>
<filter> <filter>
<id>0</id> <id>0</id>
<name>FreeRTOS_Source/portable</name> <name>FreeRTOS_Source/portable</name>
@ -209,12 +227,12 @@
</matcher> </matcher>
</filter> </filter>
<filter> <filter>
<id>0</id> <id>1418321226214</id>
<name>FreeRTOS_Source/portable/MemMang</name> <name>FreeRTOS_Source/portable/MemMang</name>
<type>5</type> <type>5</type>
<matcher> <matcher>
<id>org.eclipse.ui.ide.multiFilter</id> <id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-heap_4.c</arguments> <arguments>1.0-name-matches-false-false-heap_5.c</arguments>
</matcher> </matcher>
</filter> </filter>
</filteredResources> </filteredResources>

View file

@ -83,7 +83,7 @@
#define configUSE_TICK_HOOK 1 #define configUSE_TICK_HOOK 1
#define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */ #define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 50 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */ #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 50 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 20 * 1024 ) ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 23 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 12 ) #define configMAX_TASK_NAME_LEN ( 12 )
#define configUSE_TRACE_FACILITY 1 #define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0 #define configUSE_16_BIT_TICKS 0
@ -97,6 +97,7 @@
#define configUSE_COUNTING_SEMAPHORES 1 #define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_ALTERNATIVE_API 1 #define configUSE_ALTERNATIVE_API 1
#define configUSE_QUEUE_SETS 1 #define configUSE_QUEUE_SETS 1
#define configUSE_TASK_NOTIFICATIONS 1
/* Software timer related configuration options. */ /* Software timer related configuration options. */
#define configUSE_TIMERS 1 #define configUSE_TIMERS 1
@ -104,18 +105,18 @@
#define configTIMER_QUEUE_LENGTH 20 #define configTIMER_QUEUE_LENGTH 20
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) #define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
#define configMAX_PRIORITIES ( 8 ) #define configMAX_PRIORITIES ( 7 )
/* Run time stats gathering configuration options. */ /* Run time stats gathering configuration options. */
unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */
void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */
#define configGENERATE_RUN_TIME_STATS 1 #define configGENERATE_RUN_TIME_STATS 1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats() #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() #define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue()
/* Co-routine related configuration options. */ /* Co-routine related configuration options. */
#define configUSE_CO_ROUTINES 1 #define configUSE_CO_ROUTINES 1
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* This demo makes use of one or more example stats formatting functions. These /* This demo makes use of one or more example stats formatting functions. These
format the raw data provided by the uxTaskGetSystemState() function in to human format the raw data provided by the uxTaskGetSystemState() function in to human
@ -147,7 +148,9 @@ uses the same semantics as the standard C assert() macro. */
extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName ); extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName );
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __LINE__, __FILE__ ) #define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __LINE__, __FILE__ )
/* Include the FreeRTOS+Trace FreeRTOS trace macro definitions. */ /* Include the FreeRTOS+Trace FreeRTOS trace macro definitions. */
#define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL()
#define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL()
#include "trcKernelPort.h" #include "trcKernelPort.h"
#endif /* FREERTOS_CONFIG_H */ #endif /* FREERTOS_CONFIG_H */

View file

@ -1,14 +1,14 @@
/******************************************************************************* /*******************************************************************************
* Tracealyzer v2.6.0 Recorder Library * Tracealyzer v2.7.0 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcConfig.h * trcConfig.h
* *
* Configuration parameters for the trace recorder library. Before using the * Configuration parameters for the trace recorder library. Before using the
* trace recorder library, please check that the default settings are * trace recorder library, please check that the default settings are
* appropriate for your system, and if necessary adjust these. Most likely, you * appropriate for your system, and if necessary adjust these. Most likely, you
* will need to adjust the NTask, NISR, NQueue, NMutex and NSemaphore values to * will need to adjust the NTask, NISR, NQueue, NMutex and NSemaphore values to
* reflect the number of such objects in your system. These may be * reflect the number of such objects in your system. These may be
* over-approximated, although larger values values implies more RAM usage. * over-approximated, although larger values values implies more RAM usage.
* *
* Terms of Use * Terms of Use
@ -16,36 +16,121 @@
* use together with Percepio products. You may distribute the recorder library * use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcHardwarePort.c/.h * in its original form, including modifications in trcHardwarePort.c/.h
* given that these modification are clearly marked as your own modifications * given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files. * and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be * This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written * sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB. * permission by Percepio AB.
* *
* Disclaimer * Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and * 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 * 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 * not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or * software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or * implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its * fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential, * technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings, * incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility * 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 * 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 * not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an * 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. * 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 * www.percepio.com
******************************************************************************/ ******************************************************************************/
#ifndef TRCCONFIG_H #ifndef TRCCONFIG_H
#define 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_RING_BUFFER
/******************************************************************************* /*******************************************************************************
* 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 * EVENT_BUFFER_SIZE
@ -53,47 +138,158 @@
* Macro which should be defined as an integer value. * Macro which should be defined as an integer value.
* *
* This defines the capacity of the event buffer, i.e., the number of records * 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 * it may store. Most events use one record (4 byte), although some events
* vTracePrintF may use multiple records depending on the number of data args. * 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 15000
#define EVENT_BUFFER_SIZE 10000 /* Adjust wrt. to available RAM */
/******************************************************************************* /*******************************************************************************
* USE_LINKER_PRAGMA * NTask, NISR, NQueue, NSemaphore, NMutex
* *
* Macro which should be defined as an integer value, default is 0. * A group of macros which should be defined as integer values, zero or larger.
* *
* If this is 1, the header file "recorderdata_linker_pragma.h" is included just * These define the capacity of the Object Property Table, i.e., the maximum
* before the declaration of RecorderData (in trcBase.c), i.e., the trace data * number of objects active at any given point, within each object class (e.g.,
* structure. This allows the user to specify a pragma with linker options. * task, queue, semaphore, ...).
* *
* Example (for IAR Embedded Workbench and NXP LPC17xx): * If tasks or other other objects are deleted in your system, this
* #pragma location="AHB_RAM_MEMORY" * setting does not limit the total amount of objects created, only the number
* * of objects that have been successfully created but not yet deleted.
* This example instructs the IAR linker to place RecorderData in another RAM *
* bank, the AHB RAM. This can also be used for other compilers with a similar * Using too small values will cause vTraceError to be called, which stores an
* pragmas for linker options. * error message in the trace that is shown when opening the trace file.
* *
* Note that this only applies if using static allocation, see below. * 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 100
#define NISR 60
#define NQueue 60
#define NSemaphore 60
#define NMutex 60
#define NTimer 200
#define NEventGroup 60
#define USE_LINKER_PRAGMA 0 /******************************************************************************
* 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 1
/******************************************************************************
* 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 0
/******************************************************************************
* 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 * SYMBOL_TABLE_SIZE
* *
* Macro which should be defined as an integer value. * Macro which should be defined as an integer value.
* *
* This defines the capacity of the symbol table, in bytes. This symbol table * 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 * 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 * objects. If you don't use User Events or delete any kernel
* Object Table. Thus, 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.
* objects you set this to a very low value, e.g. 4, but not zero (0) since * A size of zero (0) is not allowed since a zero-sized array may result in a
* this causes a declaration of a zero-sized array, for which the C compiler * 32-bit pointer, i.e., using 4 bytes rather than 0.
* behavior is not standardized and may cause misaligned data. *
* Default value is 800.
******************************************************************************/ ******************************************************************************/
#define SYMBOL_TABLE_SIZE 5000 #define SYMBOL_TABLE_SIZE 5000
@ -101,16 +297,153 @@
#error "SYMBOL_TABLE_SIZE may not be zero!" #error "SYMBOL_TABLE_SIZE may not be zero!"
#endif #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.
*
* If this is 1, the header file "recorderdata_linker_pragma.h" is included just
* before the declaration of RecorderData (in trcBase.c), i.e., the trace data
* structure. This allows the user to specify a pragma with linker options.
*
* Example (for IAR Embedded Workbench and NXP LPC17xx):
* #pragma location="AHB_RAM_MEMORY"
*
* This example instructs the IAR linker to place RecorderData in another RAM
* bank, the AHB RAM. This can also be used for other compilers with a similar
* pragmas for linker options.
*
* Note that this only applies if using static allocation, see below.
******************************************************************************/
#define USE_LINKER_PRAGMA 0
/******************************************************************************
* USE_IMPLICIT_IFE_RULES
*
* Macro which should be defined as either zero (0) or one (1).
* Default is 1.
*
* 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
/******************************************************************************
* 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 * USE_SEPARATE_USER_EVENT_BUFFER
* *
* Macro which should be defined as an integer value. * Macro which should be defined as an integer value.
* Default is zero (0). * 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 * 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 * task instance named "Unknown actor". This is added as a placeholder when the
* user event history is longer than the task scheduling history. * user event history is longer than the task scheduling history.
******************************************************************************/ ******************************************************************************/
#define USE_SEPARATE_USER_EVENT_BUFFER 0 #define USE_SEPARATE_USER_EVENT_BUFFER 0
@ -125,7 +458,7 @@
* *
* Only in use if USE_SEPARATE_USER_EVENT_BUFFER is set to 1. * Only in use if USE_SEPARATE_USER_EVENT_BUFFER is set to 1.
******************************************************************************/ ******************************************************************************/
#define USER_EVENT_BUFFER_SIZE 500 #define USER_EVENT_BUFFER_SIZE 10
/******************************************************************************* /*******************************************************************************
* USER_EVENT_CHANNELS * USER_EVENT_CHANNELS
@ -138,393 +471,5 @@
******************************************************************************/ ******************************************************************************/
#define CHANNEL_FORMAT_PAIRS 32 #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 100
#define NISR 20
#define NQueue 60
#define NSemaphore 60
#define NMutex 60
#define NTimer 200
#define NEventGroup 60
/* 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 0
/******************************************************************************
* 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_Win32
#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 #endif

View file

@ -66,9 +66,9 @@
/****************************************************************************** /******************************************************************************
* This project provides two demo applications. A simple blinky style project, * This project provides two demo applications. A simple blinky style project,
* and a more comprehensive test and demo application. The * and a more comprehensive test and demo application. The
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two. * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two.
* The simply blinky demo is implemented and described in main_blinky.c. The * The simply blinky demo is implemented and described in main_blinky.c. The
* more comprehensive test and demo application is implemented and described in * more comprehensive test and demo application is implemented and described in
* main_full.c. * main_full.c.
* *
* This file implements the code that is not demo specific, including the * This file implements the code that is not demo specific, including the
@ -80,9 +80,9 @@
* application. It is provided as a convenient development and demonstration * application. It is provided as a convenient development and demonstration
* test bed only. This was tested using Windows XP on a dual core laptop. * test bed only. This was tested using Windows XP on a dual core laptop.
* *
* Windows will not be running the FreeRTOS simulator threads continuously, so * Windows will not be running the FreeRTOS simulator threads continuously, so
* the timing information in the FreeRTOS+Trace logs have no meaningful units. * the timing information in the FreeRTOS+Trace logs have no meaningful units.
* See the documentation page for the Windows simulator for an explanation of * See the documentation page for the Windows simulator for an explanation of
* the slow timing: * the slow timing:
* http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html * http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html
* - READ THE WEB DOCUMENTATION FOR THIS PORT FOR MORE INFORMATION ON USING IT - * - READ THE WEB DOCUMENTATION FOR THIS PORT FOR MORE INFORMATION ON USING IT -
@ -101,11 +101,20 @@
/* This project provides two demo applications. A simple blinky style project, /* This project provides two demo applications. A simple blinky style project,
and a more comprehensive test and demo application. The and a more comprehensive test and demo application. The
mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two. mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two.
The simply blinky demo is implemented and described in main_blinky.c. The more The simply blinky demo is implemented and described in main_blinky.c. The more
comprehensive test and demo application is implemented and described in comprehensive test and demo application is implemented and described in
main_full.c. */ main_full.c. */
#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 1 #define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0
/* This demo uses heap_5.c, and these constants define the sizes of the regions
that make up the total heap. This is only done to provide an example of heap_5
being used as this demo could easily create one large heap region instead of
multiple smaller heap regions - in which case heap_4.c would be the more
appropriate choice. */
#define mainREGION_1_SIZE 3001
#define mainREGION_2_SIZE 18105
#define mainREGION_3_SIZE 1107
/* /*
* main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1. * main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1.
@ -114,15 +123,28 @@ main_full.c. */
extern void main_blinky( void ); extern void main_blinky( void );
extern void main_full( void ); extern void main_full( void );
/* Some of the RTOS hook (callback) functions only need special processing when /*
the full demo is being used. The simply blinky demo has no special requirements, * Some of the RTOS hook (callback) functions only need special processing when
so these functions are called from the hook functions defined in this file, but * the full demo is being used. The simply blinky demo has no special
are defined in main_full.c. */ * requirements, so these functions are called from the hook functions defined
* in this file, but are defined in main_full.c.
*/
void vFullDemoTickHookFunction( void ); void vFullDemoTickHookFunction( void );
void vFullDemoIdleFunction( void ); void vFullDemoIdleFunction( void );
/* Prototypes for the standard FreeRTOS callback/hook functions implemented /*
within this file. */ * This demo uses heap_5.c, so start by defining some heap regions. This is
* only done to provide an example as this demo could easily create one large
* heap region instead of multiple smaller heap regions - in which case heap_4.c
* would be the more appropriate choice. No initialisation is required when
* heap_4.c is used.
*/
static void prvInitialiseHeap( void );
/*
* Prototypes for the standard FreeRTOS callback/hook functions implemented
* within this file.
*/
void vApplicationMallocFailedHook( void ); void vApplicationMallocFailedHook( void );
void vApplicationIdleHook( void ); void vApplicationIdleHook( void );
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ); void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );
@ -145,6 +167,13 @@ static portBASE_TYPE xTraceRunning = pdTRUE;
int main( void ) int main( void )
{ {
/* This demo uses heap_5.c, so start by defining some heap regions. This
is only done to provide an example as this demo could easily create one
large heap region instead of multiple smaller heap regions - in which case
heap_4.c would be the more appropriate choice. No initialisation is
required when heap_4.c is used. */
prvInitialiseHeap();
/* Initialise the trace recorder and create the label used to post user /* Initialise the trace recorder and create the label used to post user
events to the trace recording on each tick interrupt. */ events to the trace recording on each tick interrupt. */
vTraceInitTraceData(); vTraceInitTraceData();
@ -251,10 +280,10 @@ void vApplicationTickHook( void )
} }
#endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY */ #endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY */
/* Write a user event to the trace log. /* Write a user event to the trace log.
Note tick events will not appear in the trace recording with regular period Note tick events will not appear in the trace recording with regular period
because this project runs in a Windows simulator, and does not therefore because this project runs in a Windows simulator, and does not therefore
exhibit deterministic behaviour. Windows will run the simulator in exhibit deterministic behaviour. Windows will run the simulator in
bursts. */ bursts. */
vTraceUserEvent( xTickTraceUserEvent ); vTraceUserEvent( xTickTraceUserEvent );
} }
@ -263,26 +292,35 @@ void vApplicationTickHook( void )
void vAssertCalled( unsigned long ulLine, const char * const pcFileName ) void vAssertCalled( unsigned long ulLine, const char * const pcFileName )
{ {
static portBASE_TYPE xPrinted = pdFALSE; static portBASE_TYPE xPrinted = pdFALSE;
volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
/* Parameters are not used. */ /* Parameters are not used. */
( void ) ulLine; ( void ) ulLine;
( void ) pcFileName; ( void ) pcFileName;
taskDISABLE_INTERRUPTS(); taskENTER_CRITICAL();
__asm volatile( "int $3" );
/* Stop the trace recording. */
if( xPrinted == pdFALSE )
{ {
xPrinted = pdTRUE; /* Stop the trace recording. */
if( xTraceRunning == pdTRUE ) if( xPrinted == pdFALSE )
{ {
vTraceStop(); xPrinted = pdTRUE;
prvSaveTraceFile(); if( xTraceRunning == pdTRUE )
{
vTraceStop();
prvSaveTraceFile();
}
}
/* You can step out of this function to debug the assertion by using
the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero
value. */
while( ulSetToNonZeroInDebuggerToContinue == 0 )
{
__asm volatile( "NOP" );
__asm volatile( "NOP" );
} }
} }
taskEXIT_CRITICAL();
taskENABLE_INTERRUPTS();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -303,3 +341,34 @@ FILE* pxOutputFile;
printf( "\r\nFailed to create trace dump file\r\n" ); printf( "\r\nFailed to create trace dump file\r\n" );
} }
} }
/*-----------------------------------------------------------*/
static void prvInitialiseHeap( void )
{
/* This demo uses heap_5.c, so start by defining some heap regions. This is
only done to provide an example as this demo could easily create one large heap
region instead of multiple smaller heap regions - in which case heap_4.c would
be the more appropriate choice. No initialisation is required when heap_4.c is
used. The xHeapRegions structure requires the regions to be defined in order,
so this just creates one big array, then populates the structure with offsets
into the array - with gaps in between and messy alignment just for test
purposes. */
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
volatile uint32_t ulAdditionalOffset = 19; /* Just to prevent 'condition is always true' warnings in configASSERT(). */
const HeapRegion_t xHeapRegions[] =
{
/* Start address with dummy offsets Size */
{ ucHeap + 1, mainREGION_1_SIZE },
{ ucHeap + 15 + mainREGION_1_SIZE, mainREGION_2_SIZE },
{ ucHeap + 19 + mainREGION_1_SIZE + mainREGION_2_SIZE, mainREGION_3_SIZE },
{ NULL, 0 }
};
/* Sanity check that the sizes and offsets defined actually fit into the
array. */
configASSERT( ( ulAdditionalOffset + mainREGION_1_SIZE + mainREGION_2_SIZE + mainREGION_3_SIZE ) < configTOTAL_HEAP_SIZE );
vPortDefineHeapRegions( xHeapRegions );
}
/*-----------------------------------------------------------*/

View file

@ -190,6 +190,7 @@ static void prvQueueSendTask( void *pvParameters )
{ {
TickType_t xNextWakeTime; TickType_t xNextWakeTime;
const unsigned long ulValueToSend = 100UL; const unsigned long ulValueToSend = 100UL;
const TickType_t xBlockTime = pdMS_TO_TICKS( mainQUEUE_SEND_FREQUENCY_MS );
/* Remove compiler warning in the case that configASSERT() is not /* Remove compiler warning in the case that configASSERT() is not
defined. */ defined. */
@ -207,7 +208,7 @@ const unsigned long ulValueToSend = 100UL;
The block time is specified in ticks, the constant used converts ticks The block time is specified in ticks, the constant used converts ticks
to ms. While in the Blocked state this task will not consume any CPU to ms. While in the Blocked state this task will not consume any CPU
time. */ time. */
vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS ); vTaskDelayUntil( &xNextWakeTime, xBlockTime );
/* Send to the queue - causing the queue receive task to unblock and /* Send to the queue - causing the queue receive task to unblock and
toggle the LED. 0 is used as the block time so the sending operation toggle the LED. 0 is used as the block time so the sending operation

View file

@ -133,6 +133,8 @@
#include "QueueSet.h" #include "QueueSet.h"
#include "QueueOverwrite.h" #include "QueueOverwrite.h"
#include "EventGroupsDemo.h" #include "EventGroupsDemo.h"
#include "IntSemTest.h"
#include "TaskNotify.h"
/* Priorities at which the tasks are created. */ /* Priorities at which the tasks are created. */
#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) #define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )
@ -162,7 +164,7 @@ static void prvTestTask( void *pvParameters );
static void prvDemonstrateTaskStateAndHandleGetFunctions( void ); static void prvDemonstrateTaskStateAndHandleGetFunctions( void );
/* /*
* Called from the idle task hook function to demonstrate the use of * Called from the idle task hook function to demonstrate the use of
* xTimerPendFunctionCall() as xTimerPendFunctionCall() is not demonstrated by * xTimerPendFunctionCall() as xTimerPendFunctionCall() is not demonstrated by
* any of the standard demo tasks. * any of the standard demo tasks.
*/ */
@ -195,6 +197,7 @@ int main_full( void )
xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
/* Create the standard demo tasks. */ /* Create the standard demo tasks. */
vStartTaskNotifyTask();
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
@ -209,6 +212,7 @@ int main_full( void )
vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY ); vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );
xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
vStartEventGroupTasks(); vStartEventGroupTasks();
vStartInterruptSemaphoreTasks();
#if( configUSE_PREEMPTION != 0 ) #if( configUSE_PREEMPTION != 0 )
{ {
@ -263,7 +267,16 @@ const TickType_t xCycleFrequency = 2500 / portTICK_PERIOD_MS;
} }
#endif #endif
if( xAreEventGroupTasksStillRunning() != pdTRUE ) if( xAreTaskNotificationTasksStillRunning() != pdTRUE )
{
pcStatusMessage = "Error: Notification";
}
if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE )
{
pcStatusMessage = "Error: IntSem";
}
else if( xAreEventGroupTasksStillRunning() != pdTRUE )
{ {
pcStatusMessage = "Error: EventGroup"; pcStatusMessage = "Error: EventGroup";
} }
@ -374,7 +387,7 @@ void *pvAllocated;
xMutexToDelete = NULL; xMutexToDelete = NULL;
} }
/* Exercise heap_4 a bit. The malloc failed hook will trap failed /* Exercise heap_5 a bit. The malloc failed hook will trap failed
allocations so there is no need to test here. */ allocations so there is no need to test here. */
pvAllocated = pvPortMalloc( ( rand() % 100 ) + 1 ); pvAllocated = pvPortMalloc( ( rand() % 100 ) + 1 );
vPortFree( pvAllocated ); vPortFree( pvAllocated );
@ -402,6 +415,12 @@ void vFullDemoTickHookFunction( void )
/* Exercise event groups from interrupts. */ /* Exercise event groups from interrupts. */
vPeriodicEventGroupsProcessing(); vPeriodicEventGroupsProcessing();
/* Exercise giving mutexes from an interrupt. */
vInterruptSemaphorePeriodicTest();
/* Exercise using task notifications from an interrupt. */
xNotifyTaskFromISR();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
[InternetShortcut]
URL=http://www.freertos.org/a00090.html
IDList=

View file

@ -1,3 +1,6 @@
Links to a documentation page for each demo are provided on the following
URL: http://www.freertos.org/a00090.html
Each RTOS port has a demo application to demonstrate it's use. Each RTOS port has a demo application to demonstrate it's use.
+ The Demo/Common directory contains the demo application files as described on + The Demo/Common directory contains the demo application files as described on

View file

@ -35,8 +35,10 @@ work under terms of your choice, provided that
+ The combined work is not itself an RTOS, scheduler, kernel or related product. + The combined work is not itself an RTOS, scheduler, kernel or related product.
+ The independent modules add significant and primary functionality to FreeRTOS + The independent modules add significant and primary functionality that is
and do not merely extend the existing functionality already present in FreeRTOS. unrelated to multitasking, intertask communication or intertask signalling -
and therefore do not merely extend the functionality already present in
FreeRTOS.
Clause 2: Clause 2:

View file

@ -276,6 +276,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
/* Check the user is not attempting to wait on the bits used by the kernel /* Check the user is not attempting to wait on the bits used by the kernel
itself, and that at least one bit is being requested. */ itself, and that at least one bit is being requested. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
configASSERT( uxBitsToWaitFor != 0 ); configASSERT( uxBitsToWaitFor != 0 );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
@ -421,6 +422,7 @@ EventBits_t uxReturn;
/* Check the user is not attempting to clear the bits used by the kernel /* Check the user is not attempting to clear the bits used by the kernel
itself. */ itself. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
taskENTER_CRITICAL(); taskENTER_CRITICAL();
@ -482,6 +484,7 @@ BaseType_t xMatchFound = pdFALSE;
/* Check the user is not attempting to set the bits used by the kernel /* Check the user is not attempting to set the bits used by the kernel
itself. */ itself. */
configASSERT( xEventGroup );
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
pxList = &( pxEventBits->xTasksWaitingForBits ); pxList = &( pxEventBits->xTasksWaitingForBits );

View file

@ -723,6 +723,10 @@ extern "C" {
#define configAPPLICATION_ALLOCATED_HEAP 0 #define configAPPLICATION_ALLOCATED_HEAP 0
#endif #endif
#ifndef configUSE_TASK_NOTIFICATIONS
#define configUSE_TASK_NOTIFICATIONS 1
#endif
/* Definitions to allow backward compatibility with FreeRTOS versions prior to /* Definitions to allow backward compatibility with FreeRTOS versions prior to
V8 if desired. */ V8 if desired. */
#ifndef configENABLE_BACKWARD_COMPATIBILITY #ifndef configENABLE_BACKWARD_COMPATIBILITY

View file

@ -0,0 +1,317 @@
/*
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
#ifndef DEPRECATED_DEFINITIONS_H
#define DEPRECATED_DEFINITIONS_H
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
pre-processor definition was used to ensure the pre-processor found the correct
portmacro.h file for the port being used. That scheme was deprecated in favour
of setting the compiler's include path such that it found the correct
portmacro.h file - removing the need for the constant and allowing the
portmacro.h file to be located anywhere in relation to the port being used. The
definitions below remain in the code for backward compatibility only. New
projects should not use them. */
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef GCC_MEGA_AVR
#include "../portable/GCC/ATMega323/portmacro.h"
#endif
#ifdef IAR_MEGA_AVR
#include "../portable/IAR/ATMega323/portmacro.h"
#endif
#ifdef MPLAB_PIC24_PORT
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
#endif
#ifdef MPLAB_DSPIC_PORT
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
#endif
#ifdef MPLAB_PIC18F_PORT
#include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
#endif
#ifdef MPLAB_PIC32MX_PORT
#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
#endif
#ifdef _FEDPICC
#include "libFreeRTOS/Include/portmacro.h"
#endif
#ifdef SDCC_CYGNAL
#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
#endif
#ifdef GCC_ARM7
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
#endif
#ifdef GCC_ARM7_ECLIPSE
#include "portmacro.h"
#endif
#ifdef ROWLEY_LPC23xx
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
#endif
#ifdef IAR_MSP430
#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
#endif
#ifdef GCC_MSP430
#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
#endif
#ifdef ROWLEY_MSP430
#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
#endif
#ifdef ARM7_LPC21xx_KEIL_RVDS
#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
#endif
#ifdef SAM7_GCC
#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
#endif
#ifdef SAM7_IAR
#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
#endif
#ifdef SAM9XE_IAR
#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
#endif
#ifdef LPC2000_IAR
#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
#endif
#ifdef STR71X_IAR
#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
#endif
#ifdef STR75X_IAR
#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
#endif
#ifdef STR75X_GCC
#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
#endif
#ifdef STR91X_IAR
#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
#endif
#ifdef GCC_H8S
#include "../../Source/portable/GCC/H8S2329/portmacro.h"
#endif
#ifdef GCC_AT91FR40008
#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
#endif
#ifdef RVDS_ARMCM3_LM3S102
#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
#endif
#ifdef GCC_ARMCM3_LM3S102
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
#endif
#ifdef GCC_ARMCM3
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
#endif
#ifdef IAR_ARM_CM3
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
#endif
#ifdef IAR_ARMCM3_LM
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
#endif
#ifdef HCS12_CODE_WARRIOR
#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
#endif
#ifdef MICROBLAZE_GCC
#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
#endif
#ifdef TERN_EE
#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
#endif
#ifdef GCC_HCS12
#include "../../Source/portable/GCC/HCS12/portmacro.h"
#endif
#ifdef GCC_MCF5235
#include "../../Source/portable/GCC/MCF5235/portmacro.h"
#endif
#ifdef COLDFIRE_V2_GCC
#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
#endif
#ifdef COLDFIRE_V2_CODEWARRIOR
#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
#endif
#ifdef GCC_PPC405
#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
#endif
#ifdef GCC_PPC440
#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
#endif
#ifdef _16FX_SOFTUNE
#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
#endif
#ifdef BCC_INDUSTRIAL_PC_PORT
/* A short file name has to be used in place of the normal
FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h"
#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef BCC_FLASH_LITE_186_PORT
/* A short file name has to be used in place of the normal
FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h"
#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef __GNUC__
#ifdef __AVR32_AVR32A__
#include "portmacro.h"
#endif
#endif
#ifdef __ICCAVR32__
#ifdef __CORE__
#if __CORE__ == __AVR32A__
#include "portmacro.h"
#endif
#endif
#endif
#ifdef __91467D
#include "portmacro.h"
#endif
#ifdef __96340
#include "portmacro.h"
#endif
#ifdef __IAR_V850ES_Fx3__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx3__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx3_L__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx2__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Hx2__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_78K0R_Kx3__
#include "../../Source/portable/IAR/78K0R/portmacro.h"
#endif
#ifdef __IAR_78K0R_Kx3L__
#include "../../Source/portable/IAR/78K0R/portmacro.h"
#endif
#endif /* DEPRECATED_DEFINITIONS_H */

View file

@ -70,253 +70,22 @@
#ifndef PORTABLE_H #ifndef PORTABLE_H
#define PORTABLE_H #define PORTABLE_H
/* Include the macro file relevant to the port being used. /* Each FreeRTOS port has a unique portmacro.h header file. Originally a
NOTE: The following definitions are *DEPRECATED* as it is preferred to instead pre-processor definition was used to ensure the pre-processor found the correct
just add the path to the correct portmacro.h header file to the compiler's portmacro.h file for the port being used. That scheme was deprecated in favour
include path. */ of setting the compiler's include path such that it found the correct
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT portmacro.h file - removing the need for the constant and allowing the
#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" portmacro.h file to be located anywhere in relation to the port being used.
typedef void ( __interrupt __far *pxISR )(); Purely for reasons of backward compatibility the old method is still valid, but
#endif to make it clear that new projects should not use it, support for the port
specific constants has been moved into the deprecated_definitions.h header
file. */
#include "deprecated_definitions.h"
#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT /* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" did not result in a portmacro.h header file being included - and it should be
typedef void ( __interrupt __far *pxISR )(); included here. In this case the path to the correct portmacro.h header file
#endif must be set in the compiler's include path. */
#ifdef GCC_MEGA_AVR
#include "../portable/GCC/ATMega323/portmacro.h"
#endif
#ifdef IAR_MEGA_AVR
#include "../portable/IAR/ATMega323/portmacro.h"
#endif
#ifdef MPLAB_PIC24_PORT
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
#endif
#ifdef MPLAB_DSPIC_PORT
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
#endif
#ifdef MPLAB_PIC18F_PORT
#include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
#endif
#ifdef MPLAB_PIC32MX_PORT
#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
#endif
#ifdef _FEDPICC
#include "libFreeRTOS/Include/portmacro.h"
#endif
#ifdef SDCC_CYGNAL
#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
#endif
#ifdef GCC_ARM7
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
#endif
#ifdef GCC_ARM7_ECLIPSE
#include "portmacro.h"
#endif
#ifdef ROWLEY_LPC23xx
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
#endif
#ifdef IAR_MSP430
#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
#endif
#ifdef GCC_MSP430
#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
#endif
#ifdef ROWLEY_MSP430
#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
#endif
#ifdef ARM7_LPC21xx_KEIL_RVDS
#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
#endif
#ifdef SAM7_GCC
#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
#endif
#ifdef SAM7_IAR
#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
#endif
#ifdef SAM9XE_IAR
#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
#endif
#ifdef LPC2000_IAR
#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
#endif
#ifdef STR71X_IAR
#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
#endif
#ifdef STR75X_IAR
#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
#endif
#ifdef STR75X_GCC
#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
#endif
#ifdef STR91X_IAR
#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
#endif
#ifdef GCC_H8S
#include "../../Source/portable/GCC/H8S2329/portmacro.h"
#endif
#ifdef GCC_AT91FR40008
#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
#endif
#ifdef RVDS_ARMCM3_LM3S102
#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
#endif
#ifdef GCC_ARMCM3_LM3S102
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
#endif
#ifdef GCC_ARMCM3
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
#endif
#ifdef IAR_ARM_CM3
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
#endif
#ifdef IAR_ARMCM3_LM
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
#endif
#ifdef HCS12_CODE_WARRIOR
#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
#endif
#ifdef MICROBLAZE_GCC
#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
#endif
#ifdef TERN_EE
#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
#endif
#ifdef GCC_HCS12
#include "../../Source/portable/GCC/HCS12/portmacro.h"
#endif
#ifdef GCC_MCF5235
#include "../../Source/portable/GCC/MCF5235/portmacro.h"
#endif
#ifdef COLDFIRE_V2_GCC
#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
#endif
#ifdef COLDFIRE_V2_CODEWARRIOR
#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
#endif
#ifdef GCC_PPC405
#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
#endif
#ifdef GCC_PPC440
#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
#endif
#ifdef _16FX_SOFTUNE
#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
#endif
#ifdef BCC_INDUSTRIAL_PC_PORT
/* A short file name has to be used in place of the normal
FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h"
#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef BCC_FLASH_LITE_186_PORT
/* A short file name has to be used in place of the normal
FreeRTOSConfig.h when using the Borland compiler. */
#include "frconfig.h"
#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
typedef void ( __interrupt __far *pxISR )();
#endif
#ifdef __GNUC__
#ifdef __AVR32_AVR32A__
#include "portmacro.h"
#endif
#endif
#ifdef __ICCAVR32__
#ifdef __CORE__
#if __CORE__ == __AVR32A__
#include "portmacro.h"
#endif
#endif
#endif
#ifdef __91467D
#include "portmacro.h"
#endif
#ifdef __96340
#include "portmacro.h"
#endif
#ifdef __IAR_V850ES_Fx3__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx3__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx3_L__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Jx2__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_V850ES_Hx2__
#include "../../Source/portable/IAR/V850ES/portmacro.h"
#endif
#ifdef __IAR_78K0R_Kx3__
#include "../../Source/portable/IAR/78K0R/portmacro.h"
#endif
#ifdef __IAR_78K0R_Kx3L__
#include "../../Source/portable/IAR/78K0R/portmacro.h"
#endif
/* Catch all to ensure portmacro.h is included in the build. Newer demos
have the path as part of the project options, rather than as relative from
the project location. If portENTER_CRITICAL() has not been defined then
portmacro.h has not yet been included - as every portmacro.h provides a
portENTER_CRITICAL() definition. Check the demo application for your demo
to find the path to the correct portmacro.h file. */
#ifndef portENTER_CRITICAL #ifndef portENTER_CRITICAL
#include "portmacro.h" #include "portmacro.h"
#endif #endif
@ -370,15 +139,15 @@ typedef struct HeapRegion
size_t xSizeInBytes; size_t xSizeInBytes;
} HeapRegion_t; } HeapRegion_t;
/* /*
* Used to define multiple heap regions for use by heap_5.c. This function * Used to define multiple heap regions for use by heap_5.c. This function
* must be called before any calls to pvPortMalloc() - not creating a task, * must be called before any calls to pvPortMalloc() - not creating a task,
* queue, semaphore, mutex, software timer, event group, etc. will result in * queue, semaphore, mutex, software timer, event group, etc. will result in
* pvPortMalloc being called. * pvPortMalloc being called.
* *
* pxHeapRegions passes in an array of HeapRegion_t structures - each of which * pxHeapRegions passes in an array of HeapRegion_t structures - each of which
* defines a region of memory that can be used as the heap. The array is * defines a region of memory that can be used as the heap. The array is
* terminated by a HeapRegions_t structure that has a size of 0. The region * terminated by a HeapRegions_t structure that has a size of 0. The region
* with the lowest start address must appear first in the array. * with the lowest start address must appear first in the array.
*/ */
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ); void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions );

View file

@ -114,13 +114,23 @@ typedef enum
eDeleted /* The task being queried has been deleted, but its TCB has not yet been freed. */ eDeleted /* The task being queried has been deleted, but its TCB has not yet been freed. */
} eTaskState; } eTaskState;
/* Actions that can be performed when vTaskNotify() is called. */
typedef enum
{
eNoAction, /* Notify the task without updating its notify value. */
eSetBits, /* Set bits in the task's notification value. */
eIncrement, /* Increment the task's notification value. */
eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */
eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */
} eNotifyAction;
/* /*
* Used internally only. * Used internally only.
*/ */
typedef struct xTIME_OUT typedef struct xTIME_OUT
{ {
BaseType_t xOverflowCount; BaseType_t xOverflowCount;
TickType_t xTimeOnEntering; TickType_t xTimeOnEntering;
} TimeOut_t; } TimeOut_t;
/* /*
@ -1358,6 +1368,432 @@ void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unquali
*/ */
void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/**
* task. h
* <PRE>BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );</PRE>
*
* configUSE_TASK_NOTIFICATIONS must be defined as 1 for this function to be
* available.
*
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
* "notification value", which is a 32-bit unsigned integer (uint32_t).
*
* Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications
* are a method of sending an event directly to a task without the need for such
* an intermediary object.
*
* A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way
* task notifications can be used to send data to a task, or be used as light
* weight and fast binary or counting semaphores.
*
* A notification sent to a task will remain pending until it is cleared by the
* task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was
* already in the Blocked state to wait for a notification when the notification
* arrives then the task will automatically be removed from the Blocked state
* (unblocked) and the notification cleared.
*
* A task can use xTaskNotifyWait() to [optionally] block to wait for a
* notification to be pending, or xTaskNotifyTake() to [optionally] block
* to wait for its notification value to have a non-zero value. The task does
* not consume any CPU time while it is in the Blocked state.
*
* See http://www.FreeRTOS.org/RTOS_task_notifications.html for details of when
* it is best to use a task notification to send an event to a task compared to
* when it is best to use an intermediary object (such as a queue, semaphore,
* mutex or event group) to send an event to a task.
*
* @param xTaskToNotify The handle of the task being notified. The handle to a
* task can be returned from the xTaskCreate() API function used to create the
* task, and the handle of the currently running task can be obtained by calling
* xTaskGetCurrentTaskHandle().
*
* @param ulValue Data that can be sent with the notification. How the data is
* used depends on the value of the eAction parameter.
*
* @param eAction Specifies how the notification updates the task's notification
* value, if at all. Valid values for eAction are as follows:
*
* eSetBits -
* The task's notification value is bitwise ORed with ulValue. xTaskNofify()
* always returns pdPASS in this case.
*
* eIncrement -
* The task's notification value is incremented. ulValue is not used and
* xTaskNotify() always returns pdPASS in this case.
*
* eSetValueWithOverwrite -
* The task's notification value is set to the value of ulValue, even if the
* task being notified had not yet processed the previous notification (the
* task already had a notification pending). xTaskNotify() always returns
* pdPASS in this case.
*
* eSetValueWithoutOverwrite -
* If the task being notified did not already have a notification pending then
* the task's notification value is set to ulValue and xTaskNotify() will
* return pdPASS. If the task being notified already had a notification
* pending then no action is performed and pdFAIL is returned.
*
* eNoAction -
* The task receives a notification without its notification value being
* updated. ulValue is not used and xTaskNotify() always returns pdPASS in
* this case.
*
* @return Dependent on the value of eAction. See the description of the
* eAction parameter.
*
* \defgroup xTaskNotify xTaskNotify
* \ingroup TaskNotifications
*/
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
/**
* task. h
* <PRE>BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );</PRE>
*
* configUSE_TASK_NOTIFICATIONS must be defined as 1 for this function to be
* available.
*
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
* "notification value", which is a 32-bit unsigned integer (uint32_t).
*
* A version of xTaskNotify() that can be used from an interrupt service routine
* (ISR).
*
* Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications
* are a method of sending an event directly to a task without the need for such
* an intermediary object.
*
* A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way
* task notifications can be used to send data to a task, or be used as light
* weight and fast binary or counting semaphores.
*
* A notification sent to a task will remain pending until it is cleared by the
* task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was
* already in the Blocked state to wait for a notification when the notification
* arrives then the task will automatically be removed from the Blocked state
* (unblocked) and the notification cleared.
*
* A task can use xTaskNotifyWait() to [optionally] block to wait for a
* notification to be pending, or xTaskNotifyTake() to [optionally] block
* to wait for its notification value to have a non-zero value. The task does
* not consume any CPU time while it is in the Blocked state.
*
* See http://www.FreeRTOS.org/RTOS_task_notifications.html for details of when
* it is best to use a task notification to send an event to a task compared to
* when it is best to use an intermediary object (such as a queue, semaphore,
* mutex or event group) to send an event to a task.
*
* @param xTaskToNotify The handle of the task being notified. The handle to a
* task can be returned from the xTaskCreate() API function used to create the
* task, and the handle of the currently running task can be obtained by calling
* xTaskGetCurrentTaskHandle().
*
* @param ulValue Data that can be sent with the notification. How the data is
* used depends on the value of the eAction parameter.
*
* @param eAction Specifies how the notification updates the task's notification
* value, if at all. Valid values for eAction are as follows:
*
* eSetBits -
* The task's notification value is bitwise ORed with ulValue. xTaskNofify()
* always returns pdPASS in this case.
*
* eIncrement -
* The task's notification value is incremented. ulValue is not used and
* xTaskNotify() always returns pdPASS in this case.
*
* eSetValueWithOverwrite -
* The task's notification value is set to the value of ulValue, even if the
* task being notified had not yet processed the previous notification (the
* task already had a notification pending). xTaskNotify() always returns
* pdPASS in this case.
*
* eSetValueWithoutOverwrite -
* If the task being notified did not already have a notification pending then
* the task's notification value is set to ulValue and xTaskNotify() will
* return pdPASS. If the task being notified already had a notification
* pending then no action is performed and pdFAIL is returned.
*
* eNoAction -
* The task receives a notification without its notification value being
* updated. ulValue is not used and xTaskNotify() always returns pdPASS in
* this case.
*
* @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
* task to which the notification was sent to leave the Blocked state, and the
* unblocked task has a priority higher than the currently running task. If
* xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should
* be requested before the interrupt is exited. How a context switch is
* requested from an ISR is dependent on the port - see the documentation page
* for the port in use.
*
* @return Dependent on the value of eAction. See the description of the
* eAction parameter.
*
* \defgroup xTaskNotify xTaskNotify
* \ingroup TaskNotifications
*/
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
/**
* task. h
* <PRE>BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, BaseType_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );</pre>
*
* configUSE_TASK_NOTIFICATIONS must be defined as 1 for this function to be
* available.
*
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
* "notification value", which is a 32-bit unsigned integer (uint32_t).
*
* Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications
* are a method of sending an event directly to a task without the need for such
* an intermediary object.
*
* A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way
* task notifications can be used to send data to a task, or be used as light
* weight and fast binary or counting semaphores.
*
* A notification sent to a task will remain pending until it is cleared by the
* task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was
* already in the Blocked state to wait for a notification when the notification
* arrives then the task will automatically be removed from the Blocked state
* (unblocked) and the notification cleared.
*
* A task can use xTaskNotifyWait() to [optionally] block to wait for a
* notification to be pending, or xTaskNotifyTake() to [optionally] block
* to wait for its notification value to have a non-zero value. The task does
* not consume any CPU time while it is in the Blocked state.
*
* See http://www.FreeRTOS.org/RTOS_task_notifications.html for details of when
* it is best to use a task notification to send an event to a task compared to
* when it is best to use an intermediary object (such as a queue, semaphore,
* mutex or event group) to send an event to a task.
*
* @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value
* will be cleared in the calling task's notification value before the task
* checks to see if any notifications are pending, and optionally blocks if no
* notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if
* limits.h is included) or 0xffffffffUL (if limits.h is not included) will have
* the effect of resetting the task's notification value to 0. Setting
* ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged.
*
* @param ulBitsToClearOnExit If a notification is pending or received before
* the calling task exits the xTaskNotifyWait() function then the task's
* notification value (see the xTaskNotify() API function) is passed out using
* the pulNotificationValue parameter. Then any bits that are set in
* ulBitsToClearOnExit will be cleared in the task's notification value (note
* *pulNotificationValue is set before any bits are cleared). Setting
* ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL
* (if limits.h is not included) will have the effect of resetting the task's
* notification value to 0 before the function exits. Setting
* ulBitsToClearOnExit to 0 will leave the task's notification value unchanged
* when the function exits (in which case the value passed out in
* pulNotificationValue will match the task's notification value).
*
* @param pulNotificationValue Used to pass the task's notification value out
* of the function. Note the value passed out will not be effected by the
* clearing of any bits caused by ulBitsToClearOnExit being non-zero.
*
* @param xTicksToWait The maximum amount of time that the task should wait in
* the Blocked state for a notification to be received, should a notification
* not already be pending when xTaskNotifyWait() was called. The task
* will not consume any processing time while it is in the Blocked state. This
* is specified in kernel ticks, the macro pdMS_TO_TICSK( value_in_ms ) can be
* used to convert a time specified in milliseconds to a time specified in
* ticks.
*
* @return If a notification was received (including notifications that were
* already pending when xTaskNotifyWait was called) then pdPASS is
* returned. Otherwise pdFAIL is returned.
*
* \defgroup xTaskNotifyWait xTaskNotifyWait
* \ingroup TaskNotifications
*/
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, BaseType_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
/**
* task. h
* <PRE>BaseType_t xTaskNotifyGive( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
*
* configUSE_TASK_NOTIFICATIONS must be defined as 1 for this macro to be
* available.
*
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
* "notification value", which is a 32-bit unsigned integer (uint32_t).
*
* Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications
* are a method of sending an event directly to a task without the need for such
* an intermediary object.
*
* A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way
* task notifications can be used to send data to a task, or be used as light
* weight and fast binary or counting semaphores.
*
* xTaskNotifyGive() is a helper macro intended for use when task notifications
* are used as light weight and faster binary or counting semaphore equivalents.
* Actual FreeRTOS semaphores are given using the xSemaphoreGive() API function,
* the equivalent action that instead uses a task notification is
* xTaskNotifyGive().
*
* When task notifications are being used as a binary or counting semaphore
* equivalent then the task being notified should wait for the notification
* using the ulTaskNotificationTake() API function rather than the
* xTaskNotifyWait() API function.
*
* See http://www.FreeRTOS.org/RTOS_task_notifications.html for more details.
*
* @param xTaskToNotify The handle of the task being notified. The handle to a
* task can be returned from the xTaskCreate() API function used to create the
* task, and the handle of the currently running task can be obtained by calling
* xTaskGetCurrentTaskHandle().
*
* @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the
* eAction parameter set to eIncrement - so pdPASS is always returned.
*
* \defgroup xTaskNotifyGive xTaskNotifyGive
* \ingroup TaskNotifications
*/
#define xTaskNotifyGive( xTaskToNotify ) xTaskNotify( ( xTaskToNotify ), 0, eIncrement );
/**
* task. h
* <PRE>BaseType_t xTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
*
* configUSE_TASK_NOTIFICATIONS must be defined as 1 for this macro to be
* available.
*
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
* "notification value", which is a 32-bit unsigned integer (uint32_t).
*
* A version of xTaskNotifyGive() that can be called from an interrupt service
* routine (ISR).
*
* Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications
* are a method of sending an event directly to a task without the need for such
* an intermediary object.
*
* A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way
* task notifications can be used to send data to a task, or be used as light
* weight and fast binary or counting semaphores.
*
* xTaskNotifyGiveFromISR() is a helper macro intended for use when task
* notifications are used as light weight and faster binary or counting
* semaphore equivalents. Actual FreeRTOS semaphores are given from an ISR
* using the xSemaphoreGiveFromISR() API function, the equivalent action that
* instead uses a task notification is xTaskNotifyGiveFromISR().
*
* When task notifications are being used as a binary or counting semaphore
* equivalent then the task being notified should wait for the notification
* using the ulTaskNotificationTake() API function rather than the
* xTaskNotifyWait() API function.
*
* See http://www.FreeRTOS.org/RTOS_task_notifications.html for more details.
*
* @param xTaskToNotify The handle of the task being notified. The handle to a
* task can be returned from the xTaskCreate() API function used to create the
* task, and the handle of the currently running task can be obtained by calling
* xTaskGetCurrentTaskHandle().
*
* @param pxHigherPriorityTaskWoken xTaskNotifyGiveFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
* task to which the notification was sent to leave the Blocked state, and the
* unblocked task has a priority higher than the currently running task. If
* xTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch
* should be requested before the interrupt is exited. How a context switch is
* requested from an ISR is dependent on the port - see the documentation page
* for the port in use.
*
* @return xTaskNotifyGiveFromISR() is a macro that calls xTaskNotifyFromISR()
* with the eAction parameter set to eIncrement - so pdPASS is always returned.
*
* \defgroup xTaskNotifyWait xTaskNotifyWait
* \ingroup TaskNotifications
*/
#define xTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) xTaskNotifyFromISR( ( xTaskToNotify ), 0, eIncrement, ( pxHigherPriorityTaskWoken ) )
/**
* task. h
* <PRE>uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );</pre>
*
* configUSE_TASK_NOTIFICATIONS must be defined as 1 for this function to be
* available.
*
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
* "notification value", which is a 32-bit unsigned integer (uint32_t).
*
* Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications
* are a method of sending an event directly to a task without the need for such
* an intermediary object.
*
* A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way
* task notifications can be used to send data to a task, or be used as light
* weight and fast binary or counting semaphores.
*
* ulTaskNotifyTake() is intended for use when a task notification is used as a
* faster and lighter weight binary or counting semaphore alternative. Actual
* FreeRTOS semaphores are taken using the xSemaphoreTake() API function, the
* equivalent action that instead uses a task notification is
* xTaskNotifyTake().
*
* When a task is using its notification value as a binary or counting semaphore
* other tasks should send notifications to it using the xTaskNotifyGive()
* macro, or xTaskNotify() function with the eAction parameter set to
* eIncrement.
*
* xTaskNotifyTake() can either clear the task's notification value to
* zero on exit, in which case the notification value acts like a binary
* semaphore, or decrement the task's notification value on exit, in which case
* the notification value acts like a counting semaphore.
*
* A task can use xTaskNotifyTake() to [optionally] block to wait for a
* the tasks notification value to be non-zero. The task does not consume any
* CPU time while it is in the Blocked state.
*
* Where as xTaskNotifyWait() will return when a notification is pending,
* xTaskNotifyTake() will return when the task's notification value is
* not zero.
*
* See http://www.FreeRTOS.org/RTOS_task_notifications.html for details of when
* it is best to use a task notification to send an event to a task compared to
* when it is best to use an intermediary object (such as a queue, semaphore,
* mutex or event group) to send an event to a task.
*
* @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's
* notification value is decremented when the function exits. In this way the
* notification value acts like a counting semaphore. If xClearCountOnExit is
* not pdFALSE then the task's notification value is cleared to zero when the
* function exits. In this way the notification value acts like a binary
* semaphore.
*
* @param xTicksToWait The maximum amount of time that the task should wait in
* the Blocked state for the task's notification value to be greater than zero,
* should the count not already be greater than zero when
* xTaskNotifyTake() was called. The task will not consume any processing
* time while it is in the Blocked state. This is specified in kernel ticks,
* the macro pdMS_TO_TICSK( value_in_ms ) can be used to convert a time
* specified in milliseconds to a time specified in ticks.
*
* @return The task's notification count before it is either cleared to zero or
* decremented (see the xClearCountOnExit parameter).
*
* \defgroup ulTaskNotifyTake ulTaskNotifyTake
* \ingroup TaskNotifications
*/
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
/*----------------------------------------------------------- /*-----------------------------------------------------------
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
*----------------------------------------------------------*/ *----------------------------------------------------------*/

View file

@ -125,13 +125,12 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* Insert the new list item into the list, sorted in xItemValue order. /* Insert the new list item into the list, sorted in xItemValue order.
If the list already contains a list item with the same item value then If the list already contains a list item with the same item value then the
the new list item should be placed after it. This ensures that TCB's which new list item should be placed after it. This ensures that TCB's which are
are stored in ready lists (all of which have the same xItemValue value) stored in ready lists (all of which have the same xItemValue value) get a
get an equal share of the CPU. However, if the xItemValue is the same as share of the CPU. However, if the xItemValue is the same as the back marker
the back marker the iteration loop below will not end. This means we need the iteration loop below will not end. Therefore the value is checked
to guard against this by checking the value first and modifying the first, and the algorithm slightly modified if necessary. */
algorithm slightly if necessary. */
if( xValueOfInsertion == portMAX_DELAY ) if( xValueOfInsertion == portMAX_DELAY )
{ {
pxIterator = pxList->xListEnd.pxPrevious; pxIterator = pxList->xListEnd.pxPrevious;
@ -139,27 +138,31 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
else else
{ {
/* *** NOTE *********************************************************** /* *** NOTE ***********************************************************
If you find your application is crashing here then likely causes are: If you find your application is crashing here then likely causes are
listed below. In addition see http://www.freertos.org/FAQHelp.html for
more tips, and ensure configASSERT() is defined!
http://www.freertos.org/a00110.html#configASSERT
1) Stack overflow - 1) Stack overflow -
see http://www.freertos.org/Stacks-and-stack-overflow-checking.html see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
2) Incorrect interrupt priority assignment, especially on Cortex-M3 2) Incorrect interrupt priority assignment, especially on Cortex-M
parts where numerically high priority values denote low actual parts where numerically high priority values denote low actual
interrupt priorities, which can seem counter intuitive. See interrupt priorities, which can seem counter intuitive. See
configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html http://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
of configMAX_SYSCALL_INTERRUPT_PRIORITY on
http://www.freertos.org/a00110.html
3) Calling an API function from within a critical section or when 3) Calling an API function from within a critical section or when
the scheduler is suspended, or calling an API function that does the scheduler is suspended, or calling an API function that does
not end in "FromISR" from an interrupt. not end in "FromISR" from an interrupt.
4) Using a queue or semaphore before it has been initialised or 4) Using a queue or semaphore before it has been initialised or
before the scheduler has been started (are interrupts firing before the scheduler has been started (are interrupts firing
before vTaskStartScheduler() has been called?). before vTaskStartScheduler() has been called?).
See http://www.freertos.org/FAQHelp.html for more tips, and ensure
configASSERT() is defined! http://www.freertos.org/a00110.html#configASSERT
**********************************************************************/ **********************************************************************/
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
{ {
/* There is nothing to do here, we are just iterating to the /* There is nothing to do here, just iterating to the wanted
wanted insertion position. */ insertion position. */
} }
} }

View file

@ -167,8 +167,8 @@ the CPU itself before modifying certain hardware registers. */
{ \ { \
portCPU_IRQ_DISABLE(); \ portCPU_IRQ_DISABLE(); \
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
__asm( "DSB \n" \ __asm volatile ( "DSB \n" \
"ISB \n" ); \ "ISB \n" ); \
portCPU_IRQ_ENABLE(); \ portCPU_IRQ_ENABLE(); \
} }

View file

@ -114,7 +114,7 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
#define portPRIGROUP_SHIFT ( 8UL ) #define portPRIGROUP_SHIFT ( 8UL )
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ /* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
#define portVECTACTIVE_MASK ( 0x1FUL ) #define portVECTACTIVE_MASK ( 0xFFUL )
/* Constants required to set up the initial stack. */ /* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000UL ) #define portINITIAL_XPSR ( 0x01000000UL )

View file

@ -111,7 +111,7 @@
#define portPRIGROUP_SHIFT ( 8UL ) #define portPRIGROUP_SHIFT ( 8UL )
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ /* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
#define portVECTACTIVE_MASK ( 0x1FUL ) #define portVECTACTIVE_MASK ( 0xFFUL )
/* Constants required to manipulate the VFP. */ /* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
@ -384,27 +384,13 @@ void vPortEndScheduler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortYield( void )
{
/* Set a PendSV to request a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
/* Barriers are normally not required but do ensure the code is completely
within the specified behaviour for the architecture. */
__asm volatile( "dsb" );
__asm volatile( "isb" );
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
uxCriticalNesting++; uxCriticalNesting++;
__asm volatile( "dsb" );
__asm volatile( "isb" );
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ assert function also uses a critical section. */
@ -426,37 +412,6 @@ void vPortExitCritical( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__attribute__(( naked )) uint32_t ulPortSetInterruptMask( void )
{
__asm volatile \
( \
" mrs r0, basepri \n" \
" mov r1, %0 \n" \
" msr basepri, r1 \n" \
" bx lr \n" \
:: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1" \
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
return 0;
}
/*-----------------------------------------------------------*/
__attribute__(( naked )) void vPortClearInterruptMask( uint32_t ulNewMaskValue )
{
__asm volatile \
( \
" msr basepri, r0 \n" \
" bx lr \n" \
:::"r0" \
);
/* Just to avoid compiler warnings. */
( void ) ulNewMaskValue;
}
/*-----------------------------------------------------------*/
void xPortPendSVHandler( void ) void xPortPendSVHandler( void )
{ {
/* This is a naked function. */ /* This is a naked function. */
@ -480,6 +435,8 @@ void xPortPendSVHandler( void )
" stmdb sp!, {r3} \n" " stmdb sp!, {r3} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" dsb \n"
" isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"

View file

@ -109,25 +109,21 @@ typedef unsigned long UBaseType_t;
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYield( void );
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) vPortYield()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern uint32_t ulPortSetInterruptMask( void ); #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortRaiseBASEPRI()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) #define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
@ -188,6 +184,53 @@ not necessary for to use this port. They are defined so the common demo files
/* portNOP() is not required by this port. */ /* portNOP() is not required by this port. */
#define portNOP() #define portNOP()
#ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline))
#endif
/*-----------------------------------------------------------*/
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
{
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
__asm volatile
(
" mrs %0, basepri \n" \
" mov %1, %2 \n" \
" msr basepri, %1 \n" \
" isb \n" \
" dsb \n" \
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
{
__asm volatile
(
" msr basepri, %0 " :: "r" ( ulNewMaskValue )
);
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static void vPortYield( void )
{
/* Set a PendSV to request a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
/* Barriers are normally not required but do ensure the code is completely
within the specified behaviour for the architecture. */
__asm volatile( "dsb" );
__asm volatile( "isb" );
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -217,7 +217,7 @@ typedef struct PORT_REGISTER_DUMP
/* The human readable name of the task that was running at the time the /* The human readable name of the task that was running at the time the
exception occurred. This is the name that was given to the task when the exception occurred. This is the name that was given to the task when the
task was created using the FreeRTOS xTaskCreate() API function. */ task was created using the FreeRTOS xTaskCreate() API function. */
int8_t *pcCurrentTaskName; char *pcCurrentTaskName;
/* The handle of the task that was running a the time the exception /* The handle of the task that was running a the time the exception
occurred. */ occurred. */

View file

@ -114,7 +114,7 @@
#define portPRIGROUP_SHIFT ( 8UL ) #define portPRIGROUP_SHIFT ( 8UL )
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ /* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
#define portVECTACTIVE_MASK ( 0x1FUL ) #define portVECTACTIVE_MASK ( 0xFFUL )
/* Constants required to set up the initial stack. */ /* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
@ -327,9 +327,9 @@ void vPortEnterCritical( void )
uxCriticalNesting++; uxCriticalNesting++;
__DSB(); __DSB();
__ISB(); __ISB();
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ assert function also uses a critical section. */

View file

@ -118,7 +118,7 @@
#define portPRIGROUP_SHIFT ( 8UL ) #define portPRIGROUP_SHIFT ( 8UL )
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ /* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
#define portVECTACTIVE_MASK ( 0x1FUL ) #define portVECTACTIVE_MASK ( 0xFFUL )
/* Constants required to manipulate the VFP. */ /* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
@ -335,27 +335,13 @@ void vPortEndScheduler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortYield( void )
{
/* Set a PendSV to request a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
/* Barriers are normally not required but do ensure the code is completely
within the specified behaviour for the architecture. */
__DSB();
__ISB();
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
uxCriticalNesting++; uxCriticalNesting++;
__DSB();
__ISB();
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ assert function also uses a critical section. */

View file

@ -72,8 +72,6 @@
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
PUBLIC xPortPendSVHandler PUBLIC xPortPendSVHandler
PUBLIC ulPortSetInterruptMask
PUBLIC vPortClearInterruptMask
PUBLIC vPortSVCHandler PUBLIC vPortSVCHandler
PUBLIC vPortStartFirstTask PUBLIC vPortStartFirstTask
PUBLIC vPortEnableVFP PUBLIC vPortEnableVFP
@ -102,6 +100,8 @@ xPortPendSVHandler:
stmdb sp!, {r3} stmdb sp!, {r3}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0 msr basepri, r0
dsb
isb
bl vTaskSwitchContext bl vTaskSwitchContext
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
@ -134,20 +134,6 @@ xPortPendSVHandler:
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
ulPortSetInterruptMask:
mrs r0, basepri
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1
bx r14
/*-----------------------------------------------------------*/
vPortClearInterruptMask:
msr basepri, r0
bx r14
/*-----------------------------------------------------------*/
vPortSVCHandler: vPortSVCHandler:
/* Get the location of the current TCB. */ /* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB ldr r3, =pxCurrentTCB

View file

@ -110,11 +110,10 @@ typedef unsigned long UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYield( void );
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) vPortYield()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -145,15 +144,13 @@ extern void vPortYield( void );
/* Critical section management. */ /* Critical section management. */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( uint32_t ulNewMask );
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) #define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Tickless idle/low power functionality. */ /* Tickless idle/low power functionality. */
@ -179,6 +176,51 @@ not necessary for to use this port. They are defined so the common demo files
/* portNOP() is not required by this port. */ /* portNOP() is not required by this port. */
#define portNOP() #define portNOP()
#ifndef portFORCE_INLINE
#define portFORCE_INLINE _Pragma("inline=forced")
#endif
portFORCE_INLINE static void vPortYield( void )
{
/* Set a PendSV to request a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
/* Barriers are normally not required but do ensure the code is completely
within the specified behaviour for the architecture. */
__DSB();
__ISB();
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
{
uint32_t ulOriginalBASEPRI;
__asm volatile
(
" mrs %0, basepri \n" \
" mov r1, %1 \n" \
" msr basepri, r1 \n" \
" isb \n" \
" dsb \n" \
:"=r" (ulOriginalBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r1"
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
{
__asm volatile
(
" msr basepri, %0 " :: "r" ( ulNewMaskValue )
);
}
/*-----------------------------------------------------------*/
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
the source code because to do so would cause other compilers to generate the source code because to do so would cause other compilers to generate
warnings. */ warnings. */

View file

@ -111,7 +111,7 @@ is defined. */
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) #define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ /* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
#define portVECTACTIVE_MASK ( 0x1FUL ) #define portVECTACTIVE_MASK ( 0xFFUL )
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )

View file

@ -124,7 +124,7 @@ is defined. */
#define portPRIGROUP_SHIFT ( 8UL ) #define portPRIGROUP_SHIFT ( 8UL )
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ /* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
#define portVECTACTIVE_MASK ( 0x1FUL ) #define portVECTACTIVE_MASK ( 0xFFUL )
/* Constants required to manipulate the VFP. */ /* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
@ -134,9 +134,6 @@ is defined. */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
#define portINITIAL_EXEC_RETURN ( 0xfffffffd ) #define portINITIAL_EXEC_RETURN ( 0xfffffffd )
/* Constants used with memory barrier intrinsics. */
#define portSY_FULL_READ_WRITE ( 15 )
/* The systick is a 24-bit counter. */ /* The systick is a 24-bit counter. */
#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) #define portMAX_24_BIT_NUMBER ( 0xffffffUL )
@ -401,24 +398,10 @@ void vPortEndScheduler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortYield( void )
{
/* Set a PendSV to request a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
/* Barriers are normally not required but do ensure the code is completely
within the specified behaviour for the architecture. */
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE );
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
uxCriticalNesting++; uxCriticalNesting++;
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE );
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
@ -471,6 +454,8 @@ __asm void xPortPendSVHandler( void )
stmdb sp!, {r3} stmdb sp!, {r3}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0 msr basepri, r0
dsb
isb
bl vTaskSwitchContext bl vTaskSwitchContext
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
@ -702,26 +687,6 @@ void xPortSysTickHandler( void )
#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ #endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__asm uint32_t ulPortSetInterruptMask( void )
{
PRESERVE8
mrs r0, basepri
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1
bx r14
}
/*-----------------------------------------------------------*/
__asm void vPortClearInterruptMask( uint32_t ulNewMask )
{
PRESERVE8
msr basepri, r0
bx r14
}
/*-----------------------------------------------------------*/
__asm uint32_t vPortGetIPSR( void ) __asm uint32_t vPortGetIPSR( void )
{ {
PRESERVE8 PRESERVE8

View file

@ -107,29 +107,30 @@ typedef unsigned long UBaseType_t;
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/* Constants used with memory barrier intrinsics. */
#define portSY_FULL_READ_WRITE ( 15 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vPortYield( void );
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) vPortYield()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( uint32_t ulNewMask );
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) #define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -178,6 +179,53 @@ not necessary for to use this port. They are defined so the common demo files
/* portNOP() is not required by this port. */ /* portNOP() is not required by this port. */
#define portNOP() #define portNOP()
#ifndef portFORCE_INLINE
#define portFORCE_INLINE __forceinline
#endif
/*-----------------------------------------------------------*/
static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{
__asm
{
/* Barrier instructions are not used as this function is only used to
lower the BASEPRI value. */
msr basepri, ulBASEPRI
}
}
/*-----------------------------------------------------------*/
static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void )
{
uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
__asm
{
/* Set BASEPRI to the max syscall priority to effect a critical
section. */
mrs ulReturn, basepri
msr basepri, ulNewBASEPRI
dsb
isb
}
return ulReturn;
}
/*-----------------------------------------------------------*/
static portFORCE_INLINE void vPortYield( void )
{
/* Set a PendSV to request a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
/* Barriers are normally not required but do ensure the code is completely
within the specified behaviour for the architecture. */
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE );
}
/*-----------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -82,7 +82,7 @@
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ /* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
#define portVECTACTIVE_MASK ( 0x1FUL ) #define portVECTACTIVE_MASK ( 0xFFUL )
/* Constants required to manipulate the VFP. */ /* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */

View file

@ -1377,8 +1377,8 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{ {
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
/* Is there data in the queue now? To be running we must be /* Is there data in the queue now? To be running the calling task
the highest priority task wanting to access the queue. */ must be the highest priority task wanting to access the queue. */
if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
{ {
/* Remember the read position in case the queue is only being /* Remember the read position in case the queue is only being

View file

@ -114,6 +114,14 @@ functions but without including stdio.h here. */
#define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
#endif #endif
/* Value that can be assigned to the eNotifyState member of the TCB. */
typedef enum
{
eNotWaitingNotification,
eWaitingNotification,
eNotified
} eNotifyValue;
/* /*
* Task control block. A task control block (TCB) is allocated for each task, * Task control block. A task control block (TCB) is allocated for each task,
* and stores task state information, including a pointer to the task's context * and stores task state information, including a pointer to the task's context
@ -170,6 +178,11 @@ typedef struct tskTaskControlBlock
struct _reent xNewLib_reent; struct _reent xNewLib_reent;
#endif #endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulNotifiedValue;
eNotifyValue eNotifyState;
#endif
} tskTCB; } tskTCB;
/* The old tskTCB name is maintained above then typedefed to the new TCB_t name /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
@ -228,8 +241,8 @@ PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY; PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY;
/* Context switches are held pending while the scheduler is suspended. Also, /* Context switches are held pending while the scheduler is suspended. Also,
interrupts must not manipulate the xStateListItem of a TCB, or any of the interrupts must not manipulate the xGenericListItem of a TCB, or any of the
lists the xStateListItem can be referenced from, if the scheduler is suspended. lists the xGenericListItem can be referenced from, if the scheduler is suspended.
If an interrupt needs to unblock a task while the scheduler is suspended then it If an interrupt needs to unblock a task while the scheduler is suspended then it
moves the task's event list item into the xPendingReadyList, ready for the moves the task's event list item into the xPendingReadyList, ready for the
kernel to move the task from the pending ready list into the real ready list kernel to move the task from the pending ready list into the real ready list
@ -515,6 +528,15 @@ static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t *
*/ */
static void prvResetNextTaskUnblockTime( void ); static void prvResetNextTaskUnblockTime( void );
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
/*
* Helper function used to pad task names with spaces when printing out
* human readable tables of task information.
*/
static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName );
#endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
@ -995,7 +1017,7 @@ TCB_t * pxNewTCB;
} }
#endif #endif
else else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
{ {
/* If the task is not in any other state, it must be in the /* If the task is not in any other state, it must be in the
Ready (including pending ready) state. */ Ready (including pending ready) state. */
@ -1031,6 +1053,46 @@ TCB_t * pxNewTCB;
#endif /* INCLUDE_uxTaskPriorityGet */ #endif /* INCLUDE_uxTaskPriorityGet */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if ( INCLUDE_uxTaskPriorityGet == 1 )
UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask )
{
TCB_t *pxTCB;
UBaseType_t uxReturn, uxSavedInterruptState;
/* RTOS ports that support interrupt nesting have the concept of a
maximum system call (or maximum API call) interrupt priority.
Interrupts that are above the maximum system call priority are keep
permanently enabled, even when the RTOS kernel is in a critical section,
but cannot make any calls to FreeRTOS API functions. If configASSERT()
is defined in FreeRTOSConfig.h then
portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
failure if a FreeRTOS API function is called from an interrupt that has
been assigned a priority above the configured maximum system call
priority. Only FreeRTOS functions that end in FromISR can be called
from interrupts that have been assigned a priority at or (logically)
below the maximum system call interrupt priority. FreeRTOS maintains a
separate interrupt safe API to ensure interrupt entry is as fast and as
simple as possible. More information (albeit Cortex-M specific) is
provided on the following link:
http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
{
/* If null is passed in here then we are changing the
priority of the calling function. */
pxTCB = prvGetTCBFromHandle( xTask );
uxReturn = pxTCB->uxPriority;
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );
return uxReturn;
}
#endif /* INCLUDE_uxTaskPriorityGet */
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskPrioritySet == 1 ) #if ( INCLUDE_vTaskPrioritySet == 1 )
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
@ -1614,8 +1676,8 @@ BaseType_t xAlreadyYielded = pdFALSE;
( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
/* If we have moved a task that has a priority higher than /* If the moved task has a priority higher than the current
the current task then we should yield. */ task then a yield must be performed. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{ {
xYieldPending = pdTRUE; xYieldPending = pdTRUE;
@ -1884,7 +1946,7 @@ BaseType_t xSwitchRequired = pdFALSE;
/* See if this tick has made a timeout expire. Tasks are stored in /* See if this tick has made a timeout expire. Tasks are stored in
the queue in the order of their wake time - meaning once one task the queue in the order of their wake time - meaning once one task
has been found whose block time has not expired there is no need to has been found whose block time has not expired there is no need to
look any further down the list. */ look any further down the list. */
if( xConstTickCount >= xNextTaskUnblockTime ) if( xConstTickCount >= xNextTaskUnblockTime )
{ {
for( ;; ) for( ;; )
@ -2395,6 +2457,20 @@ BaseType_t xReturn;
xReturn = pdFALSE; xReturn = pdFALSE;
} }
#if( configUSE_TICKLESS_IDLE == 1 )
{
/* If a task is blocked on a kernel object then xNextTaskUnblockTime
might be set to the blocked task's time out time. If the task is
unblocked for a reason other than a timeout xNextTaskUnblockTime is
normally left unchanged, because it is automatically get reset to a new
value when the tick count equals xNextTaskUnblockTime. However if
tickless idling is used it might be more important to enter sleep mode
at the earliest possible time - so reset xNextTaskUnblockTime here to
ensure it is updated at the earliest possible time. */
prvResetNextTaskUnblockTime();
}
#endif
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -2788,6 +2864,13 @@ UBaseType_t x;
} }
#endif /* portUSING_MPU_WRAPPERS */ #endif /* portUSING_MPU_WRAPPERS */
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
{
pxTCB->ulNotifiedValue = 0;
pxTCB->eNotifyState = eNotWaitingNotification;
}
#endif
#if ( configUSE_NEWLIB_REENTRANT == 1 ) #if ( configUSE_NEWLIB_REENTRANT == 1 )
{ {
/* Initialise this task's Newlib reent structure. */ /* Initialise this task's Newlib reent structure. */
@ -3416,6 +3499,32 @@ TCB_t *pxTCB;
#endif /* portCRITICAL_NESTING_IN_TCB */ #endif /* portCRITICAL_NESTING_IN_TCB */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )
{
BaseType_t x;
/* Start by copying the entire string. */
strcpy( pcBuffer, pcTaskName );
/* Pad the end of the string with spaces to ensure columns line up when
printed out. */
for( x = strlen( pcBuffer ); x < configMAX_TASK_NAME_LEN; x++ )
{
pcBuffer[ x ] = ' ';
}
/* Terminate. */
pcBuffer[ x ] = 0x00;
/* Return the new end of string. */
return &( pcBuffer[ x ] );
}
#endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
/*-----------------------------------------------------------*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
void vTaskList( char * pcWriteBuffer ) void vTaskList( char * pcWriteBuffer )
@ -3487,7 +3596,12 @@ TCB_t *pxTCB;
break; break;
} }
sprintf( pcWriteBuffer, "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); /* Write the task name to the string, padding with spaces so it
can be printed in tabular form more easily. */
pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
/* Write the rest of the string. */
sprintf( pcWriteBuffer, "\t\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
pcWriteBuffer += strlen( pcWriteBuffer ); pcWriteBuffer += strlen( pcWriteBuffer );
} }
@ -3573,15 +3687,20 @@ TCB_t *pxTCB;
if( ulStatsAsPercentage > 0UL ) if( ulStatsAsPercentage > 0UL )
{ {
/* Write the task name to the string, padding with
spaces so it can be printed in tabular form more
easily. */
pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
#ifdef portLU_PRINTF_SPECIFIER_REQUIRED #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
{ {
sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); sprintf( pcWriteBuffer, "\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
} }
#else #else
{ {
/* sizeof( int ) == sizeof( long ) so a smaller /* sizeof( int ) == sizeof( long ) so a smaller
printf() library can be used. */ printf() library can be used. */
sprintf( pcWriteBuffer, "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); sprintf( pcWriteBuffer, "\t\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
} }
#endif #endif
} }
@ -3651,7 +3770,433 @@ TickType_t uxReturn;
} }
#endif /* configUSE_MUTEXES */ #endif /* configUSE_MUTEXES */
/*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
{
TickType_t xTimeToWake;
uint32_t ulReturn;
taskENTER_CRITICAL();
{
/* Only block if the notification count is not already non-zero. */
if( pxCurrentTCB->ulNotifiedValue == 0UL )
{
/* Mark this task as waiting for a notification. */
pxCurrentTCB->eNotifyState = eWaitingNotification;
if( xTicksToWait > 0 )
{
/* The task is going to block. First it must be removed
from the ready list. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is
no need to check, and the port reset macro can be called
directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
#if ( INCLUDE_vTaskSuspend == 1 )
{
if( xTicksToWait == portMAX_DELAY )
{
/* Add the task to the suspended task list instead
of a delayed task list to ensure the task is not
woken by a timing event. It will block
indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* Calculate the time at which the task should be
woken if no notification events occur. This may
overflow but this doesn't matter, the scheduler will
handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
}
#else /* INCLUDE_vTaskSuspend */
{
/* Calculate the time at which the task should be
woken if the event does not occur. This may
overflow but this doesn't matter, the scheduler will
handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
#endif /* INCLUDE_vTaskSuspend */
/* All ports are written to allow a yield in a critical
section (some will yield immediately, others wait until the
critical section exits) - but it is not something that
application code should ever do. */
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
taskENTER_CRITICAL();
{
ulReturn = pxCurrentTCB->ulNotifiedValue;
if( ulReturn != 0 )
{
if( xClearCountOnExit != pdFALSE )
{
pxCurrentTCB->ulNotifiedValue = 0UL;
}
else
{
( pxCurrentTCB->ulNotifiedValue )--;
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
pxCurrentTCB->eNotifyState = eNotWaitingNotification;
}
taskEXIT_CRITICAL();
return ulReturn;
}
#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 )
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, BaseType_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
{
TickType_t xTimeToWake;
BaseType_t xReturn;
taskENTER_CRITICAL();
{
/* Only block if a notification is not already pending. */
if( pxCurrentTCB->eNotifyState != eNotified )
{
/* Clear bits in the task's notification value as bits may get
set by the notifying task or interrupt. This can be used to
clear the value to zero. */
pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
/* Mark this task as waiting for a notification. */
pxCurrentTCB->eNotifyState = eWaitingNotification;
if( xTicksToWait > 0 )
{
/* The task is going to block. First it must be removed
from the ready list. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is
no need to check, and the port reset macro can be called
directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
#if ( INCLUDE_vTaskSuspend == 1 )
{
if( xTicksToWait == portMAX_DELAY )
{
/* Add the task to the suspended task list instead
of a delayed task list to ensure the task is not
woken by a timing event. It will block
indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* Calculate the time at which the task should be
woken if no notification events occur. This may
overflow but this doesn't matter, the scheduler will
handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
}
#else /* INCLUDE_vTaskSuspend */
{
/* Calculate the time at which the task should be
woken if the event does not occur. This may
overflow but this doesn't matter, the scheduler will
handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
#endif /* INCLUDE_vTaskSuspend */
/* All ports are written to allow a yield in a critical
section (some will yield immediately, others wait until the
critical section exits) - but it is not something that
application code should ever do. */
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
taskENTER_CRITICAL();
{
if( pulNotificationValue != NULL )
{
/* Output the current notification value, which may or may not
have changed. */
*pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
}
/* If eNotifyValue is set then either the task never entered the
blocked state (because a notification was already pending) or the
task unblocked because of a notification. Otherwise the task
unblocked because of a timeout. */
if( pxCurrentTCB->eNotifyState == eWaitingNotification )
{
/* A notification was not received. */
xReturn = pdFALSE;
}
else
{
/* A notification was already pending or a notification was
received while the task was waiting. */
pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
xReturn = pdTRUE;
}
pxCurrentTCB->eNotifyState = eNotWaitingNotification;
}
taskEXIT_CRITICAL();
return xReturn;
}
#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 )
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction )
{
TCB_t * pxTCB;
eNotifyValue eOriginalNotifyState;
BaseType_t xReturn = pdPASS;
configASSERT( xTaskToNotify );
pxTCB = ( TCB_t * ) xTaskToNotify;
taskENTER_CRITICAL();
{
eOriginalNotifyState = pxTCB->eNotifyState;
pxTCB->eNotifyState = eNotified;
switch( eAction )
{
case eSetBits :
pxTCB->ulNotifiedValue |= ulValue;
break;
case eIncrement :
( pxTCB->ulNotifiedValue )++;
break;
case eSetValueWithOverwrite :
pxTCB->ulNotifiedValue = ulValue;
break;
case eSetValueWithoutOverwrite :
if( eOriginalNotifyState != eNotified )
{
pxTCB->ulNotifiedValue = ulValue;
}
else
{
/* The value could not be written to the task. */
xReturn = pdFAIL;
}
break;
default :
/* The task is being notified without its notify value being
updated. */
break;
}
/* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */
if( eOriginalNotifyState == eWaitingNotification )
{
( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxTCB );
/* The task should not have been on an event list. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
{
/* The notified task has a priority above the currently
executing task so a yield is required. */
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
return xReturn;
}
#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 )
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )
{
TCB_t * pxTCB;
eNotifyValue eOriginalNotifyState;
BaseType_t xReturn = pdPASS;
UBaseType_t uxSavedInterruptStatus;
configASSERT( xTaskToNotify );
/* RTOS ports that support interrupt nesting have the concept of a
maximum system call (or maximum API call) interrupt priority.
Interrupts that are above the maximum system call priority are keep
permanently enabled, even when the RTOS kernel is in a critical section,
but cannot make any calls to FreeRTOS API functions. If configASSERT()
is defined in FreeRTOSConfig.h then
portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
failure if a FreeRTOS API function is called from an interrupt that has
been assigned a priority above the configured maximum system call
priority. Only FreeRTOS functions that end in FromISR can be called
from interrupts that have been assigned a priority at or (logically)
below the maximum system call interrupt priority. FreeRTOS maintains a
separate interrupt safe API to ensure interrupt entry is as fast and as
simple as possible. More information (albeit Cortex-M specific) is
provided on the following link:
http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
pxTCB = ( TCB_t * ) xTaskToNotify;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
eOriginalNotifyState = pxTCB->eNotifyState;
pxTCB->eNotifyState = eNotified;
switch( eAction )
{
case eSetBits :
pxTCB->ulNotifiedValue |= ulValue;
break;
case eIncrement :
( pxTCB->ulNotifiedValue )++;
break;
case eSetValueWithOverwrite :
pxTCB->ulNotifiedValue = ulValue;
break;
case eSetValueWithoutOverwrite :
if( eOriginalNotifyState != eNotified )
{
pxTCB->ulNotifiedValue = ulValue;
}
else
{
/* The value could not be written to the task. */
xReturn = pdFAIL;
}
break;
default :
/* The task is being notified without its notify value being
updated. */
break;
}
/* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */
if( eOriginalNotifyState == eWaitingNotification )
{
/* The task should not have been on an event list. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxTCB );
}
else
{
/* The delayed and ready lists cannot be accessed, so hold
this task pending until the scheduler is resumed. */
vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
}
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
{
/* The notified task has a priority above the currently
executing task so a yield is required. */
if( pxHigherPriorityTaskWoken != NULL )
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return xReturn;
}
#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#ifdef FREERTOS_MODULE_TEST #ifdef FREERTOS_MODULE_TEST