Update to latest FreeRTOS+Trace recorder code.

pull/4/head
Richard Barry 12 years ago
parent f9d0a153b4
commit f928b0e296

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

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* FreeRTOS+Trace v2.3.0 Recorder Library * Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcConfig.h * trcConfig.h
@ -9,12 +9,12 @@
* 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
* overapproximated, although larger values values implies more RAM usage. * over-approximated, although larger values values implies more RAM usage.
* *
* 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
* 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 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
@ -36,11 +36,7 @@
* 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.
* *
* FreeRTOS+Trace is available as Free Edition and in two premium editions. * Copyright Percepio AB, 2013.
* You may use the premium features during 30 days for evaluation.
* Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/
*
* Copyright Percepio AB, 2012.
* www.percepio.com * www.percepio.com
******************************************************************************/ ******************************************************************************/
@ -61,7 +57,7 @@
* vTracePrintF may use multiple records depending on the number of data args. * vTracePrintF may use multiple records depending on the number of data args.
******************************************************************************/ ******************************************************************************/
#define EVENT_BUFFER_SIZE 1000 /* Adjust wrt. to available RAM */ #define EVENT_BUFFER_SIZE 4000 /* Adjust wrt. to available RAM */
/******************************************************************************* /*******************************************************************************
@ -99,6 +95,43 @@
******************************************************************************/ ******************************************************************************/
#define SYMBOL_TABLE_SIZE 1000 #define SYMBOL_TABLE_SIZE 1000
/*******************************************************************************
* USE_SEPARATE_USER_EVENT_BUFFER
*
* Macro which should be defined as an integer value.
* Default is zero (0).
*
* This enables and disables the use of the separate user event buffer.
*
* 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
* user event history is longer than the task scheduling history.
******************************************************************************/
#define USE_SEPARATE_USER_EVENT_BUFFER 0
/*******************************************************************************
* USER_EVENT_BUFFER_SIZE
*
* Macro which should be defined as an integer value.
*
* This defines the capacity of the user event buffer, in number of slots.
* A single user event can use between 1 and X slots, depending on the data.
*
* Only in use if USE_SEPARATE_USER_EVENT_BUFFER is set to 1.
******************************************************************************/
#define USER_EVENT_BUFFER_SIZE 500
/*******************************************************************************
* USER_EVENT_CHANNELS
*
* Macro which should be defined as an integer value.
*
* This defines the number of allowed user event channels.
*
* Only in use if USE_SEPARATE_USER_EVENT_BUFFER is set to 1.
******************************************************************************/
#define CHANNEL_FORMAT_PAIRS 32
/******************************************************************************* /*******************************************************************************
* NTask, NISR, NQueue, NSemaphore, NMutex * NTask, NISR, NQueue, NSemaphore, NMutex
* *
@ -114,35 +147,33 @@
* *
* Using too small values will give an error message through the vTraceError * Using too small values will give an error message through the vTraceError
* routine, which makes the error message appear when opening the trace data * routine, which makes the error message appear when opening the trace data
* in FreeRTOS+Trace. If you are using the recorder status monitor task, * in Tracealyzer. If you are using the recorder status monitor task,
* any error messages are displayed in console prints, assuming that the * any error messages are displayed in console prints, assuming that the
* print macro has been defined properly (vConsolePrintMessage). * print macro has been defined properly (vConsolePrintMessage).
* *
* It can be wise to start with very large values for these constants, * 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 * unless you are very confident on these numbers. Then do a recording and
* check the actual usage in FreeRTOS+Trace. This is shown by selecting * check the actual usage in Tracealyzer. This is shown by selecting
* View -> Trace Details -> Resource Usage -> Object Table * View -> Trace Details -> Resource Usage -> Object Table
* *
* NOTE 2: Remember to account for all tasks created by FreeRTOS, such as the * NOTE 2: Remember to account for all tasks created by the kernel, such as the
* IDLE task, the FreeRTOS timer task, and any tasks created by other 3rd party * IDLE task, timer task, and any tasks created by other 3rd party
* software components, such as communication stacks. The recorder also has an * software components, such as communication stacks. The recorder also has an
* optional monitor task to account for, if this is used. * optional monitor task to account for, if this is used.
* Moreover, one task slot is used to indicate "(startup)", i.e., a fictive * Moreover, one task slot is used to indicate "(startup)", i.e., a fictive
* task that represent the time before the FreeRTOS scheduler starts. * task that represent the time before the scheduler starts.
* NTask should thus be at least 2-3 slots larger than your application task count. * NTask should thus be at least 2-3 slots larger than your application task count.
* *
* NOTE 3: The FreeRTOS timer task creates a Queue, that should be accounted
* for in NQueue.
******************************************************************************/ ******************************************************************************/
#define NTask 15 #define NTask 15
#define NISR 4 #define NISR 5
#define NQueue 3 #define NQueue 5
#define NSemaphore 4 #define NSemaphore 5
#define NMutex 2 #define NMutex 5
/* Maximum object name length for each class (includes zero termination) */ /* Maximum object name length for each class (includes zero termination) */
#define NameLenTask configMAX_TASK_NAME_LEN #define NameLenTask 15
#define NameLenISR 10 #define NameLenISR 15
#define NameLenQueue 15 #define NameLenQueue 15
#define NameLenSemaphore 15 #define NameLenSemaphore 15
#define NameLenMutex 15 #define NameLenMutex 15
@ -152,12 +183,12 @@
* *
* Macro which should be defined as a string. * Macro which should be defined as a string.
* *
* This string is stored in the trace and displayed in FreeRTOS+Trace. Can be * 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 * 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 * internal error messages from the recorder, which if occurs overwrites the
* value defined here. This may be maximum 256 chars. * value defined here. This may be maximum 256 chars.
*****************************************************************************/ *****************************************************************************/
#define TRACE_DESCRIPTION "FreeRTOS+Trace Demo" #define TRACE_DESCRIPTION "Tracealyzer Recorder Test Program"
/****************************************************************************** /******************************************************************************
* TRACE_DESCRIPTION_MAX_LENGTH * TRACE_DESCRIPTION_MAX_LENGTH
@ -195,6 +226,17 @@
* CONFIGURATION REGARDING WHAT CODE/FEATURES TO INCLUDE * 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 0
/****************************************************************************** /******************************************************************************
* INCLUDE_FLOAT_SUPPORT * INCLUDE_FLOAT_SUPPORT
* *
@ -223,8 +265,8 @@
* much faster than a printf and can therefore be used in timing critical code. * much faster than a printf and can therefore be used in timing critical code.
* See vTraceUserEvent() and vTracePrintF() in trcUser.h * See vTraceUserEvent() and vTracePrintF() in trcUser.h
* *
* Note that FreeRTOS+Trace Standard Edition or Professional Edition is required * Note that Tracealyzer Standard Edition or Professional Edition is required
* for User Events, they are not displayed in FreeRTOS+Trace Free Edition. * for User Events, they are not displayed in Tracealyzer Free Edition.
*****************************************************************************/ *****************************************************************************/
#define INCLUDE_USER_EVENTS 1 #define INCLUDE_USER_EVENTS 1
@ -240,6 +282,17 @@
*****************************************************************************/ *****************************************************************************/
#define INCLUDE_READY_EVENTS 1 #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 * INCLUDE_ISR_TRACING
* *
@ -247,10 +300,11 @@
* Default is 1. * Default is 1.
* *
* If this is zero (0), the code for recording Interrupt Service Routines is * If this is zero (0), the code for recording Interrupt Service Routines is
* excluded to reduce code size. Note, recording ISRs require that you insert * excluded to reduce code size.
* calls to vTraceStoreISRBegin and vTraceStoreISREnd in your interrupt handlers. *
* There is no automatic recording of ISRs like for task scheduling, since * Note, if the kernel has no central interrupt dispatcher, recording ISRs
* FreeRTOS does not have a central interrupt dispatcher. * require that you insert calls to vTraceStoreISRBegin and vTraceStoreISREnd
* in your interrupt handlers.
*****************************************************************************/ *****************************************************************************/
#define INCLUDE_ISR_TRACING 1 #define INCLUDE_ISR_TRACING 1
@ -261,9 +315,8 @@
* Default is 1. * Default is 1.
* *
* This must be enabled (1) if tasks, queues or other * This must be enabled (1) if tasks, queues or other
* traced kernel objects are deleted at runtime, e.g., using vTaskDelete or * traced kernel objects are deleted at runtime. If no deletes are made, this
* vQueueDelete. If no deletes are made, this can be set to 0 in order to * can be set to 0 in order to exclude the delete-handling code.
* exclude the delete-handling code.
*****************************************************************************/ *****************************************************************************/
#define INCLUDE_OBJECT_DELETE 1 #define INCLUDE_OBJECT_DELETE 1
@ -272,32 +325,32 @@
*****************************************************************************/ *****************************************************************************/
/****************************************************************************** /******************************************************************************
* RECORDER_STORE_MODE * TRACE_RECORDER_STORE_MODE
* *
* Macro which should be defined as one of: * Macro which should be defined as one of:
* - STORE_MODE_RING_BUFFER * - TRACE_STORE_MODE_RING_BUFFER
* - STORE_MODE_STOP_WHEN_FULL * - TRACE_STORE_MODE_STOP_WHEN_FULL
* Default is STORE_MODE_RING_BUFFER. * Default is TRACE_STORE_MODE_RING_BUFFER.
* *
* With RECORDER_STORE_MODE set to STORE_MODE_RING_BUFFER, the events are stored * With TRACE_RECORDER_STORE_MODE set to TRACE_STORE_MODE_RING_BUFFER, the events are
* in a ring buffer, i.e., where the oldest events are overwritten when the * stored in a ring buffer, i.e., where the oldest events are overwritten when
* buffer becomes full. This allows you to get the last events leading up to an * the buffer becomes full. This allows you to get the last events leading up
* interesting state, e.g., an error, without having a large trace buffer for * to an interesting state, e.g., an error, without having a large trace buffer
* string the whole run since startup. In this mode, the recorder can run * 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 * "forever" as the buffer never gets full, i.e., in the sense that it always
* has room for more events. * has room for more events.
* *
* To fetch the trace in mode STORE_MODE_RING_BUFFER, you need to first halt the * 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 * 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 * recorder using vTraceStop() and then store/upload the trace data using a
* FreeRTOS task that you need to provide yourself. The trace data is found in * task that you need to provide yourself. The trace data is found in the struct
* the struct RecorderData, initialized in trcBase.c. * RecorderData, initialized in trcBase.c.
* *
* Note that, if you upload the trace using a RAM dump, i.e., when the system is * 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 * halted on a breakpoint or by a debugger command, there is no need to stop the
* recorder first. * recorder first.
* *
* When RECORDER_STORE_MODE is STORE_MODE_STOP_WHEN_FULL, the recording is * 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 * stopped when the buffer becomes full. When the recorder stops itself this way
* vTracePortEnd() is called which allows for custom actions, such as triggering * 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 * a task that stores the trace buffer, i.e., in case taking a RAM dump
@ -305,12 +358,8 @@
* saves the trace to file directly, but this is not recommended in a real-time * 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. * system since the scheduler is blocked during the processing of vTracePortEnd.
*****************************************************************************/ *****************************************************************************/
#ifndef WIN32
#define RECORDER_STORE_MODE STORE_MODE_RING_BUFFER #define TRACE_RECORDER_STORE_MODE TRACE_STORE_MODE_RING_BUFFER
#else
/* Default in the Win32 demo */
#define RECORDER_STORE_MODE STORE_MODE_STOP_WHEN_FULL
#endif
/****************************************************************************** /******************************************************************************
* STOP_AFTER_N_EVENTS * STOP_AFTER_N_EVENTS
@ -337,27 +386,21 @@
* *
* For tasks with "infinite" main loops (non-terminating tasks), the concept * For tasks with "infinite" main loops (non-terminating tasks), the concept
* of a task instance has no clear definition, it is an application-specific * of a task instance has no clear definition, it is an application-specific
* thing. FreeRTOS+Trace allows you to define Instance Finish Events (IFEs), * thing. Tracealyzer allows you to define Instance Finish Events (IFEs),
* which marks the point in a cyclic task when the "task instance" ends. * 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 * 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 * which typically reads a message queue, waits for a semaphore or performs
* an explicit delay. * an explicit delay.
* *
* If USE_IMPLICIT_IFE_RULES is one (1), the following FreeRTOS kernel calls * If USE_IMPLICIT_IFE_RULES is one (1), the kernel macros (trcKernelPort.h)
* are considered by default to be IFEs (Implicit IFEs): * will define what kernel calls are considered by default to be IFEs.
* - vTaskDelay
* - vTaskDelayUntil
* - vTaskSuspend
* - xQueueReceive (blocking cases only)
* - xSemaphoreTake (blocking cases only)
* *
* However, Implicit IFEs only applies to blocking kernel calls. If an * However, Implicit IFEs only applies to blocking kernel calls. If a
* xQueueReceive reads a message without blocking, it does not create a new * service reads a message without blocking, it does not create a new
* instance since no blocking occurred. * instance since no blocking occurred.
* *
* Moreover, the actual IFE might sometimes be another blocking call such as * Moreover, the actual IFE might sometimes be another blocking call. We
* xQueueSend or xSemaphoreGive. We therefore allow for user-defined * therefore allow for user-defined Explicit IFEs by calling
* Explicit IFEs by calling
* *
* vTraceTaskInstanceIsFinished() * vTraceTaskInstanceIsFinished()
* *
@ -365,8 +408,8 @@
* additional event but instead stores the service code and object handle * additional event but instead stores the service code and object handle
* of the IFE call as properties of the task. * of the IFE call as properties of the task.
* *
* If using Explicit IFEs and the task also calls an Implicit IFE like * If using Explicit IFEs and the task also calls an Implicit IFE, this may
* vTaskDelay, this may result in additional incorrect task instances. * result in additional incorrect task instances.
* This is solved by disabling the Implicit IFEs for the task, by adding * This is solved by disabling the Implicit IFEs for the task, by adding
* a call to * a call to
* *
@ -440,9 +483,9 @@
* be mapped to your console "printf" routine. The task is named TraceMon but * be mapped to your console "printf" routine. The task is named TraceMon but
* is intentionally excluded from the demo trace. * is intentionally excluded from the demo trace.
* *
* Default is 1000 FreeRTOS ticks (typically 1 second). On the Windows port, a * Default is 1000 ticks (typically 1 second). On the Windows port, a lower
* lower value is suggested since the Windows port runs very slowly, often 20-40 * value is suggested since the Windows port runs very slowly, often 20-40
* times slower than the simulated FreeRTOS time. * times slower than the simulated time.
* *
* See vTraceMonitorTask in trcUser.c * See vTraceMonitorTask in trcUser.c
*****************************************************************************/ *****************************************************************************/

@ -1,11 +1,11 @@
/******************************************************************************* /*******************************************************************************
* FreeRTOS+Trace v2.3.0 Recorder Library * Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcPort.h * trcHardwarePort.h
* *
* Contains together with trcPort.c all portability issues of the trace recorder * Contains together with trcHardwarePort.c all hardware portability issues of
* library. * the trace recorder library.
* *
* 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
@ -32,18 +32,16 @@
* 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.
* *
* FreeRTOS+Trace is available as Free Edition and in two premium editions. * Copyright Percepio AB, 2013.
* You may use the premium features during 30 days for evaluation.
* Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/
*
* Copyright Percepio AB, 2012.
* www.percepio.com * www.percepio.com
******************************************************************************/ ******************************************************************************/
#ifndef TRCPORT_H #ifndef TRCPORT_H
#define TRCPORT_H #define TRCPORT_H
/* If FreeRTOS Win32 port */ #include "trcKernelPort.h"
/* If Win32 port */
#ifdef WIN32 #ifdef WIN32
#undef _WIN32_WINNT #undef _WIN32_WINNT
@ -74,16 +72,13 @@
* 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. Note that this gives suboptimal display in FreeRTOS+Trace. All * platforms. All time durations will be truncated to the OS tick frequency,
* time durations will be truncated to the OS tick frequency, typically 1 KHz. * typically 1 KHz. This means that a task or ISR that executes in less than
* This means that a task or ISR that executes in less than 1 ms get an exection * 1 ms get an execution time of zero.
* time of zero. They are however still visible in FreeRTOS+Trace.
* *
* PORT_Win32 * PORT_Win32
* "Accurate" timestamping based on the Windows permance counter. Note that * "Accurate" timestamping based on the Windows performance counter. Note that
* this gives the host machine time, not the simulated FreeRTOS time (tick * this gives the host machine time.
* count). The timing of the Win32 FreeRTOS build is not real-time, since it
* depends on the scheduling and tick rate of Windows, which is very slow.
* *
* Officially supported hardware timer ports: * Officially supported hardware timer ports:
* - PORT_Atmel_AT91SAM7 * - PORT_Atmel_AT91SAM7
@ -96,7 +91,7 @@
* been developed by external contributors, and have not yet been verified * been developed by external contributors, and have not yet been verified
* by Percepio AB. Let us know if you have problems getting these to work. * by Percepio AB. Let us know if you have problems getting these to work.
* *
* Unoffical hardware specific ports provided are: * Unofficial hardware specific ports provided are:
* - PORT_TEXAS_INSTRUMENTS_TMS570 * - PORT_TEXAS_INSTRUMENTS_TMS570
* - PORT_TEXAS_INSTRUMENTS_MSP430 * - PORT_TEXAS_INSTRUMENTS_MSP430
* - PORT_MICROCHIP_PIC32 * - PORT_MICROCHIP_PIC32
@ -140,29 +135,29 @@
* *
* 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.
* *
* We provide this setting for some hardware architectures below: * We provide this setting for some hardware architectures below:
* - ARM Cortex M: 0 (lower irq priority values are more significant) * - ARM Cortex M: 0 (lower IRQ priority values are more significant)
* - Atmel AT91SAM7x: 1 (higher irq priority values are more significant) * - Atmel AT91SAM7x: 1 (higher IRQ priority values are more significant)
* - Atmel AVR32: 1 (higher irq priority values are more significant) * - Atmel AVR32: 1 (higher IRQ priority values are more significant)
* - Renesas RX600: 1 (higher irq priority values are more significant) * - Renesas RX600: 1 (higher IRQ priority values are more significant)
* - Microchip PIC24: 0 (lower irq priority values are more significant) * - Microchip PIC24: 0 (lower IRQ priority values are more significant)
* - Microchip dsPIC: 0 (lower irq priority values are more significant) * - Microchip dsPIC: 0 (lower IRQ priority values are more significant)
* - TI TMS570: 0 (lower irq priority values are more significant) * - TI TMS570: 0 (lower IRQ priority values are more significant)
* - Freescale HCS08: 0 (lower irq priority values are more significant) * - Freescale HCS08: 0 (lower IRQ priority values are more significant)
* - Freescale HCS12: 0 (lower irq priority values are more significant) * - Freescale HCS12: 0 (lower IRQ priority values are more significant)
* - PowerPC 405: 0 (lower irq priority values are more significant) * - PowerPC 405: 0 (lower IRQ priority values are more significant)
* - PowerPC 440: 0 (lower irq priority values are more significant) * - PowerPC 440: 0 (lower IRQ priority values are more significant)
* - Freescale ColdFire: 1 (higher irq priority values are more significant) * - Freescale ColdFire: 1 (higher IRQ priority values are more significant)
* - NXP LPC210x: 0 (lower irq priority values are more significant) * - NXP LPC210x: 0 (lower IRQ priority values are more significant)
* - MicroBlaze: 0 (lower irq priority values are more significant) * - MicroBlaze: 0 (lower IRQ priority values are more significant)
* *
* If your chip is not on the above list, and you perhaps know this detail by * If your chip is not on the above list, and you perhaps know this detail by
* heart, please inform us by e-mail to support@percepio.com. * heart, please inform us by e-mail to support@percepio.com.
@ -206,17 +201,9 @@
* 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 uiTracePortGetTimeStamp 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
* the code of uiTracePortGetTimeStamp if using the HWTC macros. * the code of vTracePortGetTimeStamp if using the HWTC macros.
*
* FREE LICENSE OFFER FROM PERCEPIO
*
* For silicon companies and non-corporate FreeRTOS users (researchers, students,
* hobbyists or early-phase startups) we have the following offer:
* Provide a hardware port for our FreeRTOS recorder and get a FREE single-user
* license for FreeRTOS+Trace Professional Edition. Read more about this offer
* at www.percepio.com or contact us directly at support@percepio.com.
* *
******************************************************************************/ ******************************************************************************/
@ -248,7 +235,7 @@
#define HWTC_PERIOD 2995 #define HWTC_PERIOD 2995
#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)
@ -256,10 +243,10 @@
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT sysreg_read(AVR32_COUNT) #define HWTC_COUNT sysreg_read(AVR32_COUNT)
#define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) #define HWTC_PERIOD ( TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ )
#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_ARM_CortexM) #elif (SELECTED_PORT == PORT_ARM_CortexM)
@ -270,7 +257,7 @@
#define HWTC_PERIOD ((*(uint32_t*)0xE000E014) + 1) #define HWTC_PERIOD ((*(uint32_t*)0xE000E014) + 1)
#define HWTC_DIVISOR 2 #define HWTC_DIVISOR 2
#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_Renesas_RX600) #elif (SELECTED_PORT == PORT_Renesas_RX600)
@ -278,19 +265,19 @@
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
#define HWTC_COUNT (CMT0.CMCNT) #define HWTC_COUNT (CMT0.CMCNT)
#define HWTC_PERIOD ((((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/8)) #define HWTC_PERIOD ((((TRACE_PERIPHERAL_CLOCK_HZ/TRACE_TICK_RATE_HZ)-1)/8))
#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_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 was originally designed for 32-bit MCUs, and is slower /* Note: The trace library was originally designed for 32-bit MCUs, and is slower
than intended on 16-bit MCUs. Storing an event on a PIC24 takes about 70 µs. than intended on 16-bit MCUs. Storing an event on a PIC24 takes about 70 µs.
In comparison, 32-bit MCUs are often 10-20 times faster. If recording overhead In comparison, 32-bit MCUs are often 10-20 times faster. If recording overhead
becomes a problem on PIC24, use the filters to exclude less interresting tasks becomes a problem on PIC24, use the filters to exclude less interesting tasks
or system calls. */ or system calls. */
#define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_INCREMENTING
@ -298,21 +285,19 @@
#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_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. */
Assumption: prescaler is 1:1 (this setting is hardcoded in
FreeRTOS port for LPC21XX) */
#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 ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) #define HWTC_PERIOD ( TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ )
#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 */ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
@ -325,17 +310,17 @@
#define HWTC_PERIOD (RTIUDCP0) #define HWTC_PERIOD (RTIUDCP0)
#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_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 configCPU_CLOCKS_PER_TICK #define HWTC_PERIOD TRACE_CPU_CLOCKS_PER_TICK
#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) #elif (SELECTED_PORT == PORT_MICROCHIP_PIC32)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
@ -345,17 +330,17 @@
#define HWTC_PERIOD (ReadPeriod1()+1) /* Should be available in BSP */ #define HWTC_PERIOD (ReadPeriod1()+1) /* Should be available in BSP */
#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_PPC405) #elif (SELECTED_PORT == PORT_XILINX_PPC405)
/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT mfspr( 0x3db) #define HWTC_COUNT mfspr( 0x3db)
#define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) #define HWTC_PERIOD ( TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ )
#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 */
@ -364,16 +349,15 @@
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT mfspr( 0x016 ) #define HWTC_COUNT mfspr( 0x016 )
#define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) #define HWTC_PERIOD ( TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ )
#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.
* This port is based on the official FreeRTOS Microlaze port and example application.
* 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.
*/ */
@ -381,10 +365,10 @@
#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING #define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
#define HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 ) #define HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 )
#define HWTC_PERIOD ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) #define HWTC_PERIOD ( TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ )
#define HWTC_DIVISOR 16 #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_NOT_SET) #elif (SELECTED_PORT != PORT_NOT_SET)
@ -437,23 +421,17 @@
#define vTraceConsoleMessage(x) #define vTraceConsoleMessage(x)
/******************************************************************************* /*******************************************************************************
* uiTracePortGetTimeStamp * vTracePortGetTimeStamp
* *
* Returns the current time based on the HWTC macros which provide a hardware * Returns the current time based on the HWTC macros which provide a hardware
* isolation layer towards the hardware timer/counter. * isolation layer towards the hardware timer/counter.
* *
* The HWTC macros and uiTracePortGetTimeStamp 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
* the code of uiTracePortGetTimeStamp if using the HWTC macros. * the code of vTracePortGetTimeStamp if using the HWTC macros.
* *
* OFFER FROM PERCEPIO:
* For silicon companies and non-corporate FreeRTOS users (researchers,
* students, hobbyists or early-phase startups) we have an attractive offer:
* Provide a hardware timer port and get a FREE single-user licence for
* FreeRTOS+Trace Professional Edition. Read more about this offer at
* www.percepio.com or contact us directly at support@percepio.com.
******************************************************************************/ ******************************************************************************/
void uiTracePortGetTimeStamp(uint32_t *puiTimestamp); void vTracePortGetTimeStamp(uint32_t *puiTimestamp);
/******************************************************************************* /*******************************************************************************
* vTracePortEnd * vTracePortEnd
@ -485,6 +463,12 @@ void vTracePortSetOutFile(char* path);
******************************************************************************/ ******************************************************************************/
void vTracePortSave(void); void vTracePortSave(void);
#else
#define vTraceConsoleMessage(x)
#define vTracePortSetOutFile(path)
#define vTracePortSave(void)
#endif #endif
#endif #endif

@ -1,15 +1,15 @@
/******************************************************************************* /*******************************************************************************
* FreeRTOS+Trace v2.3.0 Recorder Library * Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcBase.h * trcBase.h
* *
* Core functionallity of the FreeRTOS+Trace recorder library. * Core functionality of the Tracealyzer recorder library.
* *
* 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
* 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 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
@ -31,37 +31,88 @@
* 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.
* *
* FreeRTOS+Trace is available as Free Edition and in two premium editions. * Copyright Percepio AB, 2013.
* You may use the premium features during 30 days for evaluation.
* Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/
*
* Copyright Percepio AB, 2012.
* www.percepio.com * www.percepio.com
******************************************************************************/ ******************************************************************************/
#ifndef TRCBASE_H #ifndef TRCBASE_H
#define TRCBASE_H #define TRCBASE_H
#define TRACE_MINOR_VERSION 2
#define TRACE_STORE_MODE_STOP_WHEN_FULL 1
#define TRACE_STORE_MODE_RING_BUFFER 2
#define TRACE_DATA_ALLOCATION_STATIC 1
#define TRACE_DATA_ALLOCATION_DYNAMIC 2
#define TRACE_DATA_ALLOCATION_CUSTOM 3
#include "trcKernelPort.h"
#if (USE_TRACEALYZER_RECORDER == 1)
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "FreeRTOS.h" #ifndef USE_SEPARATE_USER_EVENT_BUFFER
#include "trcConfig.h" #define USE_SEPARATE_USER_EVENT_BUFFER 0
#include "trcTypes.h" #endif
#include "trcPort.h"
/* Max number of event codes supported */
#define NEventCodes 0x100
extern volatile int recorder_busy; extern volatile int recorder_busy; // This is used to keep track of the recorder's critical sections, to determine if it is busy
// Our local critical sections for the recorder - updates an internal busy flag
#define trcCRITICAL_SECTION_BEGIN() {TRACE_ENTER_CRITICAL_SECTION(); recorder_busy++;}
#define trcCRITICAL_SECTION_END() {recorder_busy--; TRACE_EXIT_CRITICAL_SECTION();}
#define trcCRITICAL_SECTION_BEGIN() {taskENTER_CRITICAL(); recorder_busy++;} /* Structure to handle the exclude flags for all objects and tasks. We add some extra objects since index 0 is not used for each object class. */
#define trcCRITICAL_SECTION_END() {recorder_busy--; taskEXIT_CRITICAL();} extern uint8_t excludedObjects[(TRACE_KERNEL_OBJECT_COUNT + TRACE_NCLASSES) / 8 + 1];
#define NCLASSES 5 /* Structure to handle the exclude flags for all event codes */
#define VERSION 0x1AA1 extern uint8_t excludedEventCodes[NEventCodes / 8 + 1];
#define MINOR_VERSION 1
#define STORE_MODE_STOP_WHEN_FULL 1 /******************************************************************************
#define STORE_MODE_RING_BUFFER 2 * ObjectHandleStack
#define TRACE_DATA_ALLOCATION_STATIC 1 * This data-structure is used to provide a mechanism for 1-byte trace object
#define TRACE_DATA_ALLOCATION_DYNAMIC 2 * handles. This way, only 1 byte is necessary instead of 4 bytes (a pointer)
* when storing a reference to an object. This allows for up to 255 objects of
* each object class active at any given moment. There can be more "historic"
* objects, that have been deleted - that number is only limited by the size of
* the symbol table.
* Note that handle zero (0) is not used, it is a code for an invalid handle.
*
* This data structure keeps track of the FREE handles, not the handles in use.
* This data structure contains one stack per object class. When a handle is
* allocated to an object, the next free handle is popped from the stack. When
* a handle is released (on object delete), it is pushed back on the stack.
* Note that there is no initialization code that pushed the free handles
* initially, that is not necessary due to the following optimization:
*
* The stack of handles (objectHandles) is initially all zeros. Since zero
* is not a valid handle, that is a signal of additional handles needed.
* If a zero is received when popping a new handle, it is replaced by the
* index of the popped handle instead.
*
*****************************************************************************/
typedef struct
{
/* For each object class, the index of the next handle to allocate */
int16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ];
/* The lowest index of this class (constant) */
int16_t lowestIndexOfClass[ TRACE_NCLASSES ];
/* The highest index of this class (constant) */
int16_t highestIndexOfClass[ TRACE_NCLASSES ];
/* The highest use count for this class (for statistics) */
int16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ];
/* The free object handles - a set of stacks within this array */
objectHandleType objectHandles[ TRACE_KERNEL_OBJECT_COUNT ];
} objectHandleStackType;
extern objectHandleStackType objectHandleStacks;
/****************************************************************************** /******************************************************************************
* Object Property Table * Object Property Table
@ -69,45 +120,16 @@ extern volatile int recorder_busy;
* queues, mutexes, etc). The below data structures defines the properties of * queues, mutexes, etc). The below data structures defines the properties of
* each object class and are used to cast the byte buffer into a cleaner format. * each object class and are used to cast the byte buffer into a cleaner format.
* *
* The values in the object table are continously overwritten and always * The values in the object table are continuously overwritten and always
* represent the current state. If a property is changed during runtime, the OLD * represent the current state. If a property is changed during runtime, the OLD
* value should be stored in the trace buffer, not the new value (since the new * value should be stored in the trace buffer, not the new value (since the new
* value is found in the Object Property Table). * value is found in the Object Property Table).
* For close events this mechanism is the old names are stored in the symbol * For close events this mechanism is the old names are stored in the symbol
* table), for "priority set" (the old priority is stored in the event data) * table), for "priority set" (the old priority is stored in the event data)
* and for "isActive", where the value decides is the taskswitch event type * and for "isActive", where the value decides if the task switch event type
* should be "new" or "resume". * should be "new" or "resume".
******************************************************************************/ ******************************************************************************/
/* The size of the Object Property Table entries, in bytes, per object */
/* Queue properties (except name): current number of message in queue */
#define PropertyTableSizeQueue (NameLenQueue + 1)
/* Semaphore properties (except name): state (signaled = 1, cleared = 0) */
#define PropertyTableSizeSemaphore (NameLenSemaphore + 1)
/* Mutex properties (except name): owner (task handle, 0 = free) */
#define PropertyTableSizeMutex (NameLenMutex + 1)
/* Task properties (except name): Byte 0: Current priority
Byte 1: state (if already active)
Byte 2: InstanceFinishEvent_ServiceCode
Byte 3: InstanceFinishEvent_ObjHandle */
#define PropertyTableSizeTask (NameLenTask + 4)
/* ISR properties: Byte 0: priority
Byte 1: state (if already active) */
#define PropertyTableSizeISR (NameLenISR + 2)
/* The layout of the byte array representing the Object Property Table */
#define StartIndexQueue 0
#define StartIndexSemaphore StartIndexQueue + NQueue * PropertyTableSizeQueue
#define StartIndexMutex StartIndexSemaphore + NSemaphore * PropertyTableSizeSemaphore
#define StartIndexTask StartIndexMutex + NMutex * PropertyTableSizeMutex
#define StartIndexISR StartIndexTask + NTask * PropertyTableSizeTask
#define DynObjTableSize StartIndexISR + NISR * PropertyTableSizeISR
typedef struct typedef struct
{ {
/* = NCLASSES */ /* = NCLASSES */
@ -117,18 +139,18 @@ typedef struct
/* 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)*/
uint8_t NumberOfObjectsPerClass[ 4*((NCLASSES+3)/4)]; uint8_t NumberOfObjectsPerClass[ 4*((TRACE_NCLASSES+3)/4)];
/* Allocation size rounded up to the closest multiple of 4 */ /* Allocation size rounded up to the closest multiple of 4 */
uint8_t NameLengthPerClass[ 4*((NCLASSES+3)/4) ]; uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/4) ];
uint8_t TotalPropertyBytesPerClass[ 4*((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*((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*((DynObjTableSize+3)/4) ]; uint8_t objbytes[ 4*((TRACE_OBJECT_TABLE_SIZE+3)/4) ];
} ObjectPropertyTableType; } ObjectPropertyTableType;
/* Symbol table data structure */ /* Symbol table data structure */
@ -217,9 +239,45 @@ typedef struct
uint16_t xts_16; uint16_t xts_16;
} XTSEvent; } XTSEvent;
typedef struct
{
uint8_t type;
uint8_t xps_8;
uint16_t xps_16;
} XPSEvent;
/*******************************************************************************
* The separate user event buffer structure. Can be enabled in trcConfig.h.
******************************************************************************/
#if (USE_SEPARATE_USER_EVENT_BUFFER == 1)
typedef struct
{
traceLabel name;
traceLabel defaultFormat;
} ChannelFormatPair;
typedef struct
{
uint16_t bufferID;
uint16_t version;
uint32_t wraparoundCounter;
uint32_t numberOfSlots;
uint32_t nextSlotToWrite;
uint8_t numberOfChannels;
uint8_t padding1;
uint8_t padding2;
uint8_t padding3;
ChannelFormatPair channels[CHANNEL_FORMAT_PAIRS+1];
uint8_t channelBuffer[(USER_EVENT_BUFFER_SIZE + 3) & 0xFFFFFFFC]; /* 1 byte per slot, with padding for 4 byte alignment */
uint8_t dataBuffer[USER_EVENT_BUFFER_SIZE * 4]; /* 4 bytes per slot */
} UserEventBuffer;
#endif
/******************************************************************************* /*******************************************************************************
* The main datastructure, read by FreeRTOS+Trace from the RAM dump * The main data structure, read by Tracealyzer from the RAM dump
******************************************************************************/ ******************************************************************************/
typedef struct typedef struct
@ -237,15 +295,15 @@ typedef struct
uint8_t startmarker10; uint8_t startmarker10;
uint8_t startmarker11; uint8_t startmarker11;
/* For FreeRTOS: 0x1AA1 */ /* Used to determine Kernel and Endianess */
uint16_t version; uint16_t version;
/* Currently 1 for v2.2.2 (0 earlier)*/ /* Currently 1 for v2.2.2 (0 earlier)*/
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 */
@ -296,14 +354,14 @@ typedef struct
longer are available. */ longer are available. */
symbolTableType SymbolTable; symbolTableType SymbolTable;
/* For includsion 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 occured 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. */
@ -323,6 +381,13 @@ typedef struct
/* 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)
UserEventBuffer userEventBuffer;
#endif
/* This should always be 0 */
uint32_t endOfSecondaryBlocks;
uint8_t endmarker0; uint8_t endmarker0;
uint8_t endmarker1; uint8_t endmarker1;
uint8_t endmarker2; uint8_t endmarker2;
@ -335,62 +400,10 @@ typedef struct
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;
/******************************************************************************
* ObjectHandleStack
* This data-structure is used to provide a mechanism for 1-byte trace object
* handles. This way, only 1 byte is necessary instead of 4 bytes (a pointer)
* when storing a reference to an object. This allows for up to 255 objects of
* each object class - Task, ISR, Semaphore, CountingSemaphore, Mutex and Queue,
* active at any given moment. There can be more "historic" objects, that have
* been deleted - that number is only limited by the size of the symbol table.
* Note that handle zero (0) is not used, it is a code for an invalid handle.
*
* This data structure keeps track of the FREE handles, not the handles in use.
* This datastructure contains one stack per object class. When a handle is
* allocated to an object, the next free handle is popped from the stack. When
* a handle is released (on object delete), it is pushed back on the stack.
* Note that there is no initialization code that pushed the free handles
* initially, that is not necessary due to the following optimization:
*
* The stack of handles (objectHandles) is initially all zeros. Since zero
* is not a valid handle, that is a signal of additional handles needed.
* If a zero is received when popping a new handle, it is replaced by the
* index of the popped handle instead.
*
*****************************************************************************/
typedef struct
{
/* For each object class, the index of the next handle to allocate */
int16_t indexOfNextAvailableHandle[ NCLASSES ];
/* The lowest index of this class (constant) */
int16_t lowestIndexOfClass[ NCLASSES ];
/* The highest index of this class (constant) */
int16_t highestIndexOfClass[ NCLASSES ];
/* The highest use count for this class (for statistics) */
int16_t handleCountWaterMarksOfClass[ NCLASSES ];
/* The free object handles - a set of stacks within this array */
objectHandleType objectHandles[ NTask+NISR+NSemaphore+NMutex+NQueue ];
} objectHandleStackType;
/* Internal data */
extern objectHandleStackType objectHandleStacks;
/* Structures to handle the exclude flags for all objects, tasks and event codes */
#define NEventCodes 0x100
extern uint8_t excludedFlags[(NEventCodes+NQueue+NSemaphore+NMutex+NTask) / 8 + 1];
extern uint8_t ifeFlags[NTask / 8 + 1];
/* Internal functions */ /* Internal functions */
uint16_t prvTraceGetDTS(uint16_t param_maxDTS); uint16_t prvTraceGetDTS(uint16_t param_maxDTS);
@ -411,7 +424,7 @@ traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel);
void prvTraceUpdateCounters(void); void prvTraceUpdateCounters(void);
void prvCheckDataToBeOverwrittenForMultiEntryUserEvents(uint8_t nEntries); void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nEntries);
objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass); objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass);
@ -445,80 +458,48 @@ void vTraceError(const char* msg);
char* xTraceGetLastError(void); char* xTraceGetLastError(void);
/******************************************************************************* /*******************************************************************************
* xTraceInitTraceData * prvTraceInitTraceData
* *
* Allocates and initializes the recorder datastructure, based on the constants * Allocates and initializes the recorder data structure, based on the constants
* in trcConfig.h. This allows for allocating the data on the heap, instead of * in trcConfig.h. This allows for allocating the data on the heap, instead of
* using a static declaration. * using a static declaration.
******************************************************************************/ ******************************************************************************/
RecorderDataType* xTraceInitTraceData(void); void prvTraceInitTraceData(void);
/* Internal macros */ /* Internal macros */
#define PROPERTY_NAME_GET(objectclass, objecthandle) \ #define TRACE_PROPERTY_NAME_GET(objectclass, objecthandle) \
(const char*)(& RecorderDataPtr->ObjectPropertyTable.objbytes \ (const char*)(& RecorderDataPtr->ObjectPropertyTable.objbytes \
[uiIndexOfObject(objecthandle, objectclass)]) [uiIndexOfObject(objecthandle, objectclass)])
#define PROPERTY_OBJECT_STATE(objectclass, handle) \ #define TRACE_PROPERTY_OBJECT_STATE(objectclass, handle) \
RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \ RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass]] + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass]]
#define PROPERTY_ACTOR_PRIORITY(objectclass, handle) \ #define TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle) \
RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \ RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass] + 1] + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass] + 1]
#define PROPERTY_TASK_IFE_SERVICECODE(handle) \ #define TRACE_SET_FLAG_ISEXCLUDED(flags, bitIndex) flags[(bitIndex) >> 3] |= (1 << ((bitIndex) & 7))
RecorderDataPtr->ObjectPropertyTable.objbytes \ #define TRACE_CLEAR_FLAG_ISEXCLUDED(flags, bitIndex) flags[(bitIndex) >> 3] &= ~(1 << ((bitIndex) & 7))
[uiIndexOfObject(handle, TRACE_CLASS_TASK) \ #define TRACE_GET_FLAG_ISEXCLUDED(flags, bitIndex) (flags[(bitIndex) >> 3] & (1 << ((bitIndex) & 7)))
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[TRACE_CLASS_TASK]+2]
#define TRACE_SET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_SET_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)
#define PROPERTY_TASK_IFE_OBJHANDLE(handle) \ #define TRACE_CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_CLEAR_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)
RecorderDataPtr->ObjectPropertyTable.objbytes \ #define TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) TRACE_GET_FLAG_ISEXCLUDED(excludedEventCodes, eventCode)
[uiIndexOfObject(handle, TRACE_CLASS_TASK) \
+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[TRACE_CLASS_TASK]+3] /* DEBUG ASSERTS */
#if defined USE_TRACE_ASSERT && USE_TRACE_ASSERT != 0
#define SET_FLAG_ISEXCLUDED(bitIndex) excludedFlags[(bitIndex) >> 3] |= (1 << ((bitIndex) & 7)) #define TRACE_ASSERT(eval, msg, defRetVal) \
#define CLEAR_FLAG_ISEXCLUDED(bitIndex) excludedFlags[(bitIndex) >> 3] &= ~(1 << ((bitIndex) & 7)) if (!(eval)) \
#define GET_FLAG_ISEXCLUDED(bitIndex) (excludedFlags[(bitIndex) >> 3] & (1 << ((bitIndex) & 7))) { \
vTraceError("TRACE_ASSERT: " msg); \
#define SET_FLAG_MARKIFE(bitIndex) ifeFlags[(bitIndex) >> 3] |= (1 << ((bitIndex) & 7)) return defRetVal; \
#define CLEAR_FLAG_MARKIFE(bitIndex) ifeFlags[(bitIndex) >> 3] &= ~(1 << ((bitIndex) & 7)) }
#define GET_FLAG_MARKIFE(bitIndex) (ifeFlags[(bitIndex) >> 3] & (1 << ((bitIndex) & 7))) #else
#define TRACE_ASSERT(eval, msg, defRetVal)
#define SET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) SET_FLAG_ISEXCLUDED(eventCode) #endif
#define CLEAR_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) CLEAR_FLAG_ISEXCLUDED(eventCode)
#define GET_EVENT_CODE_FLAG_ISEXCLUDED(eventCode) GET_FLAG_ISEXCLUDED(eventCode)
#define SET_QUEUE_FLAG_ISEXCLUDED(queueHandle) SET_FLAG_ISEXCLUDED(NEventCodes+queueHandle-1)
#define CLEAR_QUEUE_FLAG_ISEXCLUDED(queueHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+queueHandle-1)
#define GET_QUEUE_FLAG_ISEXCLUDED(queueHandle) GET_FLAG_ISEXCLUDED(NEventCodes+queueHandle-1)
#define SET_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreHandle) SET_FLAG_ISEXCLUDED(NEventCodes+NQueue+semaphoreHandle-1)
#define CLEAR_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+NQueue+semaphoreHandle-1)
#define GET_SEMAPHORE_FLAG_ISEXCLUDED(semaphoreHandle) GET_FLAG_ISEXCLUDED(NEventCodes+NQueue+semaphoreHandle-1)
#define SET_MUTEX_FLAG_ISEXCLUDED(mutexHandle) SET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+mutexHandle-1)
#define CLEAR_MUTEX_FLAG_ISEXCLUDED(mutexHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+mutexHandle-1)
#define GET_MUTEX_FLAG_ISEXCLUDED(mutexHandle) GET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+mutexHandle-1)
#define SET_TASK_FLAG_ISEXCLUDED(taskHandle) SET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+NMutex+taskHandle-1)
#define CLEAR_TASK_FLAG_ISEXCLUDED(taskHandle) CLEAR_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+NMutex+taskHandle-1)
#define GET_TASK_FLAG_ISEXCLUDED(taskHandle) GET_FLAG_ISEXCLUDED(NEventCodes+NQueue+NSemaphore+NMutex+taskHandle-1)
#define SET_TASK_FLAG_MARKIFE(bitIndex) SET_FLAG_MARKIFE(bitIndex-1)
#define CLEAR_TASK_FLAG_MARKIFE(bitIndex) CLEAR_FLAG_MARKIFE(bitIndex-1)
#define GET_TASK_FLAG_MARKIFE(bitIndex) GET_FLAG_MARKIFE(bitIndex-1)
/* For debug printouts - the names of the object classes */
extern char OBJECTCLASSNAME[NCLASSES][10];
/*=
{
"QUEUE"
"SEMAPHORE",
"MUTEX",
"TASK",
"ISR"
};*/
#endif #endif
#endif

@ -1,308 +1,193 @@
/******************************************************************************* /*******************************************************************************
* FreeRTOS+Trace v2.3.0 Recorder Library * Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcHooks.h * trcKernelHooks.h
* *
* The kernel integration hooks for FreeRTOS (v7.1.0 or later). This file should * The kernel integration hooks.
* be included in the end of FreeRTOSConfig.h, together with: *
* * NOTE:
* #define configUSE_TRACE_FACILITY 1 * For IAR Embedded Workbench for ARM, you need to have a preprocessor condition
* * on the include, to except it from the assembler step which otherwise give
* NOTE: * compile-time errors.
* For IAR Embedded Workbench for ARM, you need to have a preprocessor condition *
* on the include, to except it from the assembler step which otherwise give * #ifdef __ICCARM__
* compile-time errors. * #include "percepio/Include/trcKernelHooks.h"
* * #endif
* #ifdef __ICCARM__ *
* #include "percepio/Include/trcHooks.h" * Terms of Use
* #endif * This software is copyright Percepio AB. The recorder library is free for
* * use together with Percepio products. You may distribute the recorder library
* Terms of Use * in its original form, including modifications in trcPort.c and trcPort.h
* This software is copyright Percepio AB. The recorder library is free for * given that these modification are clearly marked as your own modifications
* use together with Percepio products. You may distribute the recorder library * and documented in the initial comment section of these source files.
* in its original form, including modifications in trcPort.c and trcPort.h * This software is the intellectual property of Percepio AB and may not be
* given that these modification are clearly marked as your own modifications * sold or in other ways commercially redistributed without explicit written
* and documented in the initial comment section of these source files. * permission by Percepio AB.
* This software is the intellectual property of Percepio AB and may not be *
* sold or in other ways commercially redistributed without explicit written * Disclaimer
* permission by Percepio AB. * 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
* Disclaimer * not and cannot warrant the performance or results you may obtain by using the
* The trace tool and recorder library is being delivered to you AS IS and * software or documentation. Percepio AB make no warranties, express or
* Percepio AB makes no warranty as to its use or performance. Percepio AB does * implied, as to noninfringement of third party rights, merchantability, or
* not and cannot warrant the performance or results you may obtain by using the * fitness for any particular purpose. In no event will Percepio AB, its
* software or documentation. Percepio AB make no warranties, express or * technology partners, or distributors be liable to you for any consequential,
* implied, as to noninfringement of third party rights, merchantability, or * incidental or special damages, including any lost profits or lost savings,
* fitness for any particular purpose. In no event will Percepio AB, its * even if a representative of Percepio AB has been advised of the possibility
* technology partners, or distributors be liable to you for any consequential, * of such damages, or for any claim by any third party. Some jurisdictions do
* incidental or special damages, including any lost profits or lost savings, * not allow the exclusion or limitation of incidental, consequential or special
* even if a representative of Percepio AB has been advised of the possibility * damages, or the exclusion of implied warranties or limitations on how long an
* of such damages, or for any claim by any third party. Some jurisdictions do * implied warranty may last, so the above limitations may not apply to you.
* not allow the exclusion or limitation of incidental, consequential or special *
* damages, or the exclusion of implied warranties or limitations on how long an * Copyright Percepio AB, 2013.
* implied warranty may last, so the above limitations may not apply to you. * www.percepio.com
* ******************************************************************************/
* FreeRTOS+Trace is available as Free Edition and in two premium editions.
* You may use the premium features during 30 days for evaluation. #ifndef TRCKERNELHOOKS_H
* Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/ #define TRCKERNELHOOKS_H
*
* Copyright Percepio AB, 2012. #if (USE_TRACEALYZER_RECORDER == 1)
* www.percepio.com
******************************************************************************/ #undef INCLUDE_xTaskGetSchedulerState
#define INCLUDE_xTaskGetSchedulerState 1
#undef INCLUDE_xTaskGetCurrentTaskHandle
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#ifndef TRCHOOKS_H #ifndef INCLUDE_OBJECT_DELETE
#define TRCHOOKS_H #define INCLUDE_OBJECT_DELETE 0
#if (configUSE_TRACE_FACILITY == 1)
#include "trcUser.h"
#undef INCLUDE_xTaskGetSchedulerState
#define INCLUDE_xTaskGetSchedulerState 1
#undef INCLUDE_xTaskGetCurrentTaskHandle
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1
/* Called for each task that becomes ready */
#undef traceMOVED_TASK_TO_READY_STATE
#define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
vTraceStoreTaskReady((unsigned char)pxTCB->uxTaskNumber);
#endif #endif
/* Called on each OS tick. Will call uiPortGetTimestamp to make sure it is called at least once every OS tick. */ #ifndef INCLUDE_READY_EVENTS
#undef traceTASK_INCREMENT_TICK #define INCLUDE_READY_EVENTS 1
#define traceTASK_INCREMENT_TICK( xTickCount ) \ #endif
if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxMissedTicks == 0) {extern uint32_t uiTraceTickCount; uiTraceTickCount++; uiTracePortGetTimeStamp(0);}
/* Called on each task-switch */
#undef traceTASK_SWITCHED_IN
#define traceTASK_SWITCHED_IN() \
vTraceStoreTaskswitch();
/* Called on vTaskSuspend */
#undef traceTASK_SUSPEND
#define traceTASK_SUSPEND( pxTaskToSuspend ) \
vTraceStoreKernelCall(TASK_SUSPEND, TRACE_CLASS_TASK, pxTaskToSuspend->uxTaskNumber); \
vTraceSetTaskInstanceFinished((uint8_t)pxTaskToSuspend->uxTaskNumber);
/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */
#undef traceTASK_DELAY
#define traceTASK_DELAY() \
portENTER_CRITICAL(); \
vTraceStoreKernelCallWithNumericParamOnly(TASK_DELAY, (uint16_t)xTicksToDelay);\
vTraceSetTaskInstanceFinished((uint8_t)pxCurrentTCB->uxTaskNumber);\
portEXIT_CRITICAL();
/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */
#undef traceTASK_DELAY_UNTIL
#define traceTASK_DELAY_UNTIL() \
portENTER_CRITICAL(); \
vTraceStoreKernelCallWithNumericParamOnly(TASK_DELAY_UNTIL, (uint16_t)xTimeToWake); \
vTraceSetTaskInstanceFinished((uint8_t)pxCurrentTCB->uxTaskNumber); \
portEXIT_CRITICAL();
#ifndef INCLUDE_OBJECT_DELETE #ifndef INCLUDE_NEW_TIME_EVENTS
#define INCLUDE_OBJECT_DELETE 1 #define INCLUDE_NEW_TIME_EVENTS 0
#endif #endif
#if (INCLUDE_OBJECT_DELETE == 1) #if (INCLUDE_OBJECT_DELETE == 1)
/* Called on vTaskDelete */ /* This macro will remove the task and store it in the event buffer */
#undef traceTASK_DELETE #undef trcKERNEL_HOOKS_TASK_DELETE
#define traceTASK_DELETE( pxTaskToDelete ) \ #define trcKERNEL_HOOKS_TASK_DELETE(SERVICE, pxTCB) \
trcCRITICAL_SECTION_BEGIN(); \ vTraceStoreKernelCall(TRACE_GET_TASK_EVENT_CODE(SERVICE, SUCCESS, CLASS, pxTCB), TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \
vTraceStoreKernelCall(EVENTGROUP_DELETE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, pxTaskToDelete->uxTaskNumber); \ vTraceStoreObjectNameOnCloseEvent(TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \
vTraceStoreObjectNameOnCloseEvent((objectHandleType)pxTaskToDelete->uxTaskNumber, TRACE_CLASS_TASK); \ vTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \
vTraceStoreObjectPropertiesOnCloseEvent((objectHandleType)pxTaskToDelete->uxTaskNumber, TRACE_CLASS_TASK); \ vTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \
vTraceSetPriorityProperty(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber, (uint8_t)pxTaskToDelete->uxPriority); \ vTraceSetObjectState(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TASK_STATE_INSTANCE_NOT_ACTIVE); \
vTraceSetObjectState(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber, TASK_STATE_INSTANCE_NOT_ACTIVE); \ vTraceFreeObjectHandle(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
vTraceFreeObjectHandle(TRACE_CLASS_TASK, (objectHandleType)pxTaskToDelete->uxTaskNumber); \ #else
trcCRITICAL_SECTION_END(); #undef trcKERNEL_HOOKS_TASK_DELETE
#define trcKERNEL_HOOKS_TASK_DELETE(SERVICE, pxTCB)
#endif #endif
/* Called on vTaskCreate */
#undef traceTASK_CREATE
#define traceTASK_CREATE( pxNewTCB ) \
if (pxNewTCB != NULL){ \
pxNewTCB->uxTaskNumber = xTraceGetObjectHandle(TRACE_CLASS_TASK); \
vTraceSetObjectName(TRACE_CLASS_TASK, (objectHandleType)pxNewTCB->uxTaskNumber, (char*)pxNewTCB->pcTaskName); \
vTraceSetPriorityProperty(TRACE_CLASS_TASK, (objectHandleType)pxNewTCB->uxTaskNumber, (uint8_t)pxNewTCB->uxPriority); \
vTraceStoreKernelCall(EVENTGROUP_CREATE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, pxNewTCB->uxTaskNumber);\
}
/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */
#undef traceTASK_CREATE_FAILED
#define traceTASK_CREATE_FAILED() \
portENTER_CRITICAL();\
vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_TASK, TRACE_CLASS_TASK, 0); \
portEXIT_CRITICAL();
/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */
#undef traceQUEUE_CREATE
#define traceQUEUE_CREATE( pxNewQueue )\
portENTER_CRITICAL(); \
pxNewQueue->ucQueueNumber = xTraceGetObjectHandle(TraceObjectClassTable[pxNewQueue->ucQueueType]);\
vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \
vTraceSetObjectState(TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber, 0); \
portEXIT_CRITICAL();
/* Called in xQueueCreate, if the queue creation fails */
#undef traceQUEUE_CREATE_FAILED
#define traceQUEUE_CREATE_FAILED( queueType ) \
portENTER_CRITICAL();\
vTraceStoreKernelCall((uint8_t)(EVENTGROUP_FAILED_CREATE + TraceObjectClassTable[queueType]), TraceObjectClassTable[queueType], 0); \
portEXIT_CRITICAL();
/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */
#undef traceCREATE_MUTEX
#define traceCREATE_MUTEX( pxNewQueue ) \
portENTER_CRITICAL();\
pxNewQueue->ucQueueNumber = xTraceGetObjectHandle(TRACE_CLASS_MUTEX); \
vTraceStoreKernelCall(EVENTGROUP_CREATE + TraceObjectClassTable[pxNewQueue->ucQueueType], TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber); \
vTraceSetObjectState(TraceObjectClassTable[pxNewQueue->ucQueueType], pxNewQueue->ucQueueNumber, 0); \
portEXIT_CRITICAL();
/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */
#undef traceCREATE_MUTEX_FAILED
#define traceCREATE_MUTEX_FAILED() \
portENTER_CRITICAL();\
vTraceStoreKernelCall(EVENTGROUP_FAILED_CREATE + TRACE_CLASS_MUTEX, TRACE_CLASS_MUTEX, 0);\
portEXIT_CRITICAL();
/* Called when the Mutex can not be given, since not holder */
#undef traceGIVE_MUTEX_RECURSIVE_FAILED
#define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) \
portENTER_CRITICAL();\
vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TRACE_CLASS_MUTEX, TRACE_CLASS_MUTEX, pxMutex->ucQueueNumber); \
portEXIT_CRITICAL();
/* Called when a message is sent to a queue */
#undef traceQUEUE_SEND
#define traceQUEUE_SEND( pxQueue ) \
vTraceStoreKernelCall(EVENTGROUP_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){\
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (uint8_t)pxQueue->ucQueueNumber, (uint8_t)0); \
}else{\
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (uint8_t)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting + 1)); \
}
/* Called when a message failed to be sent to a queue (timeout) */
#undef traceQUEUE_SEND_FAILED
#define traceQUEUE_SEND_FAILED( pxQueue ) \
portENTER_CRITICAL();\
vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
portEXIT_CRITICAL();
/* Called when the task is blocked due to a send operation on a full queue */
#undef traceBLOCKING_ON_QUEUE_SEND
#define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) \
portENTER_CRITICAL();\
vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_SEND + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
portEXIT_CRITICAL();
/* Called when a message is received from a queue */
#undef traceQUEUE_RECEIVE
#define traceQUEUE_RECEIVE( pxQueue ) \
vTraceStoreKernelCall(EVENTGROUP_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){\
extern volatile void * volatile pxCurrentTCB; \
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxCurrentTCB)); /*For mutex, store the new owner rather than queue length */ \
}else{\
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting - 1)); \
}
/* Called when the task is blocked due to a receive operation on an empty queue */
#undef traceBLOCKING_ON_QUEUE_RECEIVE
#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \
portENTER_CRITICAL(); \
vTraceStoreKernelCall(EVENTGROUP_BLOCK_ON_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
if (TraceObjectClassTable[pxQueue->ucQueueType] != TRACE_CLASS_MUTEX){\
extern volatile void * volatile pxCurrentTCB; \
vTraceSetTaskInstanceFinished((objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxCurrentTCB)); \
}\
portEXIT_CRITICAL();
/* Called on xQueuePeek */
#undef traceQUEUE_PEEK
#define traceQUEUE_PEEK( pxQueue ) \
vTraceStoreKernelCall(EVENTGROUP_PEEK + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);
/* Called when a receive operation on a queue fails (timeout) */
#undef traceQUEUE_RECEIVE_FAILED
#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \
portENTER_CRITICAL(); \
vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
portEXIT_CRITICAL();
/* Called when a message is sent from interrupt context, e.g., using xQueueSendFromISR */
#undef traceQUEUE_SEND_FROM_ISR
#define traceQUEUE_SEND_FROM_ISR( pxQueue ) \
vTraceStoreKernelCall(EVENTGROUP_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting + 1));
/* Called when a message send from interrupt context fails (since the queue was full) */
#undef traceQUEUE_SEND_FROM_ISR_FAILED
#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) \
vTraceStoreKernelCall(EVENTGROUP_FAILED_SEND_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);
/* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */
#undef traceQUEUE_RECEIVE_FROM_ISR
#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \
vTraceStoreKernelCall(EVENTGROUP_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)(pxQueue->uxMessagesWaiting - 1));
/* Called when a message receive from interrupt context fails (since the queue was empty) */
#undef traceQUEUE_RECEIVE_FROM_ISR_FAILED
#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) \
vTraceStoreKernelCall(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber);
#if (INCLUDE_OBJECT_DELETE == 1) #if (INCLUDE_OBJECT_DELETE == 1)
/* Called on vQueueDelete */ /* This macro will remove the object and store it in the event buffer */
#undef traceQUEUE_DELETE #undef trcKERNEL_HOOKS_OBJECT_DELETE
#define traceQUEUE_DELETE( pxQueue ) \ #define trcKERNEL_HOOKS_OBJECT_DELETE(SERVICE, CLASS, pxObject) \
{ \ vTraceStoreKernelCall(TRACE_GET_OBJECT_EVENT_CODE(SERVICE, SUCCESS, CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \
portENTER_CRITICAL();\ vTraceStoreObjectNameOnCloseEvent(TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \
vTraceStoreKernelCall(EVENTGROUP_DELETE + TraceObjectClassTable[pxQueue->ucQueueType], TraceObjectClassTable[pxQueue->ucQueueType], pxQueue->ucQueueNumber); \ vTraceStoreObjectPropertiesOnCloseEvent(TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \
vTraceStoreObjectNameOnCloseEvent((objectHandleType)pxQueue->ucQueueNumber, TraceObjectClassTable[pxQueue->ucQueueType]); \ vTraceFreeObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
vTraceStoreObjectPropertiesOnCloseEvent((objectHandleType)pxQueue->ucQueueNumber, TraceObjectClassTable[pxQueue->ucQueueType]); \ #else
if (TraceObjectClassTable[pxQueue->ucQueueType] == TRACE_CLASS_MUTEX){ \ #undef trcKERNEL_HOOKS_OBJECT_DELETE
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (objectHandleType)uxTaskGetTaskNumber((xTaskHandle)pxQueue->pxMutexHolder)); \ #define trcKERNEL_HOOKS_OBJECT_DELETE(SERVICE, CLASS, pxObject)
}else{ \
vTraceSetObjectState(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber, (uint8_t)uxQueueMessagesWaiting(pxQueue)); \
} \
vTraceFreeObjectHandle(TraceObjectClassTable[pxQueue->ucQueueType], (objectHandleType)pxQueue->ucQueueNumber); \
portEXIT_CRITICAL();\
}
#endif #endif
/* Called in vTaskPrioritySet */ /* This macro will create a task in the object table */
#undef traceTASK_PRIORITY_SET #undef trcKERNEL_HOOKS_TASK_CREATE
#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \ #define trcKERNEL_HOOKS_TASK_CREATE(SERVICE, pxTCB) \
vTraceStoreKernelCallWithParam(TASK_PRIORITY_SET, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\ TRACE_SET_TASK_NUMBER(pxTCB) \
vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority); vTraceSetObjectName(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_NAME(pxTCB)); \
vTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \
/* Called in vTaskPriorityInherit, which is called by Mutex operations */ vTraceStoreKernelCall(TRACE_GET_TASK_EVENT_CODE(SERVICE, SUCCESS, CLASS, pxTCB), TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
#undef traceTASK_PRIORITY_INHERIT
#define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \ /* This macro will create a failed create call to create a task */
vTraceStoreKernelCallWithParam(TASK_PRIORITY_INHERIT, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\ #undef trcKERNEL_HOOKS_TASK_CREATE_FAILED
vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority ); #define trcKERNEL_HOOKS_TASK_CREATE_FAILED(SERVICE) \
vTraceStoreKernelCall(TRACE_GET_TASK_EVENT_CODE(SERVICE, FAILED, CLASS, pxTCB), TRACE_CLASS_TASK, 0);
/* Called in vTaskPriorityDisinherit, which is called by Mutex operations */
#undef traceTASK_PRIORITY_DISINHERIT /* This macro will setup a task in the object table */
#define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \ #undef trcKERNEL_HOOKS_OBJECT_CREATE
vTraceStoreKernelCallWithParam(TASK_PRIORITY_DISINHERIT, TRACE_CLASS_TASK, pxTask->uxTaskNumber, uiTraceGetPriorityProperty(TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber));\ #define trcKERNEL_HOOKS_OBJECT_CREATE(SERVICE, CLASS, pxObject)\
vTraceSetPriorityProperty( TRACE_CLASS_TASK, (uint8_t)pxTask->uxTaskNumber, (uint8_t)uxNewPriority ); TRACE_SET_OBJECT_NUMBER(CLASS, pxObject);\
vTraceStoreKernelCall(TRACE_GET_OBJECT_EVENT_CODE(SERVICE, SUCCESS, CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \
vTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), 0);
/* This macro will create a failed create call to create an object */
#undef trcKERNEL_HOOKS_OBJECT_CREATE_FAILED
#define trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(SERVICE, CLASS, kernelClass) \
vTraceStoreKernelCall(TRACE_GET_CLASS_EVENT_CODE(SERVICE, FAILED, CLASS, kernelClass), TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass), 0);
/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
#undef trcKERNEL_HOOKS_KERNEL_SERVICE
#define trcKERNEL_HOOKS_KERNEL_SERVICE(SERVICE, RESULT, CLASS, pxObject) \
vTraceStoreKernelCall(TRACE_GET_OBJECT_EVENT_CODE(SERVICE, RESULT, CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
/* This macro will set the state for an object */
#undef trcKERNEL_HOOKS_SET_OBJECT_STATE
#define trcKERNEL_HOOKS_SET_OBJECT_STATE(CLASS, pxObject, STATE) \
vTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), STATE);
/* This macro will flag a certain task as a finished instance */
#undef trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED
#define trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(CLASS, pxObject) \
vTraceSetTaskInstanceFinished(TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()));
#if INCLUDE_READY_EVENTS == 1
/* This macro will create an event to indicate that a task became Ready */
#undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE
#define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB) \
vTraceStoreTaskReady(TRACE_GET_TASK_NUMBER(pxTCB));
#else
#undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE
#define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB)
#endif
/* Called in vTaskResume */ /* This macro will update the internal tick counter and call vTracePortGetTimeStamp(0) to update the internal counters */
#undef traceTASK_RESUME #undef trcKERNEL_HOOKS_INCREMENT_TICK
#define traceTASK_RESUME( pxTaskToResume ) \ #define trcKERNEL_HOOKS_INCREMENT_TICK() \
vTraceStoreKernelCall(TASK_RESUME, TRACE_CLASS_TASK, pxTaskToResume->uxTaskNumber); { extern uint32_t uiTraceTickCount; uiTraceTickCount++; vTracePortGetTimeStamp(0); }
#if INCLUDE_NEW_TIME_EVENTS == 1
/* This macro will create an event indicating that the OS tick count has increased */
#undef trcKERNEL_HOOKS_NEW_TIME
#define trcKERNEL_HOOKS_NEW_TIME(SERVICE, xValue) \
vTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue);
#else
#undef trcKERNEL_HOOKS_NEW_TIME
#define trcKERNEL_HOOKS_NEW_TIME(SERVICE, xValue)
#endif
/* Called in vTaskResumeFromISR */ /* This macro will create a task switch event to the currently executing task */
#undef traceTASK_RESUME_FROM_ISR #undef trcKERNEL_HOOKS_TASK_SWITCH
#define traceTASK_RESUME_FROM_ISR( pxTaskToResume )\ #define trcKERNEL_HOOKS_TASK_SWITCH( pxTCB ) \
vTraceStoreKernelCall(TASK_RESUME_FROM_ISR, TRACE_CLASS_TASK, pxTaskToResume->uxTaskNumber); vTraceStoreTaskswitch(TRACE_GET_TASK_NUMBER(pxTCB));
/* This macro will create an event to indicate that the task has been suspended */
#undef trcKERNEL_HOOKS_TASK_SUSPEND
#define trcKERNEL_HOOKS_TASK_SUSPEND(SERVICE, pxTCB) \
vTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \
vTraceSetTaskInstanceFinished((uint8_t)TRACE_GET_TASK_NUMBER(pxTCB));
/* This macro will create an event to indicate that a task has called a wait/delay function */
#undef trcKERNEL_HOOKS_TASK_DELAY
#define trcKERNEL_HOOKS_TASK_DELAY(SERVICE, pxTCB, xValue) \
vTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue); \
vTraceSetTaskInstanceFinished((uint8_t)TRACE_GET_TASK_NUMBER(pxTCB));
/* This macro will create an event to indicate that a task has gotten its priority changed */
#undef trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE
#define trcKERNEL_HOOKS_TASK_PRIORITY_CHANGE(SERVICE, pxTCB, uxNewPriority) \
vTraceStoreKernelCallWithParam(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), uiTraceGetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)));\
vTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), (uint8_t)uxNewPriority);
/* This macro will create an event to indicate that the task has been resumed */
#undef trcKERNEL_HOOKS_TASK_RESUME
#define trcKERNEL_HOOKS_TASK_RESUME(SERVICE, pxTCB) \
vTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
#endif #endif
#endif
#endif /* TRCKERNELHOOKS_H */

@ -1,15 +1,15 @@
/******************************************************************************* /*******************************************************************************
* FreeRTOS+Trace v2.3.0 Recorder Library * Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcKernel.h * trcKernel.h
* *
* Functions used by trcHooks.h, for the FreeRTOS kernel integration. * Functions used by trcKernelHooks.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
* 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 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
@ -31,32 +31,29 @@
* 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.
* *
* FreeRTOS+Trace is available as Free Edition and in two premium editions. * Copyright Percepio AB, 2013.
* You may use the premium features during 30 days for evaluation.
* Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/
*
* Copyright Percepio AB, 2012.
* www.percepio.com * www.percepio.com
******************************************************************************/ ******************************************************************************/
#ifndef TRCKERNEL_H #ifndef TRCKERNEL_H
#define TRCKERNEL_H #define TRCKERNEL_H
#include "trcBase.h" #include "trcKernelPort.h"
/* Internal functions */ #if (USE_TRACEALYZER_RECORDER == 1)
/* Internal functions */
#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1 #if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1
void vTraceStoreTaskReady(objectHandleType handle); void vTraceStoreTaskReady(objectHandleType handle);
#endif #endif
void vTraceStoreTaskswitch(void); 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,
uint16_t param); uint32_t param);
void vTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass, void vTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass,
uint32_t objectNumber, uint8_t param); uint32_t objectNumber, uint8_t param);
@ -85,190 +82,7 @@ void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
#define TASK_STATE_INSTANCE_ACTIVE 1 #define TASK_STATE_INSTANCE_ACTIVE 1
#define TASK_STATE_INSTANCE_MARKED_FINISHED 2 #define TASK_STATE_INSTANCE_MARKED_FINISHED 2
extern objectHandleType handle_of_running_task;
/* This defines the mapping between FreeRTOS queue types and our internal
class IDs */
extern traceObjectClass TraceObjectClassTable[5];
/*******************************************************************************
* 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_RE
*
* Events that indicate that something is ready to execute.
******************************************************************************/
#define EVENTGROUP_RE (NULL_EVENT + 2) /*0x02*/
#define TR_TASK_READY (EVENTGROUP_RE + 0) /*0x02*/
/*******************************************************************************
* EVENTGROUP_TS
*
* Events for storing task-switches and interrupts. The RESUME events are
* generated if the task/interrupt is already marked active.
******************************************************************************/
#define EVENTGROUP_TS (EVENTGROUP_RE + 2) /*0x04*/
#define TS_ISR_BEGIN (EVENTGROUP_TS + 0) /*0x04*/
#define TS_ISR_RESUME (EVENTGROUP_TS + 1) /*0x05*/
#define TS_TASK_BEGIN (EVENTGROUP_TS + 2) /*0x06*/
#define TS_TASK_RESUME (EVENTGROUP_TS + 3) /*0x07*/
/*******************************************************************************
* EVENTGROUP_OBJCLOSE_NAME
*
* About Close Events
* When an object is evicted from the object property table (object close), two
* internal events are stored (EVENTGROUP_OBJCLOSE_NAME and
* EVENTGROUP_OBJCLOSE_PROP), containg the handle-name mapping and object
* properties valid up to this point.
******************************************************************************/
#define EVENTGROUP_OBJCLOSE_NAME (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 preceeding CLOSE event. Thus, these
* two events must be generated from within a critical section.
* When queues are closed, arg1 is the "state" property (i.e., number of
* buffered messages/signals).
* When actors are closed, arg1 is priority, arg2 is handle of the "instance
* finish" event, and arg3 is event code of the "instance finish" event.
* In this case, the lower three bits is the object class of the instance finish
* handle. The lower three bits are not used (always zero) when queues are
* closed since the queue type is given in the previous OBJCLOSE_NAME event.
******************************************************************************/
#define EVENTGROUP_OBJCLOSE_PROP (EVENTGROUP_OBJCLOSE_NAME + 8) /*0x10*/
/*******************************************************************************
* EVENTGROUP_CREATE
*
* The events in this group are used to log Kernel object creations.
* The lower three bits in the event code gives the object class, i.e., type of
* create operation (task, queue, semaphore, etc).
******************************************************************************/
#define EVENTGROUP_CREATE (EVENTGROUP_OBJCLOSE_PROP + 8) /*0x18*/
/*******************************************************************************
* EVENTGROUP_SEND
*
* The events in this group are used to log Send/Give events on queues,
* semaphores and mutexeds The lower three bits in the event code gives the
* object class, i.e., what type of object that is operated on (queue, semaphore
* or mutex).
******************************************************************************/
#define EVENTGROUP_SEND (EVENTGROUP_CREATE + 8) /*0x20*/
/*******************************************************************************
* EVENTGROUP_RECEIVE
*
* The events in this group are used to log Receive/Take events on queues,
* semaphores and mutexes. The lower three bits in the event code gives the
* object class, i.e., what type of object that is operated on (queue, semaphore
* or mutex).
******************************************************************************/
#define EVENTGROUP_RECEIVE (EVENTGROUP_SEND + 8) /*0x28*/
/* Send/Give operations, from ISR */
#define EVENTGROUP_SEND_FROM_ISR (EVENTGROUP_RECEIVE + 8) /*0x30*/
/* Receive/Take operations, from ISR */
#define EVENTGROUP_RECEIVE_FROM_ISR (EVENTGROUP_SEND_FROM_ISR + 8) /*0x38*/
/* "Failed" event type versions of above (timeout, failed allocation, etc) */
#define EVENTGROUP_FAILED_KSE (EVENTGROUP_RECEIVE_FROM_ISR + 8) /*0x40*/
/* Failed create calls - memory allocation failed */
#define EVENTGROUP_FAILED_CREATE (EVENTGROUP_FAILED_KSE) /*0x40*/
/* Failed send/give - timeout! */
#define EVENTGROUP_FAILED_SEND (EVENTGROUP_FAILED_CREATE + 8) /*0x48*/
/* Failed receive/take - timeout! */
#define EVENTGROUP_FAILED_RECEIVE (EVENTGROUP_FAILED_SEND + 8) /*0x50*/
/* Failed non-blocking send/give - queue full */
#define EVENTGROUP_FAILED_SEND_FROM_ISR (EVENTGROUP_FAILED_RECEIVE + 8) /*0x58*/
/* Failed non-blocking receive/take - queue empty */
#define EVENTGROUP_FAILED_RECEIVE_FROM_ISR \
(EVENTGROUP_FAILED_SEND_FROM_ISR + 8) /*0x60*/
/* Events when blocking on receive/take */ #endif
#define EVENTGROUP_BLOCK_ON_RECEIVE \
(EVENTGROUP_FAILED_RECEIVE_FROM_ISR + 8) /*0x68*/
/* Events when blocking on send/give */
#define EVENTGROUP_BLOCK_ON_SEND (EVENTGROUP_BLOCK_ON_RECEIVE + 8) /*0x70*/
/* Events on queue peek (receive) */
#define EVENTGROUP_PEEK (EVENTGROUP_BLOCK_ON_SEND + 8) /*0x78*/
/* Events on object delete (vTaskDelete or vQueueDelete) */
#define EVENTGROUP_DELETE (EVENTGROUP_PEEK + 8) /*0x80*/
/* Other events - object class is implied: TASK */
#define EVENTGROUP_OTHERS (EVENTGROUP_DELETE + 8) /*0x88*/
#define TASK_DELAY_UNTIL (EVENTGROUP_OTHERS + 0) /*0x88*/
#define TASK_DELAY (EVENTGROUP_OTHERS + 1) /*0x89*/
#define TASK_SUSPEND (EVENTGROUP_OTHERS + 2) /*0x8A*/
#define TASK_RESUME (EVENTGROUP_OTHERS + 3) /*0x8B*/
#define TASK_RESUME_FROM_ISR (EVENTGROUP_OTHERS + 4) /*0x8C*/
#define TASK_PRIORITY_SET (EVENTGROUP_OTHERS + 5) /*0x8D*/
#define TASK_PRIORITY_INHERIT (EVENTGROUP_OTHERS + 6) /*0x8E*/
#define TASK_PRIORITY_DISINHERIT (EVENTGROUP_OTHERS + 7) /*0x8F*/
/* Not yet used */
#define EVENTGROUP_FTRACE_PLACEHOLDER (EVENTGROUP_OTHERS + 8) /*0x90*/
/* User events */
#define EVENTGROUP_USEREVENT (EVENTGROUP_FTRACE_PLACEHOLDER + 8) /*0x98*/
#define USER_EVENT (EVENTGROUP_USEREVENT + 0)
/* Allow for 0-15 arguments (the number of args is added to event code) */
#define USER_EVENT_LAST (EVENTGROUP_USEREVENT + 15) /*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 immidiatly
* before the original event. The XTS event contains up to 3 additional bytes
* of the DTS value - the higher bytes of the true DTS value. The lower 1-2
* bytes are stored in the normal DTS field.
* There are two types of XTS events, XTS8 and XTS16. An XTS8 event is stored
* when there is only room for 1 byte (8 bit) DTS data in the original event,
* which means a limit of 0xFF (255). The XTS16 is used when the original event
* has a 16 bit DTS field and thereby can handle values up to 0xFFFF (65535).
*
* Using a very high frequency time base can result in many XTS events.
* Preferably, the time between two OS ticks should fit in 16 bits, i.e.,
* at most 65535. If your time base has a higher frequency, you can define
* the TRACE
******************************************************************************/
#define EVENTGROUP_SYS (EVENTGROUP_USEREVENT + 16) /*0xA8*/
#define XTS8 (EVENTGROUP_SYS + 0) /*0xA8*/
#define XTS16 (EVENTGROUP_SYS + 1) /*0xA9*/
#define EVENT_BEING_WRITTEN (EVENTGROUP_SYS + 2) /*0xAA*/
#define RESERVED_DUMMY_CODE (EVENTGROUP_SYS + 3) /*0xAB*/
#endif #endif

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* FreeRTOS+Trace v2.3.0 Recorder Library * Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcTypes.h * trcTypes.h
@ -9,7 +9,7 @@
* 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
* 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 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
@ -31,11 +31,7 @@
* 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.
* *
* FreeRTOS+Trace is available as Free Edition and in two premium editions. * Copyright Percepio AB, 2013.
* You may use the premium features during 30 days for evaluation.
* Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/
*
* Copyright Percepio AB, 2012.
* www.percepio.com * www.percepio.com
******************************************************************************/ ******************************************************************************/
@ -46,36 +42,10 @@
typedef uint16_t traceLabel; typedef uint16_t traceLabel;
typedef uint8_t UserEventChannel;
typedef uint8_t objectHandleType; typedef uint8_t objectHandleType;
typedef uint8_t traceObjectClass; typedef uint8_t traceObjectClass;
#define TRACE_CLASS_QUEUE ((traceObjectClass)0)
#define TRACE_CLASS_SEMAPHORE ((traceObjectClass)1)
#define TRACE_CLASS_MUTEX ((traceObjectClass)2)
#define TRACE_CLASS_TASK ((traceObjectClass)3)
#define TRACE_CLASS_ISR ((traceObjectClass)4)
typedef uint8_t traceKernelService;
#define TRACE_KERNEL_SERVICE_TASK_CREATE ((traceKernelService)0)
#define TRACE_KERNEL_SERVICE_TASK_DELETE ((traceKernelService)1)
#define TRACE_KERNEL_SERVICE_TASK_DELAY ((traceKernelService)2)
#define TRACE_KERNEL_SERVICE_PRIORITY_SET ((traceKernelService)3)
#define TRACE_KERNEL_SERVICE_TASK_SUSPEND ((traceKernelService)4)
#define TRACE_KERNEL_SERVICE_TASK_RESUME ((traceKernelService)5)
#define TRACE_KERNEL_SERVICE_QUEUE_CREATE ((traceKernelService)6)
#define TRACE_KERNEL_SERVICE_QUEUE_DELETE ((traceKernelService)7)
#define TRACE_KERNEL_SERVICE_QUEUE_SEND ((traceKernelService)8)
#define TRACE_KERNEL_SERVICE_QUEUE_RECEIVE ((traceKernelService)9)
#define TRACE_KERNEL_SERVICE_QUEUE_PEEK ((traceKernelService)10)
#define TRACE_KERNEL_SERVICE_MUTEX_CREATE ((traceKernelService)11)
#define TRACE_KERNEL_SERVICE_MUTEX_DELETE ((traceKernelService)12)
#define TRACE_KERNEL_SERVICE_MUTEX_GIVE ((traceKernelService)13)
#define TRACE_KERNEL_SERVICE_MUTEX_TAKE ((traceKernelService)14)
#define TRACE_KERNEL_SERVICE_SEMAPHORE_CREATE ((traceKernelService)15)
#define TRACE_KERNEL_SERVICE_SEMAPHORE_DELETE ((traceKernelService)16)
#define TRACE_KERNEL_SERVICE_SEMAPHORE_GIVE ((traceKernelService)17)
#define TRACE_KERNEL_SERVICE_SEMAPHORE_TAKE ((traceKernelService)18)
#endif #endif

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* FreeRTOS+Trace v2.3.0 Recorder Library * Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcUser.h * trcUser.h
@ -8,7 +8,7 @@
* 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
* 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 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
@ -30,25 +30,56 @@
* 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.
* *
* FreeRTOS+Trace is available as Free Edition and in two premium editions. * Copyright Percepio AB, 2013.
* You may use the premium features during 30 days for evaluation.
* Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/
*
* Copyright Percepio AB, 2012.
* www.percepio.com * www.percepio.com
******************************************************************************/ ******************************************************************************/
#ifndef TRCUSER_H #ifndef TRCUSER_H
#define TRCUSER_H #define TRCUSER_H
#include "FreeRTOS.h" #ifdef __cplusplus
extern "C" {
#endif
#include "trcKernel.h" #include "trcKernelPort.h"
#if (configUSE_TRACE_FACILITY == 1) #if (USE_TRACEALYZER_RECORDER == 1)
#ifdef __cplusplus #ifndef USE_SEPARATE_USER_EVENT_BUFFER
extern "C" { #define USE_SEPARATE_USER_EVENT_BUFFER 0
#endif
/*******************************************************************************
* TRACE_STOP_HOOK - Hook Pointer Data Type
*
* Declares a data type for a call back function that will be invoked whenever
* the recorder is stopped.
******************************************************************************/
typedef void (*TRACE_STOP_HOOK)(void);
/*******************************************************************************
* vTraceStopHookPtr
*
* Points to a call back function that is called from vTraceStop().
******************************************************************************/
extern TRACE_STOP_HOOK vTraceStopHookPtr;
/*******************************************************************************
* vTraceInitTraceData
*
* Allocates, if necessary, and initializes the recorder data structure, based
* on the constants in trcConfig.h.
******************************************************************************/
void vTraceInitTraceData(void);
/*******************************************************************************
* vTraceSetRecorderData
*
* If custom allocation is used, this function must be called so the recorder
* library knows where to save the trace data.
******************************************************************************/
#if (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_CUSTOM)
void vTraceSetRecorderData(void* pRecorderData);
#endif #endif
/******************************************************************************* /*******************************************************************************
@ -61,8 +92,8 @@ extern "C" {
* Returns 1 if the recorder was started successfully. * Returns 1 if the recorder was started successfully.
* Returns 0 if the recorder start was prevented due to a previous internal * Returns 0 if the recorder start was prevented due to a previous internal
* error. In that case, check vTraceGetLastError to get the error message. * error. In that case, check vTraceGetLastError to get the error message.
* Any error message is also presented when opening a trace file in * Any error message is also presented when opening a trace file.
* FreeRTOS+Trace v2.2.2 or later. *
******************************************************************************/ ******************************************************************************/
uint32_t uiTraceStart(void); uint32_t uiTraceStart(void);
@ -84,9 +115,9 @@ void vTraceStart(void);
* This starts a task to monitor the status of the recorder module. * This starts a task to monitor the status of the recorder module.
* This task periodically prints a line to the console window, which shows the * This task periodically prints a line to the console window, which shows the
* recorder status, the number of events recorded and the latest timestamp. * recorder status, the number of events recorded and the latest timestamp.
* This task calls vTracePortEnd (trcPort.c) when it detects that the recorder * This task calls vTracePortEnd (trcHardwarePort.c) when it detects that the
* has been stopped. This allows for adding custom actions, e.g., to store the * recorder has been stopped. This allows for adding custom actions, e.g., to
* trace to a file in case a file system is available on the device. * store the trace to a file in case a file system is available on the device.
******************************************************************************/ ******************************************************************************/
void vTraceStartStatusMonitor(void); void vTraceStartStatusMonitor(void);
@ -106,20 +137,6 @@ void vTraceStop(void);
******************************************************************************/ ******************************************************************************/
void vTraceClear(void); void vTraceClear(void);
/*******************************************************************************
* vTraceSetQueueName
*
* Assigns a name to a FreeRTOS Queue, Semaphore or Mutex. This function should
* be called right after creation of the queue/mutex/semaphore. If not using
* this function, the queues/mutexes/semaphores will be presented by their
* numeric handle only.
*
* Example:
* actuatorQ = xQueueCreate(3, sizeof(QueueMessage));
* vTraceSetQueueName(actuatorQ, "ActuatorQueue");
******************************************************************************/
void vTraceSetQueueName(void* queue, const char* name);
#if (INCLUDE_ISR_TRACING == 1) #if (INCLUDE_ISR_TRACING == 1)
/******************************************************************************* /*******************************************************************************
@ -153,15 +170,6 @@ void vTraceSetISRProperties(objectHandleType handle, const char* name, char prio
* vTraceStoreISRBegin * vTraceStoreISRBegin
* *
* Registers the beginning of an Interrupt Service Routine. * Registers the beginning of an Interrupt Service Routine.
*
* Note! This may only be used for interrupts affected by portENTER_CRITICAL.
* In some FreeRTOS ports, such as ARM Cortex M3, this does not disable all
* interrupts. Interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY are still
* enabled, but may not call the FreeRTOS API. Such may not call the recorder
* API, including this function.
*
* See http://www.freertos.org/a00110.html
*
* If allowing nested ISRs, this must be called with interrupts disabled. * If allowing nested ISRs, this must be called with interrupts disabled.
* *
* Example: * Example:
@ -180,6 +188,7 @@ void vTraceSetISRProperties(objectHandleType handle, const char* name, char prio
* vTraceStoreISREnd(); * vTraceStoreISREnd();
* portEXIT_CRITICAL(); * portEXIT_CRITICAL();
* } * }
*
******************************************************************************/ ******************************************************************************/
void vTraceStoreISRBegin(objectHandleType id); void vTraceStoreISRBegin(objectHandleType id);
@ -188,14 +197,6 @@ void vTraceStoreISRBegin(objectHandleType id);
* *
* Registers the end of an Interrupt Service Routine. * Registers the end of an Interrupt Service Routine.
* *
* Note! This may only be used for interrupts affected by portENTER_CRITICAL.
* In some FreeRTOS ports, such as ARM Cortex M3, this does not disable all
* interrupts. Interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY are still
* enabled, but may not call the FreeRTOS API. Such may not call the recorder
* API, including this function.
*
* See http://www.freertos.org/a00110.html
*
* If allowing nested ISRs, this must be called with interrupts disabled. * If allowing nested ISRs, this must be called with interrupts disabled.
* *
* Example: * Example:
@ -214,6 +215,7 @@ void vTraceStoreISRBegin(objectHandleType id);
* vTraceStoreISREnd(); * vTraceStoreISREnd();
* portEXIT_CRITICAL(); * portEXIT_CRITICAL();
* } * }
*
******************************************************************************/ ******************************************************************************/
void vTraceStoreISREnd(void); void vTraceStoreISREnd(void);
@ -378,6 +380,12 @@ void vTraceUserEvent(traceLabel eventLabel);
******************************************************************************/ ******************************************************************************/
void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...); void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...);
#if (USE_SEPARATE_USER_EVENT_BUFFER == 1)
UserEventChannel xTraceRegisterChannelFormat(traceLabel channel, traceLabel formatStr);
void vTraceChannelPrintF(UserEventChannel channel, ...);
void vTraceChannelUserEvent(UserEventChannel channel);
#endif
#else #else
#define vTracePrintF(eventLabel, formatStr, ...); #define vTracePrintF(eventLabel, formatStr, ...);
@ -386,59 +394,31 @@ void vTracePrintF(traceLabel eventLabel, const char* formatStr, ...);
#endif #endif
/******************************************************************************
* vTraceExclude______FromTrace
*
* Excludes a task or object from the trace.
* This can be useful if some irrelevant task is very frequent and is "eating
* up the buffer". This should be called after the task has been created, but
* before starting the FreeRTOS scheduler.
*****************************************************************************/
void vTraceExcludeQueueFromTrace(void* handle);
void vTraceExcludeSemaphoreFromTrace(void* handle);
void vTraceExcludeMutexFromTrace(void* handle);
void vTraceExcludeTaskFromTrace(void* handle);
void vTraceExcludeKernelServiceFromTrace(traceKernelService kernelService);
/******************************************************************************
* vTraceInclude______InTrace
*
* Includes a task, object or kernel service in the trace. This is only
* necessary if the task or object has been previously exluded.
*****************************************************************************/
void vTraceIncludeQueueInTrace(void* handle);
void vTraceIncludeSemaphoreInTrace(void* handle);
void vTraceIncludeMutexInTrace(void* handle);
void vTraceIncludeTaskInTrace(void* handle);
void vTraceIncludeKernelServiceInTrace(traceKernelService kernelService);
#ifdef __cplusplus
}
#endif
#else #else
#include "trcPort.h" /* Empty defines for user functions to avoid compiler errors if trace is not to be used */
#define vTraceInit() #define vTraceInitTraceData()
#define uiTraceStart() (1) #define uiTraceStart() (1) // Fake "success", if used when recorder is excluded from build
#define vTraceStart() #define vTraceStart()
#define vTraceStop() #define vTraceStop()
#define vTraceClear() #define vTraceClear()
#define vTraceStartStatusMonitor() #define vTraceStartStatusMonitor()
#define vTracePortSetOutFile(f)
#define vTraceGetTraceBuffer() ((void*)0) #define vTraceGetTraceBuffer() ((void*)0)
#define uiTraceGetTraceBufferSize() 0 #define uiTraceGetTraceBufferSize() 0
#define xTraceOpenLabel(label) 0 #define xTraceOpenLabel(label) 0
#define vTraceUserEvent(eventLabel) #define vTraceUserEvent(eventLabel)
#define vTracePrintF(eventLabel,formatStr,...) #define vTracePrintF(eventLabel,formatStr,...)
#define vTraceExcludeTaskFromSchedulingTrace(name) #define vTraceExcludeTaskFromSchedulingTrace(name)
#define vTraceSetQueueName(queue, name)
#define vTraceTaskSkipDefaultInstanceFinishedEvents() #define vTraceTaskSkipDefaultInstanceFinishedEvents()
#define vTraceSetISRProperties(handle, name, priority) #define vTraceSetISRProperties(handle, name, priority)
#define vTraceStoreISRBegin(id) #define vTraceStoreISRBegin(id)
#define vTraceStoreISREnd() #define vTraceStoreISREnd()
#endif #endif
#ifdef __cplusplus
}
#endif #endif
#endif

@ -1,24 +1,28 @@
FreeRTOS+Trace - Uploading the trace data Tracealyzer - Uploading the trace data
----------------------------------------- -----------------------------------------
Percepio AB, Nov. 8, 2012 Percepio AB, Nov. 8, 2012
This document decribes how to upload the trace data from the target system to This document decribes how to upload the trace data from the target system to
FreeRTOS+Trace. For information on how to integrate and enable the recorder Tracealyzer.
library in your FreeRTOS project, see the FreeRTOS+Trace User Manual.
FreeRTOS+Trace uses your existing debugger to upload the trace data from the Tracealyzer uses your existing debugger to upload the trace data from the
chip RAM. This is a plain RAM dump, that is done whenever you want to look at chip RAM. This is a plain RAM dump, that is done whenever you want to look at
the trace buffer contents. This means it works with essentially with any debug the trace buffer contents. This means it works with essentially with any debug
probe on the market. probe on the market.
Note that hardware-generated trace is not required (or used by) FreeRTOS+Trace. If the device has a file system and some possibility of accessing this file
We however plan to add support for that in future versions of FreeRTOS+Trace system from the development PC, it is also possible to write the recorder data
to a file, using vTraceGetTraceBuffer() and uiTraceGetTraceBufferSize()
found in trcUser.h/.c.
Note that hardware-generated trace is not required (or used by) Tracealyzer.
We however plan to add support for that in future versions of Tracealyzer
and other Tracealyzer products. and other Tracealyzer products.
Built-in support for Segger J-Link/J-Trace and Atmel SAM-ICE Built-in support for Segger J-Link/J-Trace and Atmel SAM-ICE
------------------------------------------------------------ ------------------------------------------------------------
FreeRTOS+Trace v2.3 supports Segger J-Link and J-Link compatible debuggers Tracealyzer v2.3 supports Segger J-Link and J-Link compatible debuggers
directly, without any debugger IDE involved. Using other debug probes is directly, without any debugger IDE involved. Using other debug probes is
also possible, but requires some extra steps, described below. also possible, but requires some extra steps, described below.
@ -36,7 +40,7 @@ can be found can by inspecting the "RecorderData" struct or the
Typical values are 0x0, 0x10000000 or 0x20000000 as start address Typical values are 0x0, 0x10000000 or 0x20000000 as start address
and 0x10000 or 0x20000 as size (64 KB or 128 KB). and 0x10000 or 0x20000 as size (64 KB or 128 KB).
This makes FreeRTOS+Trace reads the chip RAM and locate the trace data. This makes Tracealyzer reads the chip RAM and locate the trace data.
Note that this option is only available if a compatible debug probe is found. Note that this option is only available if a compatible debug probe is found.
J-Link compatible debug probes also include Atmel SAM-ICE and many built-in J-Link compatible debug probes also include Atmel SAM-ICE and many built-in
@ -46,17 +50,17 @@ connection directly to the board). Look for a Segger J-Link label on the board.
MemoryLogger extension in Atmel Studio 6 MemoryLogger extension in Atmel Studio 6
---------------------------------------- ----------------------------------------
Atmel's new MemoryLogger extension provides a superb integration with Atmel's new MemoryLogger extension provides a superb integration with
FreeRTOS+Trace. Look for "MemoryLogger" in Atmel Gallery, available in Tracealyzer. Look for "MemoryLogger" in Atmel Gallery, available in
Atmel Studio and at the Atmel website. Atmel Studio and at the Atmel website.
This extension automatically detects the path to FreeRTOS+Trace, if This extension automatically detects the path to Tracealyzer, if
installed, and gives you a single-click upload/refresh. You can use it installed, and gives you a single-click upload/refresh. You can use it
while debugging and optionally get an automatic refresh eash time the while debugging and optionally get an automatic refresh eash time the
MCU is halted, e.g., on each breakpoint. MCU is halted, e.g., on each breakpoint.
Using other development environments and debug probes Using other development environments and debug probes
----------------------------------------------------- -----------------------------------------------------
Most debuggers are able to save the RAM contents to a file. FreeRTOS+Trace Most debuggers are able to save the RAM contents to a file. Tracealyzer
supports the following common formats: supports the following common formats:
- Binary (.bin), supporting gdb, J-Link and Renesas HEW. - Binary (.bin), supporting gdb, J-Link and Renesas HEW.
- Intel Hex (.hex), supporting IAR Embedded Workbench and Atmel Studio (atprogram.exe) - Intel Hex (.hex), supporting IAR Embedded Workbench and Atmel Studio (atprogram.exe)
@ -66,7 +70,7 @@ When you store the RAM dump, you must also make sure to select the right region,
i.e., start address and size. The recorder data is stored in a single data i.e., start address and size. The recorder data is stored in a single data
block, identified by the pointer RecorderDataPtr. block, identified by the pointer RecorderDataPtr.
It is not necessary to match the begin and end of the recorder data, as long as It is not necessary to match the begin and end of the recorder data, as long as
it is fully included by the dumped memory region. FreeRTOS+Trace automatically it is fully included by the dumped memory region. Tracealyzer automatically
finds the trace data in the RAM dump, thanks to special signatures. For chips finds the trace data in the RAM dump, thanks to special signatures. For chips
with on-chip RAM only, we therefore recommend to dump the entire RAM. This is with on-chip RAM only, we therefore recommend to dump the entire RAM. This is
usually very fast. usually very fast.
@ -84,7 +88,7 @@ In the debugger view, when stopped on a breakpoint:
- File format: Intel Extended - File format: Intel Extended
- Filename: <name>.hex - Filename: <name>.hex
- Press "Save" button - Press "Save" button
You can now open <name>.hex in FreeRTOS+Trace. You can now open <name>.hex in Tracealyzer.
To find the right Start and End addresses, check the address of the symbol To find the right Start and End addresses, check the address of the symbol
"RecorderData". The addresses does not need to match this symbol exactly, as "RecorderData". The addresses does not need to match this symbol exactly, as
@ -100,7 +104,7 @@ In the debugger view, when stopped on a breakpoint:
- Start Address: 00000000 (For RX62N in the demo project) - Start Address: 00000000 (For RX62N in the demo project)
- End Address: 0000FFFF (For RX62N in the demo project) - End Address: 0000FFFF (For RX62N in the demo project)
- Access size: 1 - Access size: 1
- Press "Save" button and open <name>.bin in FreeRTOS+Trace. - Press "Save" button and open <name>.bin in Tracealyzer.
Using Microchip MPLAB v8.86 Using Microchip MPLAB v8.86
------------------------------------------------------ ------------------------------------------------------
@ -110,7 +114,7 @@ Using Microchip MPLAB v8.86
- In the dialog ("Export As"), make sure "Single Column Output" is selected (seems to be default). - In the dialog ("Export As"), make sure "Single Column Output" is selected (seems to be default).
- Select start address 0x0000 and make sure the end address is beyond the RecorderData structure. - Select start address 0x0000 and make sure the end address is beyond the RecorderData structure.
The default values seems to be the whole RAM, so you probably don't need to change this. The default values seems to be the whole RAM, so you probably don't need to change this.
- Save as a .mch file and open this file in FreeRTOS+Trace v2.2.4 or later (support for the .mch format was added in v2.2.4). - Save as a .mch file and open this file in Tracealyzer v2.2.4 or later (support for the .mch format was added in v2.2.4).
Using STM32 ST-Link Using STM32 ST-Link
------------------------------------------------------ ------------------------------------------------------
@ -118,7 +122,7 @@ Using STM32 ST-Link
- Connect to the device and view the device memory. - Connect to the device and view the device memory.
- Set the view to display the entire RAM, or at least the section containing the RecorderData structure. - Set the view to display the entire RAM, or at least the section containing the RecorderData structure.
- Select "Save as" and choose binary (.bin) or Intel Hex (.hex) format. - Select "Save as" and choose binary (.bin) or Intel Hex (.hex) format.
- Open the resulting file in FreeRTOS+Trace. - Open the resulting file in Tracealyzer.
In case you have any question, contact support@percepio.com In case you have any question, contact support@percepio.com

@ -1,20 +1,13 @@
FreeRTOS+Trace Trace Recorder Library Tracealyzer Trace Recorder Library
------------------------------------- -------------------------------------
Percepio AB Percepio AB
www.percepio.com www.percepio.com
This directory contains the core trace recorder library used by FreeRTOS+Trace v2.3. This directory contains the a generic trace recorder library for Tracealyzer v2.4.
Ready-to-run demonstrations projects are found at www.percepio.com.
For information on how to integrate the recorder library in your FreeRTOS build, see
the FreeRTOS+Trace User Manual, section 2.
For information on how to upload the trace data from your target system RAM to For information on how to upload the trace data from your target system RAM to
FreeRTOS+Trace, see "debugger trace upload.txt" Tracealyzer, see "debugger trace upload.txt"
NOTE: This trace recorder library requires FreeRTOS v7.3.0 or later.
Files included Files included
-------------- --------------
@ -22,8 +15,9 @@ Files included
- trcUser.c / trcUser.h - The main API towards the application (trcUser.h in the only include necessary). - trcUser.c / trcUser.h - The main API towards the application (trcUser.h in the only include necessary).
- trcKernel.c / trcKernel.h - Internal routines for storing kernel events. - trcKernel.c / trcKernel.h - Internal routines for storing kernel events.
- trcBase.c / trcBase.h - Internal routines for manipulating the data structures and calculating timestamps. - trcBase.c / trcBase.h - Internal routines for manipulating the data structures and calculating timestamps.
- trcPort.c / trcPort.h - The port layer, abstracting the hardware (mainly the timer used for timestamping). - trcHardwarePort.c / trcHardwarePort.h - The port layer, abstracting the hardware (mainly the timer used for timestamping).
- trcHooks.h - The interface between FreeRTOS and the recorder, containing trace macro defintions. - trcKernelHooks.h - The interface between the Kernel and the recorder, containing trace macro defintions.
- trcKernelPort.h - Kernel specific implementations of macros and data.
- trcTypes.h - Type definitions used. - trcTypes.h - Type definitions used.
Hardware Timer Ports Hardware Timer Ports

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* FreeRTOS+Trace v2.3.0 Recorder Library * Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcBase.c * trcBase.c
@ -9,7 +9,7 @@
* 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
* 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 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
@ -31,28 +31,33 @@
* 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.
* *
* FreeRTOS+Trace is available as Free Edition and in two premium editions. * Copyright Percepio AB, 2013.
* You may use the premium features during 30 days for evaluation.
* Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/
*
* Copyright Percepio AB, 2012.
* www.percepio.com * www.percepio.com
******************************************************************************/ ******************************************************************************/
#include "trcUser.h" #include "trcBase.h"
#include "task.h"
#if (USE_TRACEALYZER_RECORDER == 1)
#if (configUSE_TRACE_FACILITY == 1) #include <stdint.h>
/******************************************************************************* /*******************************************************************************
* Static data initializations * Static data initializations
******************************************************************************/ ******************************************************************************/
/* Structure to handle the exclude flags for all objects and tasks. We add some extra objects since index 0 is not used for each object class. */
uint8_t excludedObjects[(TRACE_KERNEL_OBJECT_COUNT + TRACE_NCLASSES) / 8 + 1] = { 0 };
/* Structure to handle the exclude flags for all event codes */
uint8_t excludedEventCodes[NEventCodes / 8 + 1] = { 0 };
/* Keeps track of available handles */
objectHandleStackType objectHandleStacks = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } };
/******************************************************************************* /*******************************************************************************
* RecorderData * RecorderData
* *
* The main data structure. This is the data read by FreeRTOS+Trace, typically * The main data structure. This is the data read by Tracealyzer, typically
* through a debugger RAM dump. The recorder access this through the pointer * through a debugger RAM dump. The recorder access this through the pointer
* RecorderDataPtr, to allow for dynamic memory allocation as well. * RecorderDataPtr, to allow for dynamic memory allocation as well.
* *
@ -80,315 +85,120 @@
* Remember to replace "name" with the correct section name. * Remember to replace "name" with the correct section name.
******************************************************************************/ ******************************************************************************/
static void vInitStartMarkers(void);
#if (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_STATIC) #if (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_STATIC)
#if (USE_LINKER_PRAGMA == 1) #if (USE_LINKER_PRAGMA == 1)
#include "recorderdata_linker_pragma.h" #include "recorderdata_linker_pragma.h"
#endif #endif
RecorderDataType RecorderData =
{
/* start marker, 12 chars */
0x01, 0x02, 0x03, 0x04,
0x71, 0x72, 0x73, 0x74,
0xF1, 0xF2, 0xF3, 0xF4,
/* version code - also used to determine endianness */
VERSION,
/* minor file format version */
MINOR_VERSION,
/* irq priority order */
IRQ_PRIORITY_ORDER,
/* file size (for control) */
sizeof(RecorderDataType),
/* number of events stored so far */
0,
/* size of events buffer (in event records, each 4 bytes) */
EVENT_BUFFER_SIZE,
/* next free event index (event index, not byte address) */
0,
/* buffer is full */
0,
/* frequency of clock user for timestamps, in Hz - should be 0 here
as this is used to indicate "not yet initialized" - this is instead
initialized on the first taskswitch event. */
0,
/* the absolute timestamp of the last stored event, modulo frequency */ RecorderDataType RecorderData;
0,
/* the number of seconds so far */ #endif
0,
/* is recorder active (yes = 1) - note that "close" events are always
stored to keep the name-handle mapping updated!*/
0,
/* Generated by FreeRTOS+Trace in Team Admin mode. Otherwise this should be "". */
TEAM_LICENSE_CODE,
/* debug marker 0 */
0xF0F0F0F0,
/* The Object Property Table - holds info of all active objects */
{
/* Number of object classes, also those not used */
NCLASSES,
/* The size in bytes of the object table byte pool */
DynObjTableSize,
/* The number of slots/handles available for each class */ RecorderDataType* RecorderDataPtr = NULL;
{
NQueue,
NSemaphore,
NMutex,
NTask,
NISR
},
/* The maximum name length for each object class */ /* This version of the function dynamically allocates the trace data */
{ void prvTraceInitTraceData()
NameLenQueue, {
NameLenSemaphore, #if TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_STATIC
NameLenMutex, RecorderDataPtr = &RecorderData;
NameLenTask, #elif TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_DYNAMIC
NameLenISR RecorderDataPtr = (RecorderDataType*)TRACE_MALLOC(sizeof(RecorderDataType));
}, #elif TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_CUSTOM
/* DO NOTHING */
#endif
/* The total length a property table entry of the class */ TRACE_ASSERT(RecorderDataPtr != NULL, "prvTraceInitTraceData, RecorderDataPtr == NULL", );
{
PropertyTableSizeQueue,
PropertyTableSizeSemaphore,
PropertyTableSizeMutex,
PropertyTableSizeTask,
PropertyTableSizeISR
},
/* The start index of each class in the object property table */ if (! RecorderDataPtr)
{ {
StartIndexQueue, vTraceError("No recorder data structure allocated!");
StartIndexSemaphore, return;
StartIndexMutex, }
StartIndexTask,
StartIndexISR
},
/* the object property table - encoded in a byte array using above
definitions */
{0}
},
/* debug marker 1 */ (void)memset(RecorderDataPtr, 0, sizeof(RecorderDataType));
0xF1F1F1F1,
/* The Symbol Table - holds all object names used since system RecorderDataPtr->startmarker0 = 0x00;
startup. Every string is unique, so objects with same name will share RecorderDataPtr->startmarker1 = 0x01;
an entry. Each name entry has four extra bytes: byte 0-1 is a link RecorderDataPtr->startmarker2 = 0x02;
reference in an internal linked list, used for fast lookups, byte 2-3 RecorderDataPtr->startmarker3 = 0x03;
holds a reference to a channel label used for vTracePrintF format RecorderDataPtr->startmarker4 = 0x70;
strings, and byte 4.. holds the object name, followed by a RecorderDataPtr->startmarker5 = 0x71;
zero-termination.*/ RecorderDataPtr->startmarker6 = 0x72;
{ RecorderDataPtr->startmarker7 = 0x73;
SYMBOL_TABLE_SIZE, RecorderDataPtr->startmarker8 = 0xF0;
RecorderDataPtr->startmarker9 = 0xF1;
RecorderDataPtr->startmarker10 = 0xF2;
RecorderDataPtr->startmarker11 = 0xF3;
/* next free index (0 is reserved to mean NULL) */ RecorderDataPtr->version = TRACE_KERNEL_VERSION;
1, RecorderDataPtr->minor_version = TRACE_MINOR_VERSION;
RecorderDataPtr->irq_priority_order = IRQ_PRIORITY_ORDER;
RecorderDataPtr->filesize = sizeof(RecorderDataType);
/* the symbol table byte pool */ RecorderDataPtr->maxEvents = EVENT_BUFFER_SIZE;
{0},
/* this is a 64 entry array holding 16-bit references (indexes) RecorderDataPtr->debugMarker0 = 0xF0F0F0F0;
to the most recent entry of each checksum - i.e., list heads.*/
{0},
}, /* This function is kernel specific */
vTraceInitObjectPropertyTable();
RecorderDataPtr->debugMarker1 = 0xF1F1F1F1;
RecorderDataPtr->SymbolTable.symTableSize = SYMBOL_TABLE_SIZE;
RecorderDataPtr->SymbolTable.nextFreeSymbolIndex = 1;
#if (INCLUDE_FLOAT_SUPPORT == 1) #if (INCLUDE_FLOAT_SUPPORT == 1)
/* example float, for float endian detection */ RecorderDataPtr->exampleFloatEncoding = (float)1.0; /* otherwise already zero */
(float)1.0, #endif
#else RecorderDataPtr->debugMarker2 = 0xF2F2F2F2;
/* This code signals that no float support is included */ (void)strncpy(RecorderDataPtr->systemInfo, TRACE_DESCRIPTION, TRACE_DESCRIPTION_MAX_LENGTH);
(uint32_t)0, RecorderDataPtr->debugMarker3 = 0xF3F3F3F3;
RecorderDataPtr->endmarker0 = 0x0A;
RecorderDataPtr->endmarker1 = 0x0B;
RecorderDataPtr->endmarker2 = 0x0C;
RecorderDataPtr->endmarker3 = 0x0D;
RecorderDataPtr->endmarker4 = 0x71;
RecorderDataPtr->endmarker5 = 0x72;
RecorderDataPtr->endmarker6 = 0x73;
RecorderDataPtr->endmarker7 = 0x74;
RecorderDataPtr->endmarker8 = 0xF1;
RecorderDataPtr->endmarker9 = 0xF2;
RecorderDataPtr->endmarker10 = 0xF3;
RecorderDataPtr->endmarker11 = 0xF4;
#if USE_SEPARATE_USER_EVENT_BUFFER
RecorderDataPtr->userEventBuffer.bufferID = 1;
RecorderDataPtr->userEventBuffer.version = 0;
RecorderDataPtr->userEventBuffer.numberOfSlots = USER_EVENT_BUFFER_SIZE;
RecorderDataPtr->userEventBuffer.numberOfChannels = CHANNEL_FORMAT_PAIRS + 1;
#endif #endif
/* internalErrorOccured */ /* Kernel specific initialization of the objectHandleStacks variable */
0, vTraceInitObjectHandleStack();
/* debug marker 2 */
0xF2F2F2F2,
/* The trace description string, can hold any information about the system,
e.g., version, configuration. Error messages from the recorder are
copied to this buffer. Also used for internal error messages.*/
TRACE_DESCRIPTION,
/* debug marker 3 */
0xF3F3F3F3,
/* the event data buffer, size EVENT_BUFFER_SIZE*4 */
{0},
/* end markers, used to extract the trace from a RAM dump image */
0x0A, 0x0B, 0x0C, 0x0D,
0x71, 0x72, 0x73, 0x74,
0xF1, 0xF2, 0xF3, 0xF4
};
RecorderDataType* RecorderDataPtr = &RecorderData;
/* This version of the function does nothing as the trace data is statically allocated */ /* Fix the start markers of the trace data structure */
RecorderDataType* xTraceInitTraceData(void) vInitStartMarkers();
{
return 0;
} }
#elif (TRACE_DATA_ALLOCATION == TRACE_DATA_ALLOCATION_DYNAMIC) static void vInitStartMarkers()
RecorderDataType* RecorderDataPtr = NULL;
/* This version of the function dynamically allocates the trace data */
RecorderDataType* xTraceInitTraceData(void)
{ {
RecorderDataType* tmp = (RecorderDataType*)pvPortMalloc(sizeof(RecorderDataType)); uint32_t i;
uint8_t *ptr = (uint8_t*)&(RecorderDataPtr->startmarker0);
if (! tmp) if ((*ptr) == 0)
{ {
vTraceError("Malloc failed in xTraceInitTraceData! Reduce size constants in trcConfig.h"); for (i = 0; i < 12; i++)
return NULL; {
ptr[i] += 1;
}
}
else
{
vTraceError("Trace start markers already initialized!");
} }
(void)memset(tmp, 0, sizeof(RecorderDataType));
tmp->startmarker0 = 0x01;
tmp->startmarker1 = 0x02;
tmp->startmarker2 = 0x03;
tmp->startmarker3 = 0x04;
tmp->startmarker4 = 0x71;
tmp->startmarker5 = 0x72;
tmp->startmarker6 = 0x73;
tmp->startmarker7 = 0x74;
tmp->startmarker8 = 0xF1;
tmp->startmarker9 = 0xF2;
tmp->startmarker10 = 0xF3;
tmp->startmarker11 = 0xF4;
tmp->version = VERSION;
tmp->minor_version = MINOR_VERSION;
tmp->irq_priority_order = IRQ_PRIORITY_ORDER;
tmp->filesize = sizeof(RecorderDataType);
tmp->maxEvents = EVENT_BUFFER_SIZE;
tmp->debugMarker0 = 0xF0F0F0F0;
tmp->ObjectPropertyTable.NumberOfObjectClasses = NCLASSES;
tmp->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = DynObjTableSize;
tmp->ObjectPropertyTable.NumberOfObjectsPerClass[0] = NQueue;
tmp->ObjectPropertyTable.NumberOfObjectsPerClass[1] = NSemaphore;
tmp->ObjectPropertyTable.NumberOfObjectsPerClass[2] = NMutex;
tmp->ObjectPropertyTable.NumberOfObjectsPerClass[3] = NTask;
tmp->ObjectPropertyTable.NumberOfObjectsPerClass[4] = NISR;
tmp->ObjectPropertyTable.NameLengthPerClass[0] = NameLenQueue;
tmp->ObjectPropertyTable.NameLengthPerClass[1] = NameLenSemaphore;
tmp->ObjectPropertyTable.NameLengthPerClass[2] = NameLenMutex;
tmp->ObjectPropertyTable.NameLengthPerClass[3] = NameLenTask;
tmp->ObjectPropertyTable.NameLengthPerClass[4] = NameLenISR;
tmp->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;
tmp->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;
tmp->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;
tmp->ObjectPropertyTable.TotalPropertyBytesPerClass[3] = PropertyTableSizeTask;
tmp->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;
tmp->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;
tmp->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;
tmp->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;
tmp->ObjectPropertyTable.StartIndexOfClass[3] = StartIndexTask;
tmp->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;
tmp->debugMarker1 = 0xF1F1F1F1;
tmp->SymbolTable.symTableSize = SYMBOL_TABLE_SIZE;
tmp->SymbolTable.nextFreeSymbolIndex = 1;
#if (INCLUDE_FLOAT_SUPPORT == 1)
tmp->exampleFloatEncoding = (float)1.0; /* otherwize already zero */
#endif
tmp->debugMarker2 = 0xF2F2F2F2;
(void)strncpy(tmp->systemInfo, TRACE_DESCRIPTION, TRACE_DESCRIPTION_MAX_LENGTH);
tmp->debugMarker3 = 0xF3F3F3F3;
tmp->endmarker0 = 0x0A;
tmp->endmarker1 = 0x0B;
tmp->endmarker2 = 0x0C;
tmp->endmarker3 = 0x0D;
tmp->endmarker4 = 0x71;
tmp->endmarker5 = 0x72;
tmp->endmarker6 = 0x73;
tmp->endmarker7 = 0x74;
tmp->endmarker8 = 0xF1;
tmp->endmarker9 = 0xF2;
tmp->endmarker10 = 0xF3;
tmp->endmarker11 = 0xF4;
RecorderDataPtr = tmp;
return (RecorderDataType*)RecorderDataPtr;
} }
#endif
volatile int recorder_busy = 0; volatile int recorder_busy = 0;
char sprintfBuffer[150];
/* For debug printouts - the names of the object classes */
char OBJECTCLASSNAME[NCLASSES][10] =
{
"QUEUE",
"SEMAPHORE",
"MUTEX",
"TASK",
"ISR"
};
/* Initialization of the handle mechanism, see e.g, xTraceGetObjectHandle */
objectHandleStackType objectHandleStacks =
{
/* indexOfNextAvailableHandle */
{
0,
NQueue,
NQueue + NSemaphore,
NQueue + NSemaphore + NMutex,
NQueue + NSemaphore + NMutex + NTask
},
/* lowestIndexOfClass */
{
0,
NQueue,
NQueue + NSemaphore,
NQueue + NSemaphore + NMutex,
NQueue + NSemaphore + NMutex + NTask
},
/* highestIndexOfClass */
{
NQueue - 1,
NQueue + NSemaphore - 1,
NQueue + NSemaphore + NMutex - 1,
NQueue + NSemaphore + NMutex + NTask - 1,
NQueue + NSemaphore + NMutex + NTask + NISR - 1
},
{0},
{0}
};
/* Used for internal state flags of objects */
uint8_t excludedFlags[(NEventCodes+NQueue+NSemaphore+NMutex+NTask) / 8 + 1];
uint8_t ifeFlags[NTask / 8 + 1];
/* Gives the last error message of the recorder. NULL if no error message. */ /* Gives the last error message of the recorder. NULL if no error message. */
char* traceErrorMessage = NULL; char* traceErrorMessage = NULL;
@ -399,20 +209,19 @@ void* xTraceNextFreeEventBufferSlot(void)
vTraceError("Attempt to index outside event buffer!"); vTraceError("Attempt to index outside event buffer!");
return NULL; return NULL;
} }
return (void*)(&RecorderDataPtr-> return (void*)(&RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex*4]);
eventData[RecorderDataPtr->nextFreeIndex*4]);
} }
uint16_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass) uint16_t uiIndexOfObject(objectHandleType objecthandle, uint8_t objectclass)
{ {
if ((objectclass < NCLASSES) && (objecthandle > 0) && (objecthandle <= TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiIndexOfObject: Invalid value for objectclass", 0);
TRACE_ASSERT(objecthandle > 0 && objecthandle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiIndexOfObject: Invalid value for objecthandle", 0);
if ((objectclass < TRACE_NCLASSES) && (objecthandle > 0) && (objecthandle <=
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass])) RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass]))
{ {
return (uint16_t)(RecorderDataPtr-> return (uint16_t)(RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[objectclass] +
ObjectPropertyTable.StartIndexOfClass[objectclass] + (RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[objectclass] * (objecthandle-1)));
(RecorderDataPtr->
ObjectPropertyTable.TotalPropertyBytesPerClass[objectclass] *
(objecthandle-1)));
} }
vTraceError("Object table lookup with invalid object handle or object class!"); vTraceError("Object table lookup with invalid object handle or object class!");
@ -447,6 +256,8 @@ objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass)
static objectHandleType handle; static objectHandleType handle;
static int indexOfHandle; static int indexOfHandle;
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "xTraceGetObjectHandle: Invalid value for objectclass", (objectHandleType)0);
indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass]; indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass];
if (objectHandleStacks.objectHandles[indexOfHandle] == 0) if (objectHandleStacks.objectHandles[indexOfHandle] == 0)
{ {
@ -460,31 +271,11 @@ objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass)
handle = objectHandleStacks.objectHandles[indexOfHandle]; handle = objectHandleStacks.objectHandles[indexOfHandle];
if ( objectHandleStacks.indexOfNextAvailableHandle[objectclass] if (objectHandleStacks.indexOfNextAvailableHandle[objectclass]
> objectHandleStacks.highestIndexOfClass[objectclass] ) > objectHandleStacks.highestIndexOfClass[objectclass])
{ {
/* ERROR */ /* ERROR */
switch(objectclass) vTraceError(pszTraceGetErrorNotEnoughHandles(objectclass));
{
case TRACE_CLASS_TASK:
vTraceError("Not enough TASK handles - increase NTask in trcConfig.h");
break;
case TRACE_CLASS_ISR:
vTraceError("Not enough ISR handles - increase NISR in trcConfig.h");
break;
case TRACE_CLASS_SEMAPHORE:
vTraceError("Not enough SEMAPHORE handles - increase NSemaphore in trcConfig.h");
break;
case TRACE_CLASS_MUTEX:
vTraceError("Not enough MUTEX handles - increase NMutex in trcConfig.h");
break;
case TRACE_CLASS_QUEUE:
vTraceError("Not enough QUEUE handles - increase NQueue in trcConfig.h");
break;
default:
vTraceError("Invalid object class.");
break;
}
handle = 0; /* an invalid/anonymous handle - but the recorder is stopped now... */ handle = 0; /* an invalid/anonymous handle - but the recorder is stopped now... */
} }
@ -502,6 +293,8 @@ objectHandleType xTraceGetObjectHandle(traceObjectClass objectclass)
objectHandleStacks.handleCountWaterMarksOfClass[objectclass] = objectHandleStacks.handleCountWaterMarksOfClass[objectclass] =
(objectHandleType)hndCount; (objectHandleType)hndCount;
} }
TRACE_CLEAR_OBJECT_FLAG_ISEXCLUDED(objectclass, handle);
} }
return handle; return handle;
@ -511,9 +304,12 @@ void vTraceFreeObjectHandle(traceObjectClass objectclass, objectHandleType handl
{ {
int indexOfHandle; int indexOfHandle;
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceFreeObjectHandle: Invalid value for objectclass", );
TRACE_ASSERT(handle > 0 && handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceFreeObjectHandle: Invalid value for handle", );
/* Check that there is room to push the handle on the stack */ /* Check that there is room to push the handle on the stack */
if ( (objectHandleStacks.indexOfNextAvailableHandle[objectclass] - 1) < if ((objectHandleStacks.indexOfNextAvailableHandle[objectclass] - 1) <
objectHandleStacks.lowestIndexOfClass[objectclass] ) objectHandleStacks.lowestIndexOfClass[objectclass])
{ {
/* Error */ /* Error */
vTraceError("Attempt to free more handles than allocated! (duplicate xTaskDelete or xQueueDelete?)"); vTraceError("Attempt to free more handles than allocated! (duplicate xTaskDelete or xQueueDelete?)");
@ -554,46 +350,24 @@ void vTraceSetObjectName(traceObjectClass objectclass,
{ {
static uint16_t idx; static uint16_t idx;
if (handle == 0) TRACE_ASSERT(name != NULL, "vTraceSetObjectName: name == NULL", );
if (objectclass >= TRACE_NCLASSES)
{ {
vTraceError("Illegal handle (0) in vTraceSetObjectName."); vTraceError("Illegal object class in vTraceSetObjectName");
return; return;
} }
switch(objectclass) if (handle == 0)
{ {
case TRACE_CLASS_TASK: vTraceError("Illegal handle (0) in vTraceSetObjectName.");
case TRACE_CLASS_ISR: return;
case TRACE_CLASS_SEMAPHORE:
case TRACE_CLASS_MUTEX:
case TRACE_CLASS_QUEUE:
break;
default:
vTraceError("Illegal object class in vTraceSetObjectName");
break;
} }
if (handle > if (handle > RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass])
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass])
{
switch(objectclass)
{ {
case TRACE_CLASS_TASK: /* ERROR */
vTraceError("Not enough TASK handles - increase NTask in trcConfig.h"); vTraceError(pszTraceGetErrorNotEnoughHandles(objectclass));
break;
case TRACE_CLASS_ISR:
vTraceError("Not enough ISR handles - increase NISR in trcConfig.h");
break;
case TRACE_CLASS_SEMAPHORE:
vTraceError("Not enough SEMAPHORE handles - increase NSemaphore in trcConfig.h");
break;
case TRACE_CLASS_MUTEX:
vTraceError("Not enough MUTEX handles - increase NMutex in trcConfig.h");
break;
case TRACE_CLASS_QUEUE:
vTraceError("Not enough QUEUE handles - increase NQueue in trcConfig.h");
break;
}
} }
else else
{ {
@ -603,21 +377,21 @@ void vTraceSetObjectName(traceObjectClass objectclass,
{ {
(void)strncpy((char*)&(RecorderDataPtr->ObjectPropertyTable.objbytes[idx]), (void)strncpy((char*)&(RecorderDataPtr->ObjectPropertyTable.objbytes[idx]),
name, name,
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ objectclass ] ); RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ objectclass ]);
#ifdef WIN32
printf("vTraceSetObjectName(%d, %d, %s)\n", objectclass, handle, name);
#endif
} }
} }
} }
traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel) traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel)
{ {
static uint16_t result; uint16_t result;
static uint8_t len; uint8_t len;
static uint8_t crc; uint8_t crc;
len = 0; len = 0;
crc = 0; crc = 0;
TRACE_ASSERT(name != NULL, "prvTraceOpenSymbol: name == NULL", (traceLabel)0);
prvTraceGetChecksum(name, &crc, &len); prvTraceGetChecksum(name, &crc, &len);
trcCRITICAL_SECTION_BEGIN(); trcCRITICAL_SECTION_BEGIN();
@ -635,6 +409,8 @@ traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel)
* Supporting functions * Supporting functions
******************************************************************************/ ******************************************************************************/
extern volatile uint32_t rtest_error_flag;
/******************************************************************************* /*******************************************************************************
* vTraceError * vTraceError
* *
@ -649,19 +425,25 @@ traceLabel prvTraceOpenSymbol(const char* name, traceLabel userEventChannel)
******************************************************************************/ ******************************************************************************/
void vTraceError(const char* msg) void vTraceError(const char* msg)
{ {
vTraceStop(); TRACE_ASSERT(msg != NULL, "vTraceError: msg == NULL", );
TRACE_ASSERT(RecorderDataPtr != NULL, "vTraceError: RecorderDataPtr == NULL", );
// Stop the recorder. Note: We do not call vTraceStop, since that adds a weird
// and unnecessary dependency to trcUser.c.
RecorderDataPtr->recorderActive = 0;
if (traceErrorMessage == NULL) if (traceErrorMessage == NULL)
{ {
traceErrorMessage = (char*)msg; traceErrorMessage = (char*)msg;
(void)strncpy(RecorderDataPtr->systemInfo, (void)strncpy(RecorderDataPtr->systemInfo, traceErrorMessage, TRACE_DESCRIPTION_MAX_LENGTH);
traceErrorMessage,
TRACE_DESCRIPTION_MAX_LENGTH);
RecorderDataPtr->internalErrorOccured = 1; RecorderDataPtr->internalErrorOccured = 1;
} }
} }
/****************************************************************************** /******************************************************************************
* prvCheckDataToBeOverwrittenForMultiEntryUserEvents * prvCheckDataToBeOverwrittenForMultiEntryEvents
* *
* This checks if the next event to be overwritten is a multi-entry user event, * This checks if the next event to be overwritten is a multi-entry user event,
* i.e., a USER_EVENT followed by data entries. * i.e., a USER_EVENT followed by data entries.
@ -675,12 +457,14 @@ void vTraceError(const char* msg)
* This is assumed to execute within a critical section... * This is assumed to execute within a critical section...
*****************************************************************************/ *****************************************************************************/
void prvCheckDataToBeOverwrittenForMultiEntryUserEvents( void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nofEntriesToCheck)
uint8_t nofEntriesToCheck)
{ {
/* Generic "int" type is desired - should be 16 bit variable on 16 bit HW */ /* Generic "int" type is desired - should be 16 bit variable on 16 bit HW */
unsigned int i = 0; unsigned int i = 0;
unsigned int e = 0; unsigned int e = 0;
TRACE_ASSERT(nofEntriesToCheck != 0, "prvCheckDataToBeOverwrittenForMultiEntryEvents: nofEntriesToCheck == 0", );
while (i < nofEntriesToCheck) while (i < nofEntriesToCheck)
{ {
e = RecorderDataPtr->nextFreeIndex + i; e = RecorderDataPtr->nextFreeIndex + i;
@ -692,6 +476,20 @@ void prvCheckDataToBeOverwrittenForMultiEntryUserEvents(
{ {
(void)memset(& RecorderDataPtr->eventData[e*4], 0, 4 + 4 * nDataEvents); (void)memset(& RecorderDataPtr->eventData[e*4], 0, 4 + 4 * nDataEvents);
} }
}
else if (RecorderDataPtr->eventData[e*4] == DIV_XPS)
{
if ((e + 1) < RecorderDataPtr->maxEvents)
{
/* Clear 8 bytes */
(void)memset(& RecorderDataPtr->eventData[e*4], 0, 4 + 4);
}
else
{
/* Clear 8 bytes, 4 first and 4 last */
(void)memset(& RecorderDataPtr->eventData[0], 0, 4);
(void)memset(& RecorderDataPtr->eventData[e*4], 0, 4);
}
} }
i++; i++;
} }
@ -715,7 +513,7 @@ void prvTraceUpdateCounters(void)
if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE) if (RecorderDataPtr->nextFreeIndex >= EVENT_BUFFER_SIZE)
{ {
#if (RECORDER_STORE_MODE == STORE_MODE_RING_BUFFER) #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)
RecorderDataPtr->bufferIsFull = 1; RecorderDataPtr->bufferIsFull = 1;
RecorderDataPtr->nextFreeIndex = 0; RecorderDataPtr->nextFreeIndex = 0;
#else #else
@ -723,8 +521,8 @@ void prvTraceUpdateCounters(void)
#endif #endif
} }
#if (RECORDER_STORE_MODE == STORE_MODE_RING_BUFFER) #if (TRACE_RECORDER_STORE_MODE == TRACE_STORE_MODE_RING_BUFFER)
prvCheckDataToBeOverwrittenForMultiEntryUserEvents(1); prvCheckDataToBeOverwrittenForMultiEntryEvents(1);
#endif #endif
#ifdef STOP_AFTER_N_EVENTS #ifdef STOP_AFTER_N_EVENTS
@ -754,26 +552,25 @@ uint16_t prvTraceGetDTS(uint16_t param_maxDTS)
uint32_t dts = 0; uint32_t dts = 0;
uint32_t timestamp = 0; uint32_t timestamp = 0;
TRACE_ASSERT(param_maxDTS == 0xFF || param_maxDTS == 0xFFFF, "prvTraceGetDTS: Invalid value for param_maxDTS", 0);
if (RecorderDataPtr->frequency == 0) if (RecorderDataPtr->frequency == 0)
{ {
/* If HWTC_PERIOD is mapped to the timer reload register, /* If HWTC_PERIOD is mapped to the timer reload register,
such as in the Cortex M port, it is not initialized before such as in the Cortex M port, it might not be initialized
FreeRTOS has been started. We therefore store the frequency before the Kernel scheduler has been started has been
of the timer at the first timestamped event after the started. We therefore store the frequency of the timer at
scheduler has started. (Note that this function is called the first timestamped event after the scheduler has started.
also by vTraceStart and uiTraceStart, which might be (Note that this function is called also by vTraceStart and
called before the scheduler has been started.) */ uiTraceStart, which might be called before the scheduler
has been started.) */
#if (SELECTED_PORT == PORT_Win32) #if (SELECTED_PORT == PORT_Win32)
RecorderDataPtr->frequency = 100000; RecorderDataPtr->frequency = 100000;
#elif (SELECTED_PORT == PORT_HWIndependent) #elif (SELECTED_PORT == PORT_HWIndependent)
RecorderDataPtr->frequency = configTICK_RATE_HZ; RecorderDataPtr->frequency = TRACE_TICK_RATE_HZ;
#else #else
if (xTaskGetSchedulerState() != 0) /* Has the scheduler started? */ RecorderDataPtr->frequency = TRACE_CPU_CLOCK_HZ / (uint32_t)HWTC_DIVISOR;
{
RecorderDataPtr->frequency =
(uint32_t)HWTC_PERIOD * (uint32_t)configTICK_RATE_HZ / (uint32_t)HWTC_DIVISOR;
}
#endif #endif
} }
@ -783,22 +580,12 @@ uint16_t prvTraceGetDTS(uint16_t param_maxDTS)
* comes from the modulo operation. * comes from the modulo operation.
**************************************************************************/ **************************************************************************/
uiTracePortGetTimeStamp(&timestamp); vTracePortGetTimeStamp(&timestamp);
/*************************************************************************** /***************************************************************************
* This condition is only for the Win32 port, since it does not use the tick * Since dts is unsigned the result will be correct even if timestamp has
* count but instead only HWTC_COUNT (from the performance counter). * wrapped around.
* Without this condition, you sometimes get a negative dts value (converted
* into a very large unsiged value) when the performance counter wraps
* around. In other "normal" ports also using the FreeRTOS tick counter, this
* condition can not occur and therefore has no impact.
***************************************************************************/ ***************************************************************************/
if (timestamp < old_timestamp)
{
timestamp += RecorderDataPtr->frequency;
}
dts = timestamp - old_timestamp; dts = timestamp - old_timestamp;
old_timestamp = timestamp; old_timestamp = timestamp;
@ -813,7 +600,9 @@ uint16_t prvTraceGetDTS(uint16_t param_maxDTS)
RecorderDataPtr->absTimeLastEvent += dts % RecorderDataPtr->frequency; RecorderDataPtr->absTimeLastEvent += dts % RecorderDataPtr->frequency;
} }
else else
{
RecorderDataPtr->absTimeLastEvent += dts; RecorderDataPtr->absTimeLastEvent += dts;
}
/* Check if absTimeLastEvent >= 1 second */ /* Check if absTimeLastEvent >= 1 second */
if (RecorderDataPtr->absTimeLastEvent >= RecorderDataPtr->frequency) if (RecorderDataPtr->absTimeLastEvent >= RecorderDataPtr->frequency)
@ -858,7 +647,7 @@ uint16_t prvTraceGetDTS(uint16_t param_maxDTS)
} }
} }
return (uint16_t)(dts % (param_maxDTS + 1)); return (uint16_t)dts & param_maxDTS;
} }
/******************************************************************************* /*******************************************************************************
@ -881,6 +670,9 @@ traceLabel prvTraceLookupSymbolTableEntry(const char* name,
{ {
uint16_t i = RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ]; uint16_t i = RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ];
TRACE_ASSERT(name != NULL, "prvTraceLookupSymbolTableEntry: name == NULL", (traceLabel)0);
TRACE_ASSERT(len != 0, "prvTraceLookupSymbolTableEntry: len == 0", (traceLabel)0);
while (i != 0) while (i != 0)
{ {
if (RecorderDataPtr->SymbolTable.symbytes[i + 2] == (chn & 0x00FF)) if (RecorderDataPtr->SymbolTable.symbytes[i + 2] == (chn & 0x00FF))
@ -920,6 +712,10 @@ uint16_t prvTraceCreateSymbolTableEntry(const char* name,
traceLabel channel) traceLabel channel)
{ {
uint16_t ret = 0; uint16_t ret = 0;
TRACE_ASSERT(name != NULL, "prvTraceCreateSymbolTableEntry: name == NULL", 0);
TRACE_ASSERT(len != 0, "prvTraceCreateSymbolTableEntry: len == 0", 0);
if (RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + len + 4 >= SYMBOL_TABLE_SIZE) if (RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + len + 4 >= SYMBOL_TABLE_SIZE)
{ {
vTraceError("Symbol table full. Increase SYMBOL_TABLE_SIZE in trcConfig.h"); vTraceError("Symbol table full. Increase SYMBOL_TABLE_SIZE in trcConfig.h");
@ -945,10 +741,10 @@ uint16_t prvTraceCreateSymbolTableEntry(const char* name,
(uint8_t)(channel / 0x100); (uint8_t)(channel / 0x100);
/* set name (bytes 4...4+len-1) */ /* set name (bytes 4...4+len-1) */
(void)strncpy((char*)&( RecorderDataPtr->SymbolTable.symbytes (void)strncpy((char*)&(RecorderDataPtr->SymbolTable.symbytes
[ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 4] ), name, len); [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 4]), name, len);
/* Set zero termination (at offest 4+len) */ /* Set zero termination (at offset 4+len) */
RecorderDataPtr->SymbolTable.symbytes RecorderDataPtr->SymbolTable.symbytes
[RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 4 + len] = '\0'; [RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 4 + len] = '\0';
@ -977,15 +773,20 @@ void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength)
unsigned char c; unsigned char c;
int length = 0; int length = 0;
int crc = 0; int crc = 0;
if ( pname != (const char *) 0 )
TRACE_ASSERT(pname != NULL, "prvTraceGetChecksum: pname == NULL", );
TRACE_ASSERT(pcrc != NULL, "prvTraceGetChecksum: pcrc == NULL", );
TRACE_ASSERT(plength != NULL, "prvTraceGetChecksum: plength == NULL", );
if (pname != (const char *) 0)
{ {
for ( ; (c = *pname++) != '\0'; ) for (; (c = *pname++) != '\0';)
{ {
crc += c; crc += c;
length++; length++;
} }
} }
*pcrc = (uint8_t)(crc % 64); *pcrc = (uint8_t)(crc & 0x3F);
*plength = (uint8_t)length; *plength = (uint8_t)length;
} }

@ -0,0 +1,119 @@
/*******************************************************************************
* Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com
*
* trcHardwarePort.c
*
* Contains together with trcHardwarePort.h all hardware portability issues of
* the trace recorder library.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* Copyright Percepio AB, 2013.
* www.percepio.com
******************************************************************************/
#include "trcHardwarePort.h"
#if (USE_TRACEALYZER_RECORDER == 1)
#include <stdint.h>
/*******************************************************************************
* uiTraceTickCount
*
* This variable is should be updated by the Kernel tick interrupt. This does
* not need to be modified when developing a new timer port. It is preferred to
* keep any timer port changes in the HWTC macro definitions, which typically
* give sufficient flexibility.
******************************************************************************/
uint32_t uiTraceTickCount = 0;
/******************************************************************************
* vTracePortGetTimeStamp
*
* Returns the current time based on the HWTC macros which provide a hardware
* isolation layer towards the hardware timer/counter.
*
* The HWTC macros and vTracePortGetTimeStamp is the main porting issue
* or the trace recorder library. Typically you should not need to change
* the code of vTracePortGetTimeStamp if using the HWTC macros.
*
******************************************************************************/
void vTracePortGetTimeStamp(uint32_t *pTimestamp)
{
static uint32_t last_traceTickCount = 0;
static uint32_t last_hwtc_count = 0;
uint32_t traceTickCount = 0;
uint32_t hwtc_count = 0;
/* Retrieve HWTC_COUNT only once since the same value should be used all throughout this function. */
#if (HWTC_COUNT_DIRECTION == DIRECTION_INCREMENTING)
hwtc_count = HWTC_COUNT;
#elif (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING)
hwtc_count = HWTC_PERIOD - HWTC_COUNT;
#else
Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly!
Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING
#endif
if (last_traceTickCount - uiTraceTickCount - 1 < 0x80000000)
{
/* This means last_traceTickCount is higher than uiTraceTickCount,
so we have previously compensated for a missed tick.
Therefore we use the last stored value because that is more accurate. */
traceTickCount = last_traceTickCount;
}
else
{
/* Business as usual */
traceTickCount = uiTraceTickCount;
}
/* Check for overflow. May occur if the update of uiTraceTickCount has been
delayed due to disabled interrupts. */
if (traceTickCount == last_traceTickCount && hwtc_count < last_hwtc_count)
{
/* A trace tick has occurred but not been executed by the kernel, so we compensate manually. */
traceTickCount++;
}
/* Check if the return address is OK, then we perform the calculation. */
if (pTimestamp)
{
/* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */
*pTimestamp = traceTickCount * (HWTC_PERIOD / HWTC_DIVISOR);
/* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / HWTC_DIVISOR. */
*pTimestamp += (hwtc_count + traceTickCount * (HWTC_PERIOD % HWTC_DIVISOR)) / HWTC_DIVISOR;
}
/* Store the previous values. */
last_traceTickCount = traceTickCount;
last_hwtc_count = hwtc_count;
}
#endif

@ -1,16 +1,15 @@
/******************************************************************************* /*******************************************************************************
* FreeRTOS+Trace v2.3.0 Recorder Library * Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com * Percepio AB, www.percepio.com
* *
* trcKernel.c * trcKernel.c
* *
* Functions for integration of the trace recorder library in the FreeRTOS * Functions used by trcKernelHooks.h.
* kernel (requires FreeRTOS v7.1.0 or later).
* *
* 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
* 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 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
@ -32,75 +31,22 @@
* 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.
* *
* FreeRTOS+Trace is available as Free Edition and in two premium editions. * Copyright Percepio AB, 2013.
* You may use the premium features during 30 days for evaluation.
* Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/
*
* Copyright Percepio AB, 2012.
* www.percepio.com * www.percepio.com
******************************************************************************/ ******************************************************************************/
#include "trcUser.h" #include "trcKernel.h"
#include "task.h"
#if (configUSE_TRACE_FACILITY == 1)
#if (USE_TRACEALYZER_RECORDER == 1)
#include <stdint.h>
/******************************************************************************
* TraceObjectClassTable
* Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).
* This was added since we want to map both types of Mutex and both types of
* Semaphores on common classes for all Mutexes and all Semaphores respectively.
*
* FreeRTOS Queue types
* #define queueQUEUE_TYPE_BASE ( 0U ) => TRACE_CLASS_QUEUE
* #define queueQUEUE_TYPE_MUTEX ( 1U ) => TRACE_CLASS_MUTEX
* #define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( 2U ) => TRACE_CLASS_SEMAPHORE
* #define queueQUEUE_TYPE_BINARY_SEMAPHORE ( 3U ) => TRACE_CLASS_SEMAPHORE
* #define queueQUEUE_TYPE_RECURSIVE_MUTEX ( 4U ) => TRACE_CLASS_MUTEX
******************************************************************************/
traceObjectClass TraceObjectClassTable[5] = {TRACE_CLASS_QUEUE,
TRACE_CLASS_MUTEX,
TRACE_CLASS_SEMAPHORE,
TRACE_CLASS_SEMAPHORE,
TRACE_CLASS_MUTEX };
/* This is defined in FreeRTOS! */
extern volatile void * volatile pxCurrentTCB;
/* Internal variables */ /* Internal variables */
uint8_t nISRactive = 0; 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;
static uint8_t prvTraceIsObjectExcluded(traceObjectClass, uint32_t); static uint32_t prvTraceGetParam(uint32_t, uint32_t);
/*******************************************************************************
* prvTraceIsObjectExcluded
*
* Private function that accepts an object class and an object number and uses
* that to determine if the object has been flagged as excluded.
******************************************************************************/
static uint8_t prvTraceIsObjectExcluded(traceObjectClass objectClass, uint32_t objectNumber)
{
switch(objectClass)
{
case TRACE_CLASS_QUEUE:
return GET_QUEUE_FLAG_ISEXCLUDED(objectNumber);
break;
case TRACE_CLASS_SEMAPHORE:
return GET_SEMAPHORE_FLAG_ISEXCLUDED(objectNumber);
break;
case TRACE_CLASS_MUTEX:
return GET_MUTEX_FLAG_ISEXCLUDED(objectNumber);
break;
case TRACE_CLASS_TASK:
return GET_TASK_FLAG_ISEXCLUDED(objectNumber);
break;
}
return 0;
}
#if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1 #if !defined INCLUDE_READY_EVENTS || INCLUDE_READY_EVENTS == 1
/******************************************************************************* /*******************************************************************************
@ -113,7 +59,23 @@ void vTraceStoreTaskReady(objectHandleType handle)
uint16_t dts3; uint16_t dts3;
TREvent* tr; TREvent* tr;
if (!GET_TASK_FLAG_ISEXCLUDED(handle)) TRACE_ASSERT(handle > 0 && handle <= NTask, "vTraceStoreTaskReady: Invalid value for handle", );
if (recorder_busy)
{
/***********************************************************************
* This should never occur, as the tick- and kernel call ISR is on lowest
* interrupt priority and always are disabled during the critical sections
* of the recorder.
***********************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (1)");
return;
}
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
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! */ if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
@ -122,7 +84,7 @@ void vTraceStoreTaskReady(objectHandleType handle)
if (tr != NULL) if (tr != NULL)
{ {
tr->type = TR_TASK_READY; tr->type = DIV_TASK_READY;
tr->dts = dts3; tr->dts = dts3;
tr->objHandle = handle; tr->objHandle = handle;
@ -130,20 +92,38 @@ void vTraceStoreTaskReady(objectHandleType handle)
} }
} }
} }
}
} }
#endif #endif
/******************************************************************************* /*******************************************************************************
* vTraceStoreKernelCall * vTraceStoreKernelCall
* *
* This is the main integration point for storing FreeRTOS kernel calls, and * This is the main integration point for storing kernel calls, and
* is called by the hooks in FreeRTOS.h (see trcKernel.h for event codes). * is called by the hooks in trcKernelHooks.h (see trcKernelPort.h for event codes).
******************************************************************************/ ******************************************************************************/
void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber) void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber)
{ {
KernelCall * kse; KernelCall * kse;
uint16_t dts1; uint16_t dts1;
TRACE_ASSERT(ecode < 0xFF, "vTraceStoreKernelCall: ecode >= 0xFF", );
TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCall: objectClass >= TRACE_NCLASSES", );
TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCall: Invalid value for objectNumber", );
if (recorder_busy)
{
/*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (2)");
return;
}
if (handle_of_last_logged_task == 0) if (handle_of_last_logged_task == 0)
{ {
return; return;
@ -155,30 +135,8 @@ void vTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_
/* 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)
{ {
/* Make sure ISRs never change the IFE flags of tasks */
if (!nISRactive)
{
/* This checks if this is the first kernel call after a call to
vTraceTaskInstanceIsFinished. In that case, calls to this kernel service
with this specific kernel object become the "instance finish event"
(IFE) of the calling task.*/
if (GET_TASK_FLAG_MARKIFE(handle_of_last_logged_task))
{
/* Reset the flag - this has been handled now */
CLEAR_TASK_FLAG_MARKIFE(handle_of_last_logged_task);
/* Store the kernel service tagged as instance finished event */
PROPERTY_TASK_IFE_SERVICECODE(handle_of_last_logged_task) =
(uint8_t)ecode;
/* Store the handle of the specific kernel object */
PROPERTY_TASK_IFE_OBJHANDLE(handle_of_last_logged_task) =
(objectHandleType)objectNumber;
}
}
/* Check if the referenced object or the event code is excluded */ /* Check if the referenced object or the event code is excluded */
if (!prvTraceIsObjectExcluded(objectClass, objectNumber) && !GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode)) if (!uiTraceIsObjectExcluded(objectClass, objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(ecode))
{ {
trcCRITICAL_SECTION_BEGIN(); trcCRITICAL_SECTION_BEGIN();
dts1 = (uint16_t)prvTraceGetDTS(0xFFFF); dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);
@ -214,11 +172,28 @@ void vTraceStoreKernelCallWithParam(uint32_t evtcode,
KernelCallWithParamAndHandle * kse; KernelCallWithParamAndHandle * kse;
uint8_t dts2; uint8_t dts2;
TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCall: evtcode >= 0xFF", );
TRACE_ASSERT(objectClass < TRACE_NCLASSES, "vTraceStoreKernelCallWithParam: objectClass >= TRACE_NCLASSES", );
TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "vTraceStoreKernelCallWithParam: Invalid value for objectNumber", );
if (RecorderDataPtr->recorderActive && handle_of_last_logged_task && if (RecorderDataPtr->recorderActive && handle_of_last_logged_task &&
(! inExcludedTask || nISRactive)) (! inExcludedTask || nISRactive))
{ {
if (recorder_busy)
{
/*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (3)");
return;
}
/* Check if the referenced object or the event code is excluded */ /* Check if the referenced object or the event code is excluded */
if (!prvTraceIsObjectExcluded(objectClass, objectNumber) && !GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode)) if (!uiTraceIsObjectExcluded(objectClass, objectNumber) && !TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
{ {
trcCRITICAL_SECTION_BEGIN(); trcCRITICAL_SECTION_BEGIN();
dts2 = (uint8_t)prvTraceGetDTS(0xFF); dts2 = (uint8_t)prvTraceGetDTS(0xFF);
@ -240,6 +215,35 @@ void vTraceStoreKernelCallWithParam(uint32_t evtcode,
} }
} }
/*******************************************************************************
* prvTraceGetParam
*
* Used for storing extra bytes for kernel calls with numeric parameters.
******************************************************************************/
static uint32_t prvTraceGetParam(uint32_t param_max, uint32_t param)
{
XPSEvent* xps;
TRACE_ASSERT(param_max == 0xFF || param_max == 0xFFFF, "prvTraceGetParam: Invalid value for param_max", param);
if (param <= param_max)
{
return param;
}
else
{
xps = (XPSEvent*) xTraceNextFreeEventBufferSlot();
if (xps != NULL)
{
xps->type = DIV_XPS;
xps->xps_8 = (param & (0xFF00 & ~param_max)) >> 8;
xps->xps_16 = (param & (0xFFFF0000 & ~param_max)) >> 16;
prvTraceUpdateCounters();
}
return param & param_max;
}
}
/******************************************************************************* /*******************************************************************************
* vTraceStoreKernelCallWithNumericParamOnly * vTraceStoreKernelCallWithNumericParamOnly
@ -247,20 +251,40 @@ void vTraceStoreKernelCallWithParam(uint32_t evtcode,
* Used for storing kernel calls with numeric parameters only. This is * Used for storing kernel calls with numeric parameters only. This is
* only used for traceTASK_DELAY and traceDELAY_UNTIL at the moment. * only used for traceTASK_DELAY and traceDELAY_UNTIL at the moment.
******************************************************************************/ ******************************************************************************/
void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint16_t param) void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
{ {
KernelCallWithParam16 * kse; KernelCallWithParam16 * kse;
uint8_t dts6; uint8_t dts6;
uint16_t restParam = 0;
TRACE_ASSERT(evtcode < 0xFF, "vTraceStoreKernelCallWithNumericParamOnly: Invalid value for evtcode", );
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 (!GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode)) if (!TRACE_GET_EVENT_CODE_FLAG_ISEXCLUDED(evtcode))
{ {
if (recorder_busy)
{
/*************************************************************************
* This may occur if a high-priority ISR is illegally using a system call,
* or creates a user event.
* Only ISRs that are disabled by TRACE_ENTER_CRITICAL_SECTION may use system calls
* or user events (see TRACE_MAX_SYSCALL_INTERRUPT_PRIORITY).
*************************************************************************/
vTraceError("Recorder busy - high priority ISR using syscall? (4)");
return;
}
trcCRITICAL_SECTION_BEGIN(); trcCRITICAL_SECTION_BEGIN();
dts6 = (uint8_t)prvTraceGetDTS(0xFF); dts6 = (uint8_t)prvTraceGetDTS(0xFF);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{
restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{ {
kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot(); kse = (KernelCallWithParam16*) xTraceNextFreeEventBufferSlot();
@ -268,28 +292,28 @@ void vTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint16_t param)
{ {
kse->dts = dts6; kse->dts = dts6;
kse->type = (uint8_t)evtcode; kse->type = (uint8_t)evtcode;
kse->param = param; kse->param = restParam;
prvTraceUpdateCounters(); prvTraceUpdateCounters();
} }
} }
}
trcCRITICAL_SECTION_END(); trcCRITICAL_SECTION_END();
} }
} }
} }
objectHandleType handle_of_running_task = 0;
/******************************************************************************* /*******************************************************************************
* vTraceStoreTaskswitch * vTraceStoreTaskswitch
* Called by the scheduler from the SWITCHED_OUT hook, and by uiTraceStart. * Called by the scheduler from the SWITCHED_OUT hook, and by uiTraceStart.
* At this point interrupts are assumed to be disabled! * At this point interrupts are assumed to be disabled!
******************************************************************************/ ******************************************************************************/
void vTraceStoreTaskswitch(void) void vTraceStoreTaskswitch(objectHandleType task_handle)
{ {
uint16_t dts3; uint16_t dts3;
TSEvent* ts; TSEvent* ts;
int8_t skipEvent = 0; int8_t skipEvent = 0;
uint32_t schedulerState = 0;
TRACE_ASSERT(task_handle <= NTask, "vTraceStoreTaskswitch: Invalid value for task_handle", );
/*************************************************************************** /***************************************************************************
This is used to detect if a high-priority ISRs is illegally using the This is used to detect if a high-priority ISRs is illegally using the
@ -298,9 +322,7 @@ void vTraceStoreTaskswitch(void)
If this is detected, it triggers a call to vTraceError with the error 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 "Illegal call to vTraceStoreISRBegin/End". If you get this error, it means
that the macro taskENTER_CRITICAL does not disable this ISR, as required. that the macro trcCRITICAL_SECTION_BEGIN does not disable this ISR, as required.
You can solve this by adjusting the value of the FreeRTOS constant
configMAX_SYSCALL_INTERRUPT_PRIORITY, which is defined in FreeRTOSConfig.h
Note: Setting recorder_busy is normally handled in our macros Note: Setting recorder_busy is normally handled in our macros
trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this trcCRITICAL_SECTION_BEGIN and _END, but is needed explicitly in this
@ -309,50 +331,25 @@ void vTraceStoreTaskswitch(void)
***************************************************************************/ ***************************************************************************/
recorder_busy++; recorder_busy++;
schedulerState = xTaskGetSchedulerState();
if (schedulerState == 0)
{
/* This occurs on the very first taskswitch event, generated by
vTraceStart and uiTraceStart if the scheduler is not yet started.
This creates a dummy "(startup)" task entry internally in the
recorder */
if (handle_of_running_task == 0)
{
handle_of_running_task = xTraceGetObjectHandle(TRACE_CLASS_TASK);
vTraceSetObjectName(TRACE_CLASS_TASK,
handle_of_running_task,
"(startup)");
vTraceSetPriorityProperty(TRACE_CLASS_TASK,
handle_of_running_task,
0);
}
}
else
{
handle_of_running_task =
(objectHandleType)uxTaskGetTaskNumber(xTaskGetCurrentTaskHandle());
}
/* Skip the event if the task has been excluded, using vTraceExcludeTask */ /* Skip the event if the task has been excluded, using vTraceExcludeTask */
if (GET_TASK_FLAG_ISEXCLUDED(handle_of_running_task)) if (TRACE_GET_TASK_FLAG_ISEXCLUDED(task_handle))
{ {
skipEvent = 1; skipEvent = 1;
inExcludedTask = 1; inExcludedTask = 1;
} }
else else
{
inExcludedTask = 0; inExcludedTask = 0;
}
/* Skip the event if the same task is scheduled */ /* Skip the event if the same task is scheduled */
if (handle_of_running_task == handle_of_last_logged_task) if (task_handle == handle_of_last_logged_task)
{ {
skipEvent = 1; skipEvent = 1;
} }
if (! RecorderDataPtr->recorderActive)
if (!RecorderDataPtr->recorderActive)
{ {
skipEvent = 1; skipEvent = 1;
} }
@ -364,7 +361,7 @@ void vTraceStoreTaskswitch(void)
if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
{ {
handle_of_last_logged_task = handle_of_running_task; handle_of_last_logged_task = task_handle;
ts = (TSEvent*)xTraceNextFreeEventBufferSlot(); ts = (TSEvent*)xTraceNextFreeEventBufferSlot();
if (ts != NULL) if (ts != NULL)
@ -411,7 +408,12 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
const char * name; const char * name;
traceLabel idx; traceLabel idx;
name = PROPERTY_NAME_GET(objectclass, handle); TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceStoreObjectNameOnCloseEvent: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceStoreObjectNameOnCloseEvent: Invalid value for handle", );
if (RecorderDataPtr->recorderActive)
{
name = TRACE_PROPERTY_NAME_GET(objectclass, handle);
idx = prvTraceOpenSymbol(name, 0); idx = prvTraceOpenSymbol(name, 0);
@ -424,7 +426,7 @@ void vTraceStoreObjectNameOnCloseEvent(objectHandleType handle,
ce->symbolIndex = idx; ce->symbolIndex = idx;
prvTraceUpdateCounters(); prvTraceUpdateCounters();
} }
}
} }
void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle, void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
@ -432,60 +434,69 @@ void vTraceStoreObjectPropertiesOnCloseEvent(objectHandleType handle,
{ {
ObjClosePropEvent * pe; ObjClosePropEvent * pe;
if (objectclass == TRACE_CLASS_ISR) TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceStoreObjectPropertiesOnCloseEvent: objectclass >= TRACE_NCLASSES", );
{ TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceStoreObjectPropertiesOnCloseEvent: Invalid value for handle", );
/* ISR handles should not be closed - never called for ISR */
return;
}
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();
if (pe != NULL) if (pe != NULL)
{ {
if (objectclass == TRACE_CLASS_TASK) if (objectclass == TRACE_CLASS_TASK)
{ {
pe->arg1 = PROPERTY_ACTOR_PRIORITY(objectclass, handle); pe->arg1 = TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle);
pe->arg2 = PROPERTY_TASK_IFE_SERVICECODE(handle); pe->arg2 = 0; // Legacy - IFE info removed.
pe->arg3 = PROPERTY_TASK_IFE_OBJHANDLE(handle); pe->arg3 = 0; // Legacy - IFE info removed.
PROPERTY_TASK_IFE_SERVICECODE(handle) = 0;
PROPERTY_TASK_IFE_OBJHANDLE(handle) = 0;
}else{ }else{
pe->arg1 = 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;
prvTraceUpdateCounters(); prvTraceUpdateCounters();
} }
}
} }
#endif #endif
void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value) void vTraceSetPriorityProperty(uint8_t objectclass, uint8_t id, uint8_t value)
{ {
PROPERTY_ACTOR_PRIORITY(objectclass, id) = value; TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceSetPriorityProperty: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceSetPriorityProperty: Invalid value for id", );
TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id) = value;
} }
uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id) uint8_t uiTraceGetPriorityProperty(uint8_t objectclass, uint8_t id)
{ {
return PROPERTY_ACTOR_PRIORITY(objectclass, id); TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetPriorityProperty: objectclass >= TRACE_NCLASSES", 0);
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetPriorityProperty: Invalid value for id", 0);
return TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id);
} }
void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value) void vTraceSetObjectState(uint8_t objectclass, uint8_t id, uint8_t value)
{ {
PROPERTY_OBJECT_STATE(objectclass, id) = value; TRACE_ASSERT(objectclass < TRACE_NCLASSES, "vTraceSetObjectState: objectclass >= TRACE_NCLASSES", );
TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "vTraceSetObjectState: Invalid value for id", );
TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value;
} }
void vTraceSetTaskInstanceFinished(objectHandleType handle) uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id)
{ {
#if (USE_IMPLICIT_IFE_RULES == 1) TRACE_ASSERT(objectclass < TRACE_NCLASSES, "uiTraceGetObjectState: objectclass >= TRACE_NCLASSES", 0);
if (PROPERTY_TASK_IFE_SERVICECODE(handle) == 0) TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceGetObjectState: Invalid value for id", 0);
{
PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle) = 0; return TRACE_PROPERTY_OBJECT_STATE(objectclass, id);
}
#endif
} }
uint8_t uiTraceGetObjectState(uint8_t objectclass, uint8_t id) void vTraceSetTaskInstanceFinished(objectHandleType handle)
{ {
return PROPERTY_OBJECT_STATE(objectclass, id); TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_TASK], "vTraceSetTaskInstanceFinished: Invalid value for handle", );
#if (USE_IMPLICIT_IFE_RULES == 1)
TRACE_PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle) = 0;
#endif
} }
#endif #endif

@ -0,0 +1,191 @@
/*******************************************************************************
* Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernelPort.c
*
* Kernel-specific functionality for FreeRTOS, used by the recorder library.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcHardwarePort.c/.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* Copyright Percepio AB, 2013.
* www.percepio.com
******************************************************************************/
#include "trcKernelPort.h"
#if (USE_TRACEALYZER_RECORDER == 1)
#include <stdint.h>
#include "task.h"
traceObjectClass TraceObjectClassTable[5] = {
TRACE_CLASS_QUEUE,
TRACE_CLASS_MUTEX,
TRACE_CLASS_SEMAPHORE,
TRACE_CLASS_SEMAPHORE,
TRACE_CLASS_MUTEX
};
extern unsigned char ucQueueGetQueueType(void*);
extern unsigned char ucQueueGetQueueNumber(void*);
objectHandleType prvTraceGetObjectNumber(void* handle)
{
return ucQueueGetQueueNumber(handle);
}
unsigned char prvTraceGetObjectType(void* handle)
{
return ucQueueGetQueueType(handle);
}
objectHandleType prvTraceGetTaskNumber(void* handle)
{
return (objectHandleType)uxTaskGetTaskNumber(handle);
}
void prvTraceEnterCritical()
{
taskENTER_CRITICAL();
}
void prvTraceExitCritical()
{
taskEXIT_CRITICAL();
}
unsigned char prvTraceIsSchedulerActive()
{
return xTaskGetSchedulerState() == taskSCHEDULER_RUNNING;
}
unsigned char prvTraceIsSchedulerSuspended()
{
return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;
}
unsigned char prvTraceIsSchedulerStarted()
{
return xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;
}
void* prvTraceGetCurrentTaskHandle()
{
return xTaskGetCurrentTaskHandle();
}
/* Initialization of the object property table */
void vTraceInitObjectPropertyTable()
{
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectClasses = TRACE_NCLASSES;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[0] = NQueue;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[1] = NSemaphore;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = NMutex;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = NTask;
RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = NISR;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = NameLenQueue;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = NameLenSemaphore;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = NameLenMutex;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = NameLenTask;
RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = NameLenISR;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[3] = PropertyTableSizeTask;
RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[3] = StartIndexTask;
RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;
RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;
}
/* Initialization of the handle mechanism, see e.g, xTraceGetObjectHandle */
void vTraceInitObjectHandleStack()
{
objectHandleStacks.indexOfNextAvailableHandle[0] = 0;
objectHandleStacks.indexOfNextAvailableHandle[1] = NQueue;
objectHandleStacks.indexOfNextAvailableHandle[2] = NQueue + NSemaphore;
objectHandleStacks.indexOfNextAvailableHandle[3] = NQueue + NSemaphore + NMutex;
objectHandleStacks.indexOfNextAvailableHandle[4] = NQueue + NSemaphore + NMutex + NTask;
objectHandleStacks.lowestIndexOfClass[0] = 0;
objectHandleStacks.lowestIndexOfClass[1] = NQueue;
objectHandleStacks.lowestIndexOfClass[2] = NQueue + NSemaphore;
objectHandleStacks.lowestIndexOfClass[3] = NQueue + NSemaphore + NMutex;
objectHandleStacks.lowestIndexOfClass[4] = NQueue + NSemaphore + NMutex + NTask;
objectHandleStacks.highestIndexOfClass[0] = NQueue - 1;
objectHandleStacks.highestIndexOfClass[1] = NQueue + NSemaphore - 1;
objectHandleStacks.highestIndexOfClass[2] = NQueue + NSemaphore + NMutex - 1;
objectHandleStacks.highestIndexOfClass[3] = NQueue + NSemaphore + NMutex + NTask - 1;
objectHandleStacks.highestIndexOfClass[4] = NQueue + NSemaphore + NMutex + NTask + NISR - 1;
}
/* Returns the "Not enough handles" error message for this object class */
const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)
{
switch(objectclass)
{
case TRACE_CLASS_TASK:
return "Not enough TASK handles - increase NTask in trcConfig.h";
case TRACE_CLASS_ISR:
return "Not enough ISR handles - increase NISR in trcConfig.h";
case TRACE_CLASS_SEMAPHORE:
return "Not enough SEMAPHORE handles - increase NSemaphore in trcConfig.h";
case TRACE_CLASS_MUTEX:
return "Not enough MUTEX handles - increase NMutex in trcConfig.h";
case TRACE_CLASS_QUEUE:
return "Not enough QUEUE handles - increase NQueue in trcConfig.h";
default:
return "pszTraceGetErrorHandles: Invalid objectclass!";
}
}
/* Returns the exclude state of the object */
uint8_t uiTraceIsObjectExcluded(traceObjectClass objectclass, objectHandleType handle)
{
TRACE_ASSERT(objectclass < TRACE_NCLASSES, "prvTraceIsObjectExcluded: objectclass >= TRACE_NCLASSES", 1);
TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], "uiTraceIsObjectExcluded: Invalid value for handle", 1);
switch(objectclass)
{
case TRACE_CLASS_TASK:
return TRACE_GET_TASK_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_SEMAPHORE:
return TRACE_GET_SEMAPHORE_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_MUTEX:
return TRACE_GET_MUTEX_FLAG_ISEXCLUDED(handle);
case TRACE_CLASS_QUEUE:
return TRACE_GET_QUEUE_FLAG_ISEXCLUDED(handle);
}
/* Must never reach */
return 1;
}
#endif

@ -0,0 +1,749 @@
/*******************************************************************************
* Tracealyzer v2.4.1 Recorder Library
* Percepio AB, www.percepio.com
*
* trcKernelPort.h
*
* Kernel-specific functionality for FreeRTOS, used by the recorder library.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcHardwarePort.c/.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* Copyright Percepio AB, 2013.
* www.percepio.com
******************************************************************************/
#ifndef TRCKERNELPORT_H_
#define TRCKERNELPORT_H_
#include "FreeRTOS.h" // Defines configUSE_TRACE_FACILITY
#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_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOS.h" */
#define TRACE_PERIPHERAL_CLOCK_HZ configPERIPHERAL_CLOCK_HZ /* Defined in "FreeRTOS.h" */
#define TRACE_TICK_RATE_HZ configTICK_RATE_HZ /* Defined in "FreeRTOS.h" */
#define TRACE_CPU_CLOCKS_PER_TICK configCPU_CLOCKS_PER_TICK /* Defined in "FreeRTOS.h" */
/************************************************************************/
/* KERNEL SPECIFIC OBJECT CONFIGURATION */
/************************************************************************/
#define TRACE_NCLASSES 5
#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_KERNEL_OBJECT_COUNT (NQueue + NSemaphore + NMutex + NTask + NISR)
/* 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)
/* 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
/* Number of bytes used by the object table */
#define TRACE_OBJECT_TABLE_SIZE StartIndexISR + NISR * PropertyTableSizeISR
/* Includes */
#include "trcTypes.h"
#include "trcConfig.h"
#include "trcKernelHooks.h"
#include "trcHardwarePort.h"
#include "trcBase.h"
#include "trcKernel.h"
#include "trcUser.h"
/* 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_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_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_FAILED (EVENTGROUP_KSE_FAILED) /*0x40*/
/* Failed send/give - timeout! */
#define EVENTGROUP_SEND_FAILED (EVENTGROUP_CREATE_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_SUCCESS (EVENTGROUP_PEEK_SUCCESS + 8) /*0x80*/
/* Other events - object class is implied: TASK */
#define EVENTGROUP_OTHERS (EVENTGROUP_DELETE_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*/
/* Not yet used */
#define EVENTGROUP_FTRACE_PLACEHOLDER (EVENTGROUP_OTHERS + 8) /*0x90*/
/* User events */
#define EVENTGROUP_USEREVENT (EVENTGROUP_FTRACE_PLACEHOLDER + 8) /*0x98*/
#define USER_EVENT (EVENTGROUP_USEREVENT + 0)
/* Allow for 0-15 arguments (the number of args is added to event code) */
#define USER_EVENT_LAST (EVENTGROUP_USEREVENT + 15) /*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*/
/************************************************************************/
/* 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 prvTraceEnterCritical(void);
void prvTraceExitCritical(void);
void* prvTraceGetCurrentTaskHandle(void);
/************************************************************************/
/* KERNEL SPECIFIC MACROS USED BY THE TRACE RECORDER */
/************************************************************************/
#define TRACE_MALLOC(size) pvPortMalloc(size)
#define TRACE_ENTER_CRITICAL_SECTION() prvTraceEnterCritical();
#define TRACE_EXIT_CRITICAL_SECTION() prvTraceExitCritical();
#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_OBJECT_NUMBER(CLASS, pxObject) (prvTraceGetObjectNumber(pxObject))
#define TRACE_SET_OBJECT_NUMBER(CLASS, pxObject) pxObject->ucQueueNumber = 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) (EVENTGROUP_##SERVICE##_##RESULT + TRACE_CLASS_TASK)
/************************************************************************/
/* KERNEL SPECIFIC WRAPPERS THAT SHOULD BE CALLED BY THE KERNEL */
/************************************************************************/
/* 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 == ( unsigned portBASE_TYPE ) pdTRUE || uxMissedTicks == 0) { trcKERNEL_HOOKS_INCREMENT_TICK(); } \
if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) 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() \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY, pxCurrentTCB, xTicksToDelay); \
trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(UNUSED,pxCurrentTCB); \
TRACE_EXIT_CRITICAL_SECTION();
/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */
#undef traceTASK_DELAY_UNTIL
#define traceTASK_DELAY_UNTIL() \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \
trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(UNUSED,pxCurrentTCB); \
TRACE_EXIT_CRITICAL_SECTION();
#if (INCLUDE_OBJECT_DELETE == 1)
/* Called on vTaskDelete */
#undef traceTASK_DELETE
#define traceTASK_DELETE( pxTaskToDelete ) \
trcKERNEL_HOOKS_TASK_DELETE(DELETE, pxTaskToDelete);
#endif
#if (INCLUDE_OBJECT_DELETE == 1)
/* Called on vQueueDelete */
#undef traceQUEUE_DELETE
#define traceQUEUE_DELETE( pxQueue ) \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_OBJECT_DELETE(DELETE, 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, pxNewTCB); \
}
/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */
#undef traceTASK_CREATE_FAILED
#define traceTASK_CREATE_FAILED() \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_TASK_CREATE_FAILED(CREATE); \
TRACE_EXIT_CRITICAL_SECTION();
/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */
#undef traceQUEUE_CREATE
#define traceQUEUE_CREATE( pxNewQueue )\
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_OBJECT_CREATE(CREATE, UNUSED, pxNewQueue); \
TRACE_EXIT_CRITICAL_SECTION();
/* Called in xQueueCreate, if the queue creation fails */
#undef traceQUEUE_CREATE_FAILED
#define traceQUEUE_CREATE_FAILED( queueType ) \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE, UNUSED, queueType); \
TRACE_EXIT_CRITICAL_SECTION();
/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */
#undef traceCREATE_MUTEX
#define traceCREATE_MUTEX( pxNewQueue ) \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_OBJECT_CREATE(CREATE, UNUSED, pxNewQueue); \
TRACE_EXIT_CRITICAL_SECTION();
/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */
#undef traceCREATE_MUTEX_FAILED
#define traceCREATE_MUTEX_FAILED() \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(CREATE, UNUSED, queueQUEUE_TYPE_MUTEX); \
TRACE_EXIT_CRITICAL_SECTION();
/* Called when the Mutex can not be given, since not holder */
#undef traceGIVE_MUTEX_RECURSIVE_FAILED
#define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxMutex); \
TRACE_EXIT_CRITICAL_SECTION();
/* Called when a message is sent to a queue */
#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)); /*For mutex, store the new owner rather than queue length */
/* Called when a message failed to be sent to a queue (timeout) */
#undef traceQUEUE_SEND_FAILED
#define traceQUEUE_SEND_FAILED( pxQueue ) \
TRACE_ENTER_CRITICAL_SECTION();\
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, FAILED, UNUSED, pxQueue); \
TRACE_EXIT_CRITICAL_SECTION();
/* 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 ) \
TRACE_ENTER_CRITICAL_SECTION();\
trcKERNEL_HOOKS_KERNEL_SERVICE(SEND, BLOCK, UNUSED, pxQueue); \
TRACE_EXIT_CRITICAL_SECTION();
/* 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)); /*For mutex, store the new owner rather than queue length */
/* Called when a receive operation on a queue fails (timeout) */
#undef traceQUEUE_RECEIVE_FAILED
#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \
TRACE_ENTER_CRITICAL_SECTION(); \
trcKERNEL_HOOKS_KERNEL_SERVICE(RECEIVE, FAILED, UNUSED, pxQueue); \
TRACE_EXIT_CRITICAL_SECTION();
/* 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 ) \
TRACE_ENTER_CRITICAL_SECTION(); \
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(UNUSED, pxQueue); \
} \
TRACE_EXIT_CRITICAL_SECTION();
/* 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);
/************************************************************************/
/* 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_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; \
}
#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; \
}
/* 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));
/* 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);
#endif
#endif /* TRCKERNELPORT_H_ */

@ -1,208 +0,0 @@
/*******************************************************************************
* FreeRTOS+Trace v2.3.0 Recorder Library
* Percepio AB, www.percepio.com
*
* trcPort.c
*
* Contains all portability issues of the trace recorder library.
* See also trcPort.h, where port-specific macros are defined.
*
* Terms of Use
* This software is copyright Percepio AB. The recorder library is free for
* use together with Percepio products. You may distribute the recorder library
* in its original form, including modifications in trcPort.c and trcPort.h
* given that these modification are clearly marked as your own modifications
* and documented in the initial comment section of these source files.
* This software is the intellectual property of Percepio AB and may not be
* sold or in other ways commercially redistributed without explicit written
* permission by Percepio AB.
*
* Disclaimer
* The trace tool and recorder library is being delivered to you AS IS and
* Percepio AB makes no warranty as to its use or performance. Percepio AB does
* not and cannot warrant the performance or results you may obtain by using the
* software or documentation. Percepio AB make no warranties, express or
* implied, as to noninfringement of third party rights, merchantability, or
* fitness for any particular purpose. In no event will Percepio AB, its
* technology partners, or distributors be liable to you for any consequential,
* incidental or special damages, including any lost profits or lost savings,
* even if a representative of Percepio AB has been advised of the possibility
* of such damages, or for any claim by any third party. Some jurisdictions do
* not allow the exclusion or limitation of incidental, consequential or special
* damages, or the exclusion of implied warranties or limitations on how long an
* implied warranty may last, so the above limitations may not apply to you.
*
* OFFER FROM PERCEPIO:
* For silicon companies and non-corporate FreeRTOS users (researchers, students
* , hobbyists or early-phase startups) we have an attractive offer:
* Provide a hardware timer port and get a FREE single-user licence for
* FreeRTOS+Trace Professional Edition. Read more about this offer at
* www.percepio.com or contact us directly at support@percepio.com.
*
* FreeRTOS+Trace is available as Free Edition and in two premium editions.
* You may use the premium features during 30 days for evaluation.
* Download FreeRTOS+Trace at http://www.percepio.com/products/downloads/
*
* Copyright Percepio AB, 2012.
* www.percepio.com
******************************************************************************/
#include "trcUser.h"
#if (configUSE_TRACE_FACILITY == 1)
#if (INCLUDE_SAVE_TO_FILE == 1)
static char* prvFileName = NULL;
#endif
/*******************************************************************************
* uiTraceTickCount
*
* This variable is updated by the traceTASK_INCREMENT_TICK macro in the
* FreeRTOS tick handler. This does not need to be modified when developing a
* new timer port. It is prefered to keep any timer port changes in the HWTC
* macro definitions, which typically give sufficient flexibility.
******************************************************************************/
uint32_t uiTraceTickCount = 0;
/******************************************************************************
* uiTracePortGetTimeStamp
*
* Returns the current time based on the HWTC macros which provide a hardware
* isolation layer towards the hardware timer/counter.
*
* The HWTC macros and uiTracePortGetTimeStamp is the main porting issue
* or the trace recorder library. Typically you should not need to change
* the code of uiTracePortGetTimeStamp if using the HWTC macros.
*
* OFFER FROM PERCEPIO:
* For silicon companies and non-corporate FreeRTOS users (researchers, students
* , hobbyists or early-phase startups) we have an attractive offer:
* Provide a hardware timer port and get a FREE single-user license for
* FreeRTOS+Trace Professional Edition. Read more about this offer at
* www.percepio.com or contact us directly at support@percepio.com.
******************************************************************************/
void uiTracePortGetTimeStamp(uint32_t *pTimestamp)
{
static uint32_t last_traceTickCount = 0;
static uint32_t last_hwtc_count = 0;
uint32_t traceTickCount = 0;
uint32_t hwtc_count = 0;
/* Retrieve HWTC_COUNT only once since the same value should be used all throughout this function. */
#if (HWTC_COUNT_DIRECTION == DIRECTION_INCREMENTING)
hwtc_count = HWTC_COUNT;
#elif (HWTC_COUNT_DIRECTION == DIRECTION_DECREMENTING)
hwtc_count = HWTC_PERIOD - HWTC_COUNT;
#else
Junk text to cause compiler error - HWTC_COUNT_DIRECTION is not set correctly!
Should be DIRECTION_INCREMENTING or DIRECTION_DECREMENTING
#endif
if (last_traceTickCount - uiTraceTickCount - 1 < 0x80000000)
{
/* This means last_traceTickCount is higher than uiTraceTickCount,
so we have previously compensated for a missed tick.
Therefore we use the last stored value because that is more accurate. */
traceTickCount = last_traceTickCount;
}
else
{
/* Business as usual */
traceTickCount = uiTraceTickCount;
}
/* Check for overflow. May occur if the update of uiTraceTickCount has been
delayed due to disabled interrupts. */
if (traceTickCount == last_traceTickCount && hwtc_count < last_hwtc_count)
{
/* A trace tick has occurred but not been executed by the kernel, so we compensate manually. */
traceTickCount++;
}
/* Check if the return address is OK, then we perform the calculation. */
if (pTimestamp)
{
/* Get timestamp from trace ticks. Scale down the period to avoid unwanted overflows. */
*pTimestamp = traceTickCount * (HWTC_PERIOD / HWTC_DIVISOR);
/* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / HWTC_DIVISOR. */
*pTimestamp += (hwtc_count + traceTickCount * (HWTC_PERIOD % HWTC_DIVISOR)) / HWTC_DIVISOR;
}
/* Store the previous values. */
last_traceTickCount = traceTickCount;
last_hwtc_count = hwtc_count;
}
/*******************************************************************************
* vTracePortEnd
*
* This function is called by the monitor when a recorder stop is detected.
* This is used by the Win32 port to store the trace to a file. The file path is
* set using vTracePortSetOutFile.
******************************************************************************/
void vTracePortEnd()
{
vTraceConsoleMessage("\n\r[FreeRTOS+Trace] Running vTracePortEnd.\n\r");
#if (WIN32_PORT_SAVE_WHEN_STOPPED == 1)
vTracePortSave();
#endif
#if (WIN32_PORT_EXIT_WHEN_STOPPED == 1)
/* In the FreeRTOS/Win32 demo, this allows for killing the application
when the recorder is stopped (e.g., when the buffer is full) */
system("pause");
exit(0);
#endif
}
#if (INCLUDE_SAVE_TO_FILE == 1)
/*******************************************************************************
* vTracePortSetOutFile
*
* Sets the filename/path used in vTracePortSave.
* This is set in a separate function, since the Win32 port calls vTracePortSave
* in vTracePortEnd if WIN32_PORT_SAVE_WHEN_STOPPED is set.
******************************************************************************/
void vTracePortSetOutFile(char* path)
{
prvFileName = path;
}
/*******************************************************************************
* vTracePortSave
*
* Saves the trace to a file on a local file system. The path is set in a
* separate function, vTracePortSetOutFile, since the Win32 port calls
* vTracePortSave in vTracePortEnd if WIN32_PORT_SAVE_WHEN_STOPPED is set.
******************************************************************************/
void vTracePortSave()
{
char buf[180];
FILE* f;
if (prvFileName == NULL)
{
prvFileName = "FreeRTOSPlusTrace.dump";
sprintf(buf, "No filename specified, using default \"%s\".", prvFileName);
vTraceConsoleMessage(buf);
}
fopen_s(&f, prvFileName, "wb");
if (f)
{
fwrite(RecorderDataPtr, sizeof(RecorderDataType), 1, f);
fclose(f);
sprintf(buf, "\n\r[FreeRTOS+Trace] Saved in: %s\n\r", prvFileName);
vTraceConsoleMessage(buf);
}
else
{
sprintf(buf, "\n\r[FreeRTOS+Trace] Failed to write to output file!\n\r");
vTraceConsoleMessage(buf);
}
}
#endif
#endif

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