diff options
author | Ming Yue <mingyue86010@gmail.com> | 2020-08-13 14:29:33 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-13 14:29:33 -0700 |
commit | d248555de5ec05260201e48a06f8252852c5fb18 (patch) | |
tree | 371807ff06428845017c19a42692118d62c71125 | |
parent | 70dcbe4527a45ab4fea6d58c016e7d3032f31e8c (diff) | |
download | freertos-git-d248555de5ec05260201e48a06f8252852c5fb18.tar.gz |
Update #169 -- Percepio Tracealyzer Recorder v4.3.11 (#201)
* * Pull Request for Percepio Tracealyzer Recorder v4.3.11
* Update Tracealyzer demo config file.
Co-authored-by: Erik Tamlin <erik.tamlin@percepio.com>
38 files changed, 16058 insertions, 13440 deletions
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcConfig.h index 3a6fab81b..0989814e6 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcConfig.h +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcConfig.h @@ -98,22 +98,32 @@ extern "C" { * TRC_RECORDER_MODE_STREAMING
******************************************************************************/
#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_SNAPSHOT
+
/******************************************************************************
* TRC_CFG_FREERTOS_VERSION
*
* Specify what version of FreeRTOS that is used (don't change unless using the
* trace recorder library with an older version of FreeRTOS).
*
- * TRC_FREERTOS_VERSION_7_3 If using FreeRTOS v7.3.x
- * TRC_FREERTOS_VERSION_7_4 If using FreeRTOS v7.4.x
- * TRC_FREERTOS_VERSION_7_5_OR_7_6 If using FreeRTOS v7.5.0 - v7.6.0
- * TRC_FREERTOS_VERSION_8_X If using FreeRTOS v8.X.X
- * TRC_FREERTOS_VERSION_9_0_0 If using FreeRTOS v9.0.0
- * TRC_FREERTOS_VERSION_9_0_1 If using FreeRTOS v9.0.1
- * TRC_FREERTOS_VERSION_9_0_2 If using FreeRTOS v9.0.2
- * TRC_FREERTOS_VERSION_10_0_0 If using FreeRTOS v10.0.0 or later
+ * TRC_FREERTOS_VERSION_7_3_X If using FreeRTOS v7.3.X
+ * TRC_FREERTOS_VERSION_7_4_X If using FreeRTOS v7.4.X
+ * TRC_FREERTOS_VERSION_7_5_X If using FreeRTOS v7.5.X
+ * TRC_FREERTOS_VERSION_7_6_X If using FreeRTOS v7.6.X
+ * TRC_FREERTOS_VERSION_8_X_X If using FreeRTOS v8.X.X
+ * TRC_FREERTOS_VERSION_9_0_0 If using FreeRTOS v9.0.0
+ * TRC_FREERTOS_VERSION_9_0_1 If using FreeRTOS v9.0.1
+ * TRC_FREERTOS_VERSION_9_0_2 If using FreeRTOS v9.0.2
+ * TRC_FREERTOS_VERSION_10_0_0 If using FreeRTOS v10.0.0
+ * TRC_FREERTOS_VERSION_10_0_1 If using FreeRTOS v10.0.1
+ * TRC_FREERTOS_VERSION_10_1_0 If using FreeRTOS v10.1.0
+ * TRC_FREERTOS_VERSION_10_1_1 If using FreeRTOS v10.1.1
+ * TRC_FREERTOS_VERSION_10_2_0 If using FreeRTOS v10.2.0
+ * TRC_FREERTOS_VERSION_10_2_1 If using FreeRTOS v10.2.1
+ * TRC_FREERTOS_VERSION_10_3_0 If using FreeRTOS v10.3.0
+ * TRC_FREERTOS_VERSION_10_3_1 If using FreeRTOS v10.3.1
+ * TRC_FREERTOS_VERSION_10_4_0 If using FreeRTOS v10.4.0 or later
*****************************************************************************/
-#define TRC_CFG_FREERTOS_VERSION TRC_FREERTOS_VERSION_10_0_0
+#define TRC_CFG_FREERTOS_VERSION TRC_FREERTOS_VERSION_10_3_1
/*******************************************************************************
* TRC_CFG_SCHEDULING_ONLY
@@ -144,13 +154,13 @@ extern "C" { *
* Macro which should be defined as either zero (0) or one (1).
*
- * If this is zero (0), all code related to User Events is excluded in order
+ * If this is zero (0), all code related to User Events is excluded in order
* to reduce code size. Any attempts of storing User Events are then silently
* ignored.
*
- * User Events are application-generated events, like "printf" but for the
- * trace log, generated using vTracePrint and vTracePrintF.
- * The formatting is done on host-side, by Tracealyzer. User Events are
+ * User Events are application-generated events, like "printf" but for the
+ * trace log, generated using vTracePrint and vTracePrintF.
+ * The formatting is done on host-side, by Tracealyzer. User Events are
* therefore much faster than a console printf and can often be used
* in timing critical code without problems.
*
@@ -170,7 +180,14 @@ extern "C" { * Macro which should be defined as either zero (0) or one (1).
*
* If this is zero (0), the code for recording Interrupt Service Routines is
- * excluded, in order to reduce code size.
+ * excluded, in order to reduce code size. This means that any calls to
+ * vTraceStoreISRBegin/vTraceStoreISREnd will be ignored.
+ * This does not completely disable ISR tracing, in cases where an ISR is
+ * calling a traced kernel service. These events will still be recorded and
+ * show up in anonymous ISR instances in Tracealyzer, with names such as
+ * "ISR sending to <queue name>".
+ * To disable such tracing, please refer to vTraceSetFilterGroup and
+ * vTraceSetFilterMask.
*
* Default value is 1.
*
@@ -234,7 +251,7 @@ extern "C" { *
* Macro which should be defined as either zero (0) or one (1).
*
- * If this is zero (0), the trace will exclude any "pending function call"
+ * If this is zero (0), the trace will exclude any "pending function call"
* events, such as xTimerPendFunctionCall().
*
* Default value is 0 since dependent on timers.c
@@ -253,6 +270,90 @@ extern "C" { ******************************************************************************/
#define TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS 0
+ /******************************************************************************
+ * TRC_CFG_ENABLE_STACK_MONITOR
+ *
+ * If enabled (1), the recorder periodically reports the unused stack space of
+ * all active tasks.
+ * The stack monitoring runs in the Tracealyzer Control task, TzCtrl. This task
+ * is always created by the recorder when in streaming mode.
+ * In snapshot mode, the TzCtrl task is only used for stack monitoring and is
+ * not created unless this is enabled.
+ *****************************************************************************/
+#define TRC_CFG_ENABLE_STACK_MONITOR 0
+
+ /******************************************************************************
+ * TRC_CFG_STACK_MONITOR_MAX_TASKS
+ *
+ * Macro which should be defined as a non-zero integer value.
+ *
+ * This controls how many tasks that can be monitored by the stack monitor.
+ * If this is too small, some tasks will be excluded and a warning is shown.
+ *
+ * Default value is 10.
+ *****************************************************************************/
+#define TRC_CFG_STACK_MONITOR_MAX_TASKS 10
+
+ /******************************************************************************
+ * TRC_CFG_STACK_MONITOR_MAX_REPORTS
+ *
+ * Macro which should be defined as a non-zero integer value.
+ *
+ * This defines how many tasks that will be subject to stack usage analysis for
+ * each execution of the Tracealyzer Control task (TzCtrl). Note that the stack
+ * monitoring cycles between the tasks, so this does not affect WHICH tasks that
+ * are monitored, but HOW OFTEN each task stack is analyzed.
+ *
+ * This setting can be combined with TRC_CFG_CTRL_TASK_DELAY to tune the
+ * frequency of the stack monitoring. This is motivated since the stack analysis
+ * can take some time to execute.
+ * However, note that the stack analysis runs in a separate task (TzCtrl) that
+ * can be executed on low priority. This way, you can avoid that the stack
+ * analysis disturbs any time-sensitive tasks.
+ *
+ * Default value is 1.
+ *****************************************************************************/
+#define TRC_CFG_STACK_MONITOR_MAX_REPORTS 1
+
+ /*******************************************************************************
+ * Configuration Macro: TRC_CFG_CTRL_TASK_PRIORITY
+ *
+ * The scheduling priority of the Tracealyzer Control (TzCtrl) task.
+ *
+ * In streaming mode, TzCtrl is used to receive start/stop commands from
+ * Tracealyzer and in some cases also to transmit the trace data (for stream
+ * ports that uses the internal buffer, like TCP/IP). For such stream ports,
+ * make sure the TzCtrl priority is high enough to ensure reliable periodic
+ * execution and transfer of the data, but low enough to avoid disturbing any
+ * time-sensitive functions.
+ *
+ * In Snapshot mode, TzCtrl is only used for the stack usage monitoring and is
+ * not created if stack monitoring is disabled. TRC_CFG_CTRL_TASK_PRIORITY should
+ * be low, to avoid disturbing any time-sensitive tasks.
+ ******************************************************************************/
+#define TRC_CFG_CTRL_TASK_PRIORITY 1
+
+ /*******************************************************************************
+ * Configuration Macro: TRC_CFG_CTRL_TASK_DELAY
+ *
+ * The delay between loops of the TzCtrl task (see TRC_CFG_CTRL_TASK_PRIORITY),
+ * which affects the frequency of the stack monitoring.
+ *
+ * In streaming mode, this also affects the trace data transfer if you are using
+ * a stream port leveraging the internal buffer (like TCP/IP). A shorter delay
+ * increases the CPU load of TzCtrl somewhat, but may improve the performance of
+ * of the trace streaming, especially if the trace buffer is small.
+ ******************************************************************************/
+#define TRC_CFG_CTRL_TASK_DELAY 10
+
+ /*******************************************************************************
+ * Configuration Macro: TRC_CFG_CTRL_TASK_STACK_SIZE
+ *
+ * The stack size of the Tracealyzer Control (TzCtrl) task.
+ * See TRC_CFG_CTRL_TASK_PRIORITY for further information about TzCtrl.
+ ******************************************************************************/
+#define TRC_CFG_CTRL_TASK_STACK_SIZE (configMINIMAL_STACK_SIZE * 2)
+
/*******************************************************************************
* Configuration Macro: TRC_CFG_RECORDER_BUFFER_ALLOCATION
*
@@ -286,6 +387,16 @@ extern "C" { *****************************************************************************/
#define TRC_CFG_MAX_ISR_NESTING 8
+/******************************************************************************
+ * TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND
+ *
+ * When using FreeRTOS v10.3.0 or v10.3.1, please make sure that the trace
+ * point in prvNotifyQueueSetContainer() in queue.c is renamed from
+ * traceQUEUE_SEND to traceQUEUE_SET_SEND in order to tell them apart from
+ * other traceQUEUE_SEND trace points. Then set this to TRC_ACKNOWLEDGED.
+ *****************************************************************************/
+#define TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND TRC_ACKNOWLEDGED /* 0 or TRC_ACKNOWLEDGED */
+
/* Specific configuration, depending on Streaming/Snapshot mode */
#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
#include "trcSnapshotConfig.h"
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/aws_secure_sockets.tzext.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/aws_secure_sockets.tzext.h new file mode 100644 index 000000000..f2ebf74c0 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/aws_secure_sockets.tzext.h @@ -0,0 +1,170 @@ +/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.2.0 + * Percepio AB, www.percepio.com + * + * aws_secure_socket.tzext.h + * + * An example of a Tracealyzer extension for tracing API calls, in this case + * for tracing selected functions in Amazon FreeRTOS/aws_secure_sockets. + * See trcExtensions.h for information on how to use this. + * + * To create your own extension, first make sure to read the documentation + * in trcExtensions.h. Then, to create an extension header file like this + * one, you need to provide: + * + * - Extension Definitions - name and event codes of the extensions. + * + * - Trace Wrappers - calls the original function and traces the event. + * + * - Function Redefinitions - changes the function calls to the trace wrappers. + * + * See the below comments for details about these definitions. Note that you + * also need a matching .xml file for Tracealyzer to understand the data. + * See trcExtensions.h for further information. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef _AWS_SECURE_SOCKETS_TZEXT_H +#define _AWS_SECURE_SOCKETS_TZEXT_H + +/***** Extension Definitions *****/ + +/****************************************************************************** + * <EXTENSIONPREFIX>_NAME + * The name of the extension as a string constant. This name is used by the + * Tracealyzer host application to find the right XML file for interpreting + * the events. Assuming the extension name is "aws_secure_sockets", Tracealyzer + * will look for an XML file named "aws_secure_sockets-<VERSION>.xml", first in + * the folder of the current trace file, next in the Tracealyzer 4/cfg folder. + * For the VERSION part, see the TRC_EXT_<ExtName>_VERSION macros below. + * + * Note: The extension name displayed in Tracealyzer is defined in the XML file + * in the EventGroup element (e.g. <EventGroup name="SOCKETS">) + * + *****************************************************************************/ +#define TRC_EXT_SOCKETS_NAME "aws_secure_sockets" + +/****************************************************************************** + * <EXTENSIONPREFIX>_VERSION_MAJOR + * <EXTENSIONPREFIX>_VERSION_MINOR + * <EXTENSIONPREFIX>_VERSION_PATCH + * + * The version code of the extension (MAJOR.MINOR.PATCH) + * + * If you increment the version code when modifying an extension, you can still + * show old traces recorded using an earlier version of the extension. + * + * Assuming the extension name is "aws_secure_sockets", and the below version + * codes are 1 (MAJOR), 2 (MINOR), 3 (PATCH), Tracealyzer will assume the + * corresponding XML file is named "aws_secure_sockets-v1.2.3.xml". So if then + * view a trace recorded with extension version 1.2.2, those traces will look + * for "aws_secure_sockets-v1.2.2.xml" instead. + * + * Note that major and minor are stored as 8 bit values, while patch is stored + * using 16 bits. They are treated as unsigned integers, so the maximum values + * are 256, 256 and 65535. + *****************************************************************************/ +#define TRC_EXT_SOCKETS_VERSION_MAJOR 1 + +#define TRC_EXT_SOCKETS_VERSION_MINOR 0 + +#define TRC_EXT_SOCKETS_VERSION_PATCH 0 + + +/****************************************************************************** + * <EXTENSIONPREFIX>_<EVENTCODE> + * The event codes used in the trace wrapper functions. Important that these + * are relative to <PREFIX>_FIRST. + *****************************************************************************/ +#define EVENTCODE_SOCKETS_Connect (TRC_EXT_BASECODE + 0) + +#define EVENTCODE_SOCKETS_Send (TRC_EXT_BASECODE + 1) + +#define EVENTCODE_SOCKETS_Recv (TRC_EXT_BASECODE + 2) + +/****************************************************************************** + * <EXTENSIONPREFIX>_COUNT + * The number of event codes used by this extension. Should be at least 1. + * Tracealyzer allows for events codes up to 4095. + *****************************************************************************/ +#define TRC_EXT_SOCKETS_COUNT 2 + + +/***** Trace Wrappers *****/ + +#include "aws_secure_sockets.h" /* Including the original header file, so that custom data types are understood. */ + +static inline int32_t SOCKETS_Connect__trace( Socket_t xSocket, SocketsSockaddr_t * pxAddress, Socklen_t xAddressLength ) +{ + int32_t ret = SOCKETS_Connect(xSocket, pxAddress, xAddressLength); + + // Note: The host-side xml file assumes that ret == 0 means OK, otherwise timeout/error. + prvTraceStoreEvent3(EVENTCODE_SOCKETS_Connect, (uint32_t)xSocket, (uint32_t)pxAddress->ulAddress, (uint32_t)ret); + + return ret; +} + +static inline int32_t SOCKETS_Send__trace( Socket_t xSocket, const void * pvBuffer, size_t xDataLength, uint32_t ulFlags ) +{ + int32_t ret = SOCKETS_Send(xSocket, pvBuffer, xDataLength, ulFlags); + + // Note: The host-side xml file assumes that ret == 0 means OK, otherwise timeout/error. + prvTraceStoreEvent2(EVENTCODE_SOCKETS_Send, (uint32_t)xSocket, (uint32_t)ret); + + return ret; +} + + +static inline int32_t SOCKETS_Recv__trace( Socket_t xSocket, void * pvBuffer, size_t xBufferLength, uint32_t ulFlags ) +{ + int32_t ret = SOCKETS_Recv(xSocket, pvBuffer, xBufferLength, ulFlags); + + // Note: The host-side xml file assumes that ret == 0 means OK, otherwise timeout/error. + prvTraceStoreEvent2(EVENTCODE_SOCKETS_Recv, (uint32_t)xSocket, (uint32_t)ret); + + return ret; +} + +/***** Function Redefinitions *****/ + +#define SOCKETS_Connect SOCKETS_Connect__trace + +#define SOCKETS_Send SOCKETS_Send__trace + +#define SOCKETS_Recv SOCKETS_Recv__trace + +#endif /* _AWS_SECURE_SOCKETS_TZEXT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/aws_wifi.tzext.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/aws_wifi.tzext.h new file mode 100644 index 000000000..238eacaff --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/aws_wifi.tzext.h @@ -0,0 +1,169 @@ +/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.2.0 + * Percepio AB, www.percepio.com + * + * aws_secure_socket.tzext.h + * + * An example of a Tracealyzer extension for tracing API calls, in this case + * for tracing selected functions in Amazon FreeRTOS/aws_wifi. + * See trcExtensions.h for information on how to use this. + * + * To create your own extension, first make sure to read the documentation + * in trcExtensions.h. Then, to create an extension header file like this + * one, you need to provide: + * + * - Extension Definitions - name and event codes of the extensions. + * + * - Trace Wrappers - calls the original function and traces the event. + * + * - Function Redefinitions - changes the function calls to the trace wrappers. + * + * See the below comments for details about these definitions. Note that you + * also need a matching .xml file for Tracealyzer to understand the data. + * See trcExtensions.h for further information. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef _AWS_WIFI_TZEXT_H +#define _AWS_WIFI_TZEXT_H + +/***** Extension Definitions (must use the same prefix!) *****/ + +/****************************************************************************** + * <EXTENSIONPREFIX>_NAME + * The name of the extension as a string constant. This name is used by the + * Tracealyzer host application to find the right XML file for interpreting + * the events. Assuming the extension name is "aws_secure_sockets", Tracealyzer + * will look for an XML file named "aws_secure_sockets-<VERSION>.xml", first in + * the folder of the current trace file, next in the Tracealyzer 4/cfg folder. + * For the VERSION part, see the TRC_EXT_<ExtName>_VERSION macros below. + * + * Note: The extension name displayed in Tracealyzer is defined in the XML file + * in the EventGroup element (e.g. <EventGroup name="SOCKETS">) + * + *****************************************************************************/ +#define TRC_EXT_WIFI_NAME "aws_wifi" + +/****************************************************************************** + * <EXTENSIONPREFIX>_VERSION_MAJOR + * <EXTENSIONPREFIX>_VERSION_MINOR + * <EXTENSIONPREFIX>_VERSION_PATCH + * + * The version code of the extension (MAJOR.MINOR.PATCH) + * + * If you increment the version code when modifying an extension, you can still + * show old traces recorded using an earlier version of the extension. + * + * Assuming the extension name is "aws_secure_sockets", and the below version + * codes are 1 (MAJOR), 2 (MINOR), 3 (PATCH), Tracealyzer will assume the + * corresponding XML file is named "aws_secure_sockets-v1.2.3.xml". So if then + * view a trace recorded with extension version 1.2.2, those traces will look + * for "aws_secure_sockets-v1.2.2.xml" instead. + * + * Note that major and minor are stored as 8 bit values, while patch is stored + * using 16 bits. They are treated as unsigned integers, so the maximum values + * are 256, 256 and 65535. + *****************************************************************************/ +#define TRC_EXT_WIFI_VERSION_MAJOR 1 + +#define TRC_EXT_WIFI_VERSION_MINOR 0 + +#define TRC_EXT_WIFI_VERSION_PATCH 0 + +/****************************************************************************** + * <EXTENSIONPREFIX>_<EVENTCODE> + * The event codes used in the trace wrapper functions. Important that these + * are relative to <PREFIX>_FIRST. + *****************************************************************************/ +#define EVENTCODE_WIFI_On (TRC_EXT_BASECODE + 0) + +#define EVENTCODE_WIFI_Off (TRC_EXT_BASECODE + 1) + +#define EVENTCODE_WIFI_ConnectAP (TRC_EXT_BASECODE + 2) + +/****************************************************************************** + * <EXTENSIONPREFIX>_COUNT + * The number of event codes used by this extension. Should be at least 1. + * Tracealyzer allows for events codes up to 4095. + *****************************************************************************/ +#define TRC_EXT_WIFI_COUNT 3 + + +/***** Trace Wrappers *****/ + +#include "aws_wifi.h" /* Including the original header file, so that custom data types are understood. */ + +static inline WIFIReturnCode_t WIFI_On__trace( void ) +{ + WIFIReturnCode_t ret = WIFI_On(); + + // Note: The host-side xml file assumes that ret == 0 means OK, otherwise timeout/error. + prvTraceStoreEvent1(EVENTCODE_WIFI_On, (uint32_t)ret); + + return ret; +} + + static inline WIFIReturnCode_t WIFI_Off__trace( void ) + { + WIFIReturnCode_t ret = WIFI_Off(); + + // Note: The host-side xml file assumes that ret == 0 means OK, otherwise timeout/error. + prvTraceStoreEvent1(EVENTCODE_WIFI_Off, (uint32_t)ret); + + return ret; + } + + static inline WIFIReturnCode_t WIFI_ConnectAP__trace( const WIFINetworkParams_t * const pxNetworkParams ) + { + WIFIReturnCode_t ret = WIFI_ConnectAP(pxNetworkParams); + + // Note: The host-side xml file assumes that ret == 0 means OK, otherwise timeout/error. + + prvTraceStoreStringEvent(2, EVENTCODE_WIFI_ConnectAP, pxNetworkParams->pcSSID, pxNetworkParams->xSecurity, ret); + + return ret; + } + +/***** Function Redefinitions *****/ + +#define WIFI_On WIFI_On__trace + +#define WIFI_Off WIFI_Off__trace + +#define WIFI_ConnectAP WIFI_ConnectAP__trace + +#endif /* _AWS_SECURE_SOCKETS2_TZEXT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcExtensions.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcExtensions.h new file mode 100644 index 000000000..dfcdfcea7 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcExtensions.h @@ -0,0 +1,422 @@ +/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcExtensions.h + * + * The extension interface of the recorder library, allowing for tracing + * function calls to any API without modifications. All that is needed is a + * single #include line in the .c files calling the API. + * + * This can be used to provide more detailed traces, including calls to e.g. + * middleware, drivers or important APIs in your application code. This can be + * applied selectively to specified functions and may include selected + * parameters as well as the return value. + * + * Unlike the "User Event" concept, an extension is intended for systematic use + * and can benefit from all powerful features in Tracealyzer via host-side XML + * files that configure how Tracealyzer should interpret each event. + * + * Extensions are self-contained and easy to integrate, which makes them + * convenient for distribution. Software vendors can thus develop such + * extensions and provide trace support for their users. + * + * An extension consists of two files: + * + * - An extension header file (e.g. "api.tzext.h") - this defines how to + * trace the API function calls. + * + * - An XML file for the Tracealyzer application (e.g. "api-v1.0.0.xml"). + * This needs to match the tracing setup in your extension header file. + * + * + * USAGE + * + * This description assumes you already have the extension files for the APIs you + * like to trace. To include them, follow these steps: + * + * 1. Update trcExtensions.h with respect to: + * + * 1.1. TRC_CFG_EXTENSION_COUNT: The number of extensions to enable (max 4). + * + * 1.2. The name(s) of the extension header file(s) to include. + * + * 1.3. The Extension Prefix, i.e., the first part of the definition names + * used in each header file. + * + * 2. Add #include "trcExtensions.h" in all .c files calling the API: + * + * #include ... + * #include "api.h" // The API you like to trace + * #include ... + * #include "trcExtensions.h" + * + * We recommend to put this as the LAST #include statement. + * + * HOWEVER, don't include "trcExtensions.h" in the .c files containing the + * functions you intend to trace. The compiler will then complain about + * multiple definitions of the trace wrapper function. + * + * 3. Copy the extension XML file to the "Tracealyzer 4/cfg" folder. + * On Windows this is typically + * + * C:\Program Files\Percepio\Tracealyzer 4\cfg + * + * + * HOW IT WORKS + * + * By including "trcExtensions.h" in your .c files, the preprocessor will + * redefine all calls of the functions specified in the extension header file. + * Calls to those functions will now instead call the "trace wrapper functions" + * defined in the extension header. The trace wrapper functions then call the + * original function as well as the trace recorder library. + * + * call foo(a) ----> foo__trace(a) -----> foo(a) + * -----> trace recorder library + * + * Note that the trace wrapper function should have the same declaration as the + * original function (apart from the name) and also returns any return value + * back to the original caller. So functionally this is completely transparent. + * + * This works also for calls via function pointers, as the assignments of the + * function pointers will be affected, so the function pointers will point to + * the trace wrapper function. + * + * It even works when calling binary libraries, since only the calling code + * is modified, not the API itself. + * + * Extensions include a version code (Major.Minor.Patch), which is registered + * in the trace and also part of the XML file name. This way, Tracealyzer + * automatically finds the matching XML file, even if you open a old trace + * recorded using a earlier version of the extension (e.g. if the API has + * changed). + * + * LIMITATIONS + * + * The main limitation of this automatic approach is that it only allows for + * tracing call between different .c files. Moreover, you can't trace multiple + * APIs with calls between them. This since the calling file must include + * trcExtensions.h, while the called file must NOT include this. + * + * It is however possible to get around this limitation. You need to add + * #undef lines for each affected function to locally disable the redefinition, + * and modify each function call to instead call the trace wrapper function. + * + * #include "trcExtensions.h" + * #undef foo + * ... + * void foo(int a) + * { + * ... + * } + * ... + * foo__trace(a); // in another function - call foo and trace it + * + * These changes can remain in your code if you like, as the trace wrappers + * works even if the recorder is disabled. + * + * MAKING YOUR OWN EXTENSIONS + * + * Examples are found in the extensions directory. We recommend that you start + * by looking at aws_secure_sockets files (.h and .xml) that provides a basic + * example. The aws_wifi files provides a more advanced example. + * The header files include detailed documentation about how to design them, + * + * The XML files should have the same name as specified in the NAME property + * in the header file, followed by the version, i.e. + * + * <NAME>-v<VERSION_MAJOR>.<<VERSION_MINOR>.<VERSION_PATCH>.xml + * + * Documentation for the XML file format is not yet available, but is under + * development. + * + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRCEXTENSIONS_H_ +#define TRCEXTENSIONS_H_ + +#include "trcRecorder.h" + +/****************************************************************************** + * TRC_CFG_EXTENSION_COUNT + * + * Defines the number of extensions included in the trace. Maximum 4 extensions + * can be included. + * + * Default value is 0 (extension support disabled). + * + *****************************************************************************/ +#define TRC_CFG_EXTENSION_COUNT 0 + +/****************************************************************************** + * TRC_CFG_EXT_MAX_NAME_LEN + * + * Defines the maximum length of extension name(s), i.e. the <EXTENSION>_NAME + * macro(s) in trcExtensions.h. + * + * This value should will by rounded up to the nearest multiple of 4, and must + * not be zero. To disable extension support, see TRC_CFG_EXTENSION_COUNT. + * + * It is important that this setting is large enough so extension names are + * not truncated, otherwise the host-side Tracealyzer application won't be able + * to find the corresponding XML file. + * + * You may adjust this to reduce memory usage, or increase it to allow for + * longer extension names. + * + * Default value is 20. + *****************************************************************************/ +#define TRC_CFG_EXT_MAX_NAME_LEN 20 + +/****************************************************************************** + * TRC_EXTENSION_EVENTCODE_BASE + * + * The first event code used for the Extension system. This will be the first + * event code of the first extension, and other event codes are relative to + * this. This can be modified but this is normally not required. + *****************************************************************************/ +#define TRC_EXTENSION_EVENTCODE_BASE 256 + +/*** Included Extensions ****************************************************** + * + * Below you specify what extensions to include. For each + * extension you must define: + * + * - HEADER: The header file that defines the trace extension. + * + * - EXTENSION_PREFIX: The first part of the HEADER definition names. + * + *****************************************************************************/ +#define TRC_EXT1_HEADER "aws_secure_sockets.tzext.h" +#define TRC_EXT1_PREFIX TRC_EXT_SOCKETS + +#define TRC_EXT2_HEADER "aws_wifi.tzext.h" +#define TRC_EXT2_PREFIX TRC_EXT_WIFI + +#define TRC_EXT3_HEADER "Here you specify the header file for Extensions 3." +#define TRC_EXT3_PREFIX NOT_DEFINED + +#define TRC_EXT4_HEADER "Here you specify the header file for Extensions 4." +#define TRC_EXT4_PREFIX NOT_DEFINED + +/*** Don't modify below ******************************************************/ + +#define ROUNDUP4(n) (4*((n+3)/4)) + +typedef struct{ + uint16_t firstEventCode; + uint16_t lastEventCode; + uint16_t patchVersion; + uint8_t minorVersion; + uint8_t majorVersion; + char name[ROUNDUP4(TRC_CFG_EXT_MAX_NAME_LEN)]; +} PSFExtensionEntryType; + +typedef struct{ + uint16_t extensionEntryCount; + uint16_t baseEventCode; +#if (TRC_CFG_EXTENSION_COUNT > 0) + uint8_t extensionEntryNameMaxLength; + uint8_t extensionEntrySize; + PSFExtensionEntryType extension[TRC_CFG_EXTENSION_COUNT]; +#endif +} PSFExtensionInfoType; + + +extern PSFExtensionInfoType PSFExtensionInfo; + +#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) +#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ + +#define TRC_EXT_BASECODE (PSFExtensionInfo.extension[TRC_EXT_NUMBER-1].firstEventCode) + +#if (TRC_CFG_EXTENSION_COUNT >= 1) + #ifdef TRC_EXT1_HEADER + #define TRC_EXT_NUMBER 1 + #include TRC_EXT1_HEADER + #undef TRC_EXT_NUMBER + #endif +#endif + +#if (TRC_CFG_EXTENSION_COUNT >= 2) + #ifdef TRC_EXT2_HEADER + #define TRC_EXT_NUMBER 2 + #include TRC_EXT2_HEADER + #undef TRC_EXT_NUMBER + #endif +#endif + +#if (TRC_CFG_EXTENSION_COUNT >= 3) + #ifdef TRC_EXT3_HEADER + #define TRC_EXT_NUMBER 3 + #include TRC_EXT3_HEADER + #undef TRC_EXT_NUMBER + #endif +#endif + +#if (TRC_CFG_EXTENSION_COUNT == 4) + #ifdef TRC_EXT3_HEADER + #define TRC_EXT_NUMBER 4 + #include TRC_EXT4_HEADER + #undef TRC_EXT_NUMBER + #endif +#endif + +#define TRC_EXT1_COUNT CAT(TRC_EXT1_PREFIX, _COUNT) +#define TRC_EXT2_COUNT CAT(TRC_EXT2_PREFIX, _COUNT) +#define TRC_EXT3_COUNT CAT(TRC_EXT3_PREFIX, _COUNT) +#define TRC_EXT4_COUNT CAT(TRC_EXT4_PREFIX, _COUNT) + +#define TRC_EXT1_NAME CAT(TRC_EXT1_PREFIX, _NAME) +#define TRC_EXT2_NAME CAT(TRC_EXT2_PREFIX, _NAME) +#define TRC_EXT3_NAME CAT(TRC_EXT3_PREFIX, _NAME) +#define TRC_EXT4_NAME CAT(TRC_EXT4_PREFIX, _NAME) + +#define TRC_EXT1_VERSION_MAJOR CAT(TRC_EXT1_PREFIX, _VERSION_MAJOR) +#define TRC_EXT2_VERSION_MAJOR CAT(TRC_EXT2_PREFIX, _VERSION_MAJOR) +#define TRC_EXT3_VERSION_MAJOR CAT(TRC_EXT3_PREFIX, _VERSION_MAJOR) +#define TRC_EXT4_VERSION_MAJOR CAT(TRC_EXT4_PREFIX, _VERSION_MAJOR) + +#define TRC_EXT1_VERSION_MINOR CAT(TRC_EXT1_PREFIX, _VERSION_MINOR) +#define TRC_EXT2_VERSION_MINOR CAT(TRC_EXT2_PREFIX, _VERSION_MINOR) +#define TRC_EXT3_VERSION_MINOR CAT(TRC_EXT3_PREFIX, _VERSION_MINOR) +#define TRC_EXT4_VERSION_MINOR CAT(TRC_EXT4_PREFIX, _VERSION_MINOR) + +#define TRC_EXT1_VERSION_PATCH CAT(TRC_EXT1_PREFIX, _VERSION_PATCH) +#define TRC_EXT2_VERSION_PATCH CAT(TRC_EXT2_PREFIX, _VERSION_PATCH) +#define TRC_EXT3_VERSION_PATCH CAT(TRC_EXT3_PREFIX, _VERSION_PATCH) +#define TRC_EXT4_VERSION_PATCH CAT(TRC_EXT4_PREFIX, _VERSION_PATCH) + +#if ((TRC_CFG_EXTENSION_COUNT > 4) || (TRC_CFG_EXTENSION_COUNT < 0)) + #error "TRC_CFG_EXTENSION_COUNT must be in range [0..4]" +#endif + +#if (TRC_CFG_EXTENSION_COUNT == 0) +#define TRC_EXTENSIONS_DATA +#endif + +#if (TRC_CFG_EXTENSION_COUNT == 1) +#define TRC_EXTENSIONS_DATA \ +{ \ + { TRC_EXTENSION_EVENTCODE_BASE, \ + TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT-1, \ + TRC_EXT1_VERSION_PATCH, \ + TRC_EXT1_VERSION_MINOR, \ + TRC_EXT1_VERSION_MAJOR, \ + TRC_EXT1_NAME } \ +} +#endif + +#if (TRC_CFG_EXTENSION_COUNT == 2) +#define TRC_EXTENSIONS_DATA \ +{ \ + { TRC_EXTENSION_EVENTCODE_BASE, \ + TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT-1, \ + TRC_EXT1_VERSION_PATCH, \ + TRC_EXT1_VERSION_MINOR, \ + TRC_EXT1_VERSION_MAJOR, \ + TRC_EXT1_NAME } \ + ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT, \ + TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT-1, \ + TRC_EXT2_VERSION_PATCH, \ + TRC_EXT2_VERSION_MINOR, \ + TRC_EXT2_VERSION_MAJOR, \ + TRC_EXT2_NAME } \ +} +#endif + +#if (TRC_CFG_EXTENSION_COUNT == 3) +#define TRC_EXTENSIONS_DATA \ +{ \ + { TRC_EXTENSION_EVENTCODE_BASE, \ + TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT-1, \ + TRC_EXT1_VERSION_PATCH, \ + TRC_EXT1_VERSION_MINOR, \ + TRC_EXT1_VERSION_MAJOR, \ + TRC_EXT1_NAME } \ + ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT, \ + TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT-1, \ + TRC_EXT2_VERSION_PATCH, \ + TRC_EXT2_VERSION_MINOR, \ + TRC_EXT2_VERSION_MAJOR, \ + TRC_EXT2_NAME } \ + ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT, \ + TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT + TRC_EXT3_COUNT - 1, \ + TRC_EXT3_VERSION_PATCH, \ + TRC_EXT3_VERSION_MINOR, \ + TRC_EXT3_VERSION_MAJOR, \ + TRC_EXT3_NAME } \ +} +#endif +#if (TRC_CFG_EXTENSION_COUNT == 4) +#define TRC_EXTENSIONS_DATA \ +{ \ + { TRC_EXTENSION_EVENTCODE_BASE, \ + TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT-1, \ + TRC_EXT1_VERSION_PATCH, \ + TRC_EXT1_VERSION_MINOR, \ + TRC_EXT1_VERSION_MAJOR, \ + TRC_EXT1_NAME } \ + ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT, \ + TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT-1, \ + TRC_EXT2_VERSION_PATCH, \ + TRC_EXT2_VERSION_MINOR, \ + TRC_EXT2_VERSION_MAJOR, \ + TRC_EXT2_NAME } \ + ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT, \ + TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT + TRC_EXT3_COUNT - 1, \ + TRC_EXT3_VERSION_PATCH, \ + TRC_EXT3_VERSION_MINOR, \ + TRC_EXT3_VERSION_MAJOR, \ + TRC_EXT3_NAME } \ + ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT + TRC_EXT3_COUNT, \ + TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT + TRC_EXT3_COUNT + TRC_EXT4_COUNT- 1, \ + TRC_EXT4_VERSION_PATCH, \ + TRC_EXT4_VERSION_MINOR, \ + TRC_EXT4_VERSION_MAJOR, \ + TRC_EXT4_NAME } \ +} +#endif + +#if (TRC_CFG_EXTENSION_COUNT > 0) +#define TRC_EXTENSION_INFO {TRC_CFG_EXTENSION_COUNT, TRC_EXTENSION_EVENTCODE_BASE, ROUNDUP4(TRC_CFG_EXT_MAX_NAME_LEN), sizeof(PSFExtensionEntryType), TRC_EXTENSIONS_DATA} +#else +#define TRC_EXTENSION_INFO {TRC_CFG_EXTENSION_COUNT, TRC_EXTENSION_EVENTCODE_BASE} +#endif + +#endif /* TRCEXTENSIONS_H_ */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h index 6bd981c4c..e452999ee 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h @@ -1,478 +1,558 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcHardwarePort.h
- *
- * The hardware abstraction layer for the trace recorder.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_HARDWARE_PORT_H
-#define TRC_HARDWARE_PORT_H
-
-#include "trcPortDefines.h"
-
-
-#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NOT_SET)
- #error "TRC_CFG_HARDWARE_PORT not selected - see trcConfig.h"
-#endif
-
-/*******************************************************************************
- * TRC_IRQ_PRIORITY_ORDER
- *
- * Macro which should be defined as an integer of 0 or 1.
- *
- * This should be 0 if lower IRQ priority values implies higher priority
- * levels, such as on ARM Cortex M. If the opposite scheme is used, i.e.,
- * if higher IRQ priority values means higher priority, this should be 1.
- *
- * This setting is not critical. It is used only to sort and colorize the
- * interrupts in priority order, in case you record interrupts using
- * the vTraceStoreISRBegin and vTraceStoreISREnd routines.
- *
- ******************************************************************************
- *
- * HWTC Macros
- *
- * These macros provides a hardware isolation layer representing the
- * hardware timer/counter used for the event timestamping.
- *
- * TRC_HWTC_COUNT: How to read the current value of the timer/counter.
- *
- * TRC_HWTC_TYPE: Tells the type of timer/counter used for TRC_HWTC_COUNT:
- *
- * - TRC_FREE_RUNNING_32BIT_INCR:
- * Free-running 32-bit timer/counter, counting upwards from 0.
- *
- * - TRC_FREE_RUNNING_32BIT_DECR
- * Free-running 32-bit timer/counter, counting downwards from 0xFFFFFFFF.
- *
- * - TRC_OS_TIMER_INCR
- * Periodic timer that drives the OS tick interrupt, counting upwards
- * from 0 until (TRC_HWTC_PERIOD-1).
- *
- * - TRC_OS_TIMER_DECR
- * Periodic timer that drives the OS tick interrupt, counting downwards
- * from TRC_HWTC_PERIOD-1 until 0.
- *
- * - TRC_CUSTOM_TIMER_INCR
- * A custom timer or counter independent of the OS tick, counting
- * downwards from TRC_HWTC_PERIOD-1 until 0. (Currently only supported
- * in streaming mode).
- *
- * - TRC_CUSTOM_TIMER_DECR
- * A custom timer independent of the OS tick, counting downwards
- * from TRC_HWTC_PERIOD-1 until 0. (Currently only supported
- * in streaming mode).
- *
- * TRC_HWTC_PERIOD: The number of HWTC_COUNT ticks until the timer wraps
- * around. If using TRC_FREE_RUNNING_32BIT_INCR/DECR, this should be 0.
- *
- * TRC_HWTC_FREQ_HZ: The clock rate of the TRC_HWTC_COUNT counter in Hz. If using
- * TRC_OS_TIMER_INCR/DECR, this is should be TRC_HWTC_PERIOD * TRACE_TICK_RATE_HZ.
- * If using a free-running timer, this is often TRACE_CPU_CLOCK_HZ (if running at
- * the core clock rate). If using TRC_CUSTOM_TIMER_INCR/DECR, this should match
- * the clock rate of your custom timer (i.e., TRC_HWTC_COUNT). If the default value
- * of TRC_HWTC_FREQ_HZ is incorrect for your setup, you can override it by calling
- * vTraceSetFrequency before calling vTraceEnable.
- *
- * TRC_HWTC_DIVISOR (used in snapshot mode only):
- * In snapshot mode, the timestamp resolution is TRC_HWTC_FREQ_HZ/TRC_HWTC_DIVISOR.
- * If the timer frequency is very high (hundreds of MHz), we recommend increasing
- * the TRC_HWTC_DIVISOR prescaler, to reduce the bandwidth needed to store
- * timestamps. This since extra "XTS" events are inserted if the time since the
- * previous event exceeds a certain limit (255 or 65535 depending on event type).
- * It is advised to keep the time between most events below 65535 native ticks
- * (after division by TRC_HWTC_DIVISOR) to avoid frequent XTS events.
- ******************************************************************************/
-
-#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NOT_SET)
- #error "TRC_CFG_HARDWARE_PORT not selected - see trcConfig.h"
-#endif
-
-#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win32)
- /* This can be used as a template for any free-running 32-bit counter */
- #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR
- #define TRC_HWTC_COUNT (ulGetRunTimeCounterValue())
- #define TRC_HWTC_PERIOD 0
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ 100000
-
- #define TRC_IRQ_PRIORITY_ORDER 1
-
- #define TRC_PORT_SPECIFIC_INIT()
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_HWIndependent)
- /* Timestamping by OS tick only (typically 1 ms resolution) */
- #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
- #define TRC_HWTC_COUNT 0
- #define TRC_HWTC_PERIOD 1
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ TRACE_TICK_RATE_HZ
-
- /* Set the meaning of IRQ priorities in ISR tracing - see above */
- #define TRC_IRQ_PRIORITY_ORDER NOT_SET
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M)
-
- #ifndef __CORTEX_M
- #error "Can't find the CMSIS API. Please include your processor's header file in trcConfig.h"
- #endif
-
- /**************************************************************************
- * For Cortex-M3, M4 and M7, the DWT cycle counter is used for timestamping.
- * For Cortex-M0 and M0+, the SysTick timer is used since DWT is not
- * available. Systick timestamping can also be forced on Cortex-M3, M4 and
- * M7 by defining the preprocessor directive TRC_CFG_ARM_CM_USE_SYSTICK,
- * either directly below or in trcConfig.h.
- *
- * #define TRC_CFG_ARM_CM_USE_SYSTICK
- **************************************************************************/
-
- #if ((__CORTEX_M >= 0x03) && (! defined TRC_CFG_ARM_CM_USE_SYSTICK))
-
- void prvTraceInitCortexM(void);
-
- #define TRC_REG_DEMCR (*(volatile uint32_t*)0xE000EDFC)
- #define TRC_REG_DWT_CTRL (*(volatile uint32_t*)0xE0001000)
- #define TRC_REG_DWT_CYCCNT (*(volatile uint32_t*)0xE0001004)
- #define TRC_REG_DWT_EXCCNT (*(volatile uint32_t*)0xE000100C)
-
- #define TRC_REG_ITM_LOCKACCESS (*(volatile uint32_t*)0xE0001FB0)
- #define TRC_ITM_LOCKACCESS_UNLOCK (0xC5ACCE55)
-
- /* Bit mask for TRCENA bit in DEMCR - Global enable for DWT and ITM */
- #define TRC_DEMCR_TRCENA (1 << 24)
-
- /* Bit mask for NOPRFCNT bit in DWT_CTRL. If 1, DWT_EXCCNT is not supported */
- #define TRC_DWT_CTRL_NOPRFCNT (1 << 24)
-
- /* Bit mask for NOCYCCNT bit in DWT_CTRL. If 1, DWT_CYCCNT is not supported */
- #define TRC_DWT_CTRL_NOCYCCNT (1 << 25)
-
- /* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_EXCCNT */
- #define TRC_DWT_CTRL_EXCEVTENA (1 << 18)
-
- /* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_CYCCNT */
- #define TRC_DWT_CTRL_CYCCNTENA (1)
-
- #define TRC_PORT_SPECIFIC_INIT() prvTraceInitCortexM()
-
- #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR
- #define TRC_HWTC_COUNT TRC_REG_DWT_CYCCNT
- #define TRC_HWTC_PERIOD 0
- #define TRC_HWTC_DIVISOR 4
- #define TRC_HWTC_FREQ_HZ TRACE_CPU_CLOCK_HZ
- #define TRC_IRQ_PRIORITY_ORDER 0
-
- #else
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
- #define TRC_HWTC_COUNT (*((volatile uint32_t*)0xE000E018))
- #define TRC_HWTC_PERIOD ((*((volatile uint32_t*)0xE000E014)) + 1)
- #define TRC_HWTC_DIVISOR 4
- #define TRC_HWTC_FREQ_HZ TRACE_CPU_CLOCK_HZ
- #define TRC_IRQ_PRIORITY_ORDER 0
-
- #endif
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Renesas_RX600)
-
- #include "iodefine.h"
-
- #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
- #define TRC_HWTC_COUNT (CMT0.CMCNT)
-
- #elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
-
- /* Decreasing counters better for Tickless Idle? */
- #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
- #define TRC_HWTC_COUNT (CMT0.CMCOR - CMT0.CMCNT)
-
- #endif
-
- #define TRC_HWTC_PERIOD (CMT0.CMCOR + 1)
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 1
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_MICROCHIP_PIC24_PIC32)
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
- #define TRC_HWTC_COUNT (TMR1)
- #define TRC_HWTC_PERIOD (PR1 + 1)
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 0
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_TMS570_RM48)
-
- #define TRC_RTIFRC0 *((uint32_t *)0xFFFFFC10)
- #define TRC_RTICOMP0 *((uint32_t *)0xFFFFFC50)
- #define TRC_RTIUDCP0 *((uint32_t *)0xFFFFFC54)
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
- #define TRC_HWTC_COUNT (TRC_RTIFRC0 - (TRC_RTICOMP0 - TRC_RTIUDCP0))
- #define TRC_HWTC_PERIOD (TRC_RTIUDCP0)
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 0
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Atmel_AT91SAM7)
-
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
- #define TRC_HWTC_COUNT ((uint32_t)(AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF))
- #define TRC_HWTC_PERIOD ((uint32_t)(AT91C_BASE_PITC->PITC_PIMR + 1))
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 1
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Atmel_UC3A0)
-
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO*/
-
- /* For Atmel AVR32 (AT32UC3A) */
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
- #define TRC_HWTC_COUNT ((uint32_t)sysreg_read(AVR32_COUNT))
- #define TRC_HWTC_PERIOD ((uint32_t)(sysreg_read(AVR32_COMPARE) + 1))
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 1
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NXP_LPC210X)
-
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
-
- /* Tested with LPC2106, but should work with most LPC21XX chips. */
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
- #define TRC_HWTC_COUNT *((uint32_t *)0xE0004008 )
- #define TRC_HWTC_PERIOD *((uint32_t *)0xE0004018 )
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 0
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_MSP430)
-
- /* UNOFFICIAL PORT - NOT YET VERIFIED */
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
- #define TRC_HWTC_COUNT (TA0R)
- #define TRC_HWTC_PERIOD (((uint16_t)TACCR0)+1)
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 1
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_PPC405)
-
- /* UNOFFICIAL PORT - NOT YET VERIFIED */
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
- #define TRC_HWTC_COUNT mfspr(0x3db)
- #define TRC_HWTC_PERIOD (TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ)
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 0
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_PPC440)
-
- /* UNOFFICIAL PORT */
-
- /* This should work with most PowerPC chips */
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
- #define TRC_HWTC_COUNT mfspr(0x016)
- #define TRC_HWTC_PERIOD (TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ)
- #define TRC_HWTC_DIVISOR 1
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 0
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_MICROBLAZE)
-
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
-
- /* This should work with most Microblaze configurations.
- * It uses the AXI Timer 0 - the tick interrupt source.
- * If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required.
- */
- #include "xtmrctr_l.h"
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
- #define TRC_HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 )
- #define TRC_HWTC_PERIOD (XTmrCtr_mGetLoadReg( XPAR_TMRCTR_0_BASEADDR, 0) + 1)
- #define TRC_HWTC_DIVISOR 16
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 0
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Altera_NiosII)
-
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
-
- #include "system.h"
- #include "sys/alt_timestamp.h"
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
- #define TRC_HWTC_COUNT (uint32_t)alt_timestamp()
- #define TRC_HWTC_PERIOD 0xFFFFFFFF
- #define TRC_HWTC_FREQ_HZ TIMESTAMP_TIMER_FREQ
- #define TRC_HWTC_DIVISOR 1
- #define TRC_IRQ_PRIORITY_ORDER 0
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9)
-
- /* INPUT YOUR PERIPHERAL BASE ADDRESS HERE */
- #define TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS 0xSOMETHING
-
- #define TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET 0x0600
- #define TRC_CA9_MPCORE_PRIVCTR_PERIOD_REG (*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x00))
- #define TRC_CA9_MPCORE_PRIVCTR_COUNTER_REG (*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x04))
- #define TRC_CA9_MPCORE_PRIVCTR_CONTROL_REG (*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x08))
-
- #define TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_MASK 0x0000FF00
- #define TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_SHIFT 8
- #define TRC_CA9_MPCORE_PRIVCTR_PRESCALER (((TRC_CA9_MPCORE_PRIVCTR_CONTROL_REG & TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_MASK) >> TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_SHIFT) + 1)
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
- #define TRC_HWTC_COUNT TRC_CA9_MPCORE_PRIVCTR_COUNTER_REG
- #define TRC_HWTC_PERIOD (TRC_CA9_MPCORE_PRIVCTR_PERIOD_REG + 1)
-
- /****************************************************************************************
- NOTE: The private timer ticks with a very high frequency (half the core-clock usually),
- depending on the prescaler used. If a low prescaler is used, the number of HW ticks between
- the trace events gets large, and thereby inefficient to store (sometimes extra events are
- needed). To improve efficiency, you may use the TRC_HWTC_DIVISOR as an additional prescaler.
- *****************************************************************************************/
- #define TRC_HWTC_DIVISOR 1
-
- #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
- #define TRC_IRQ_PRIORITY_ORDER 0
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_POWERPC_Z4)
-
- /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
-
- #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
- //#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
- #define TRC_HWTC_COUNT PIT.TIMER[configTICK_PIT_CHANNEL].CVAL.R // must be the PIT channel used for the systick
- #define TRC_HWTC_PERIOD ((configPIT_CLOCK_HZ / configTICK_RATE_HZ) - 1U) // TODO FIXME or maybe not -1? what's the right "period" value?
- #define TRC_HWTC_FREQ_HZ configPIT_CLOCK_HZ
- #define TRC_HWTC_DIVISOR 1
- #define TRC_IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
-
-#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_APPLICATION_DEFINED)
-
- #if !( defined (TRC_HWTC_TYPE) && defined (TRC_HWTC_COUNT) && defined (TRC_HWTC_PERIOD) && defined (TRC_HWTC_FREQ_HZ) && defined (TRC_IRQ_PRIORITY_ORDER) )
- #error "The hardware port is not completely defined!"
- #endif
-
-#elif (TRC_CFG_HARDWARE_PORT != TRC_HARDWARE_PORT_NOT_SET)
-
- #error "TRC_CFG_HARDWARE_PORT had unsupported value!"
- #define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_NOT_SET
-
-#endif
-
-#ifndef TRC_HWTC_DIVISOR
- #define TRC_HWTC_DIVISOR 1
-#endif
-
-#ifndef TRC_PORT_SPECIFIC_INIT
- #define TRC_PORT_SPECIFIC_INIT()
-#endif
-
-/* If Win32 port */
-#ifdef WIN32
-
- #undef _WIN32_WINNT
- #define _WIN32_WINNT 0x0600
-
- /* Standard includes. */
- #include <stdio.h>
- #include <windows.h>
- #include <direct.h>
-
- /***************************************************************************
- * The Win32 port by default saves the trace to file and then kills the
- * program when the recorder is stopped, to facilitate quick, simple tests
- * of the recorder.
- ***************************************************************************/
- #define WIN32_PORT_SAVE_WHEN_STOPPED 1
- #define WIN32_PORT_EXIT_WHEN_STOPPED 1
-
-#endif
-
-#if (TRC_CFG_HARDWARE_PORT != TRC_HARDWARE_PORT_NOT_SET)
-
- #ifndef TRC_HWTC_TYPE
- #error "TRC_HWTC_TYPE is not set!"
- #endif
-
- #ifndef TRC_HWTC_COUNT
- #error "TRC_HWTC_COUNT is not set!"
- #endif
-
- #ifndef TRC_HWTC_PERIOD
- #error "TRC_HWTC_PERIOD is not set!"
- #endif
-
- #ifndef TRC_HWTC_DIVISOR
- #error "TRC_HWTC_DIVISOR is not set!"
- #endif
-
- #ifndef TRC_IRQ_PRIORITY_ORDER
- #error "TRC_IRQ_PRIORITY_ORDER is not set!"
- #elif (TRC_IRQ_PRIORITY_ORDER != 0) && (TRC_IRQ_PRIORITY_ORDER != 1)
- #error "TRC_IRQ_PRIORITY_ORDER has bad value!"
- #endif
-
- #if (TRC_HWTC_DIVISOR < 1)
- #error "TRC_HWTC_DIVISOR must be a non-zero positive value!"
- #endif
-
- #ifndef TRC_HWTC_FREQ_HZ
- #error "TRC_HWTC_FREQ_HZ not defined!"
- #endif
-
-#endif
-
-#endif /*TRC_SNAPSHOT_HARDWARE_PORT_H*/
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcHardwarePort.h + * + * The hardware abstraction layer for the trace recorder. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_HARDWARE_PORT_H +#define TRC_HARDWARE_PORT_H + +#include "trcPortDefines.h" + + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NOT_SET) + #error "TRC_CFG_HARDWARE_PORT not selected - see trcConfig.h" +#endif + +/******************************************************************************* + * TRC_IRQ_PRIORITY_ORDER + * + * Macro which should be defined as an integer of 0 or 1. + * + * This should be 0 if lower IRQ priority values implies higher priority + * levels, such as on ARM Cortex M. If the opposite scheme is used, i.e., + * if higher IRQ priority values means higher priority, this should be 1. + * + * This setting is not critical. It is used only to sort and colorize the + * interrupts in priority order, in case you record interrupts using + * the vTraceStoreISRBegin and vTraceStoreISREnd routines. + * + ****************************************************************************** + * + * HWTC Macros + * + * These macros provides a hardware isolation layer representing the + * hardware timer/counter used for the event timestamping. + * + * TRC_HWTC_COUNT: How to read the current value of the timer/counter. + * + * TRC_HWTC_TYPE: Tells the type of timer/counter used for TRC_HWTC_COUNT: + * + * - TRC_FREE_RUNNING_32BIT_INCR: + * Free-running 32-bit timer/counter, counting upwards from 0. + * + * - TRC_FREE_RUNNING_32BIT_DECR + * Free-running 32-bit timer/counter, counting downwards from 0xFFFFFFFF. + * + * - TRC_OS_TIMER_INCR + * Periodic timer that drives the OS tick interrupt, counting upwards + * from 0 until (TRC_HWTC_PERIOD-1). + * + * - TRC_OS_TIMER_DECR + * Periodic timer that drives the OS tick interrupt, counting downwards + * from TRC_HWTC_PERIOD-1 until 0. + * + * - TRC_CUSTOM_TIMER_INCR + * A custom timer or counter independent of the OS tick, counting + * downwards from TRC_HWTC_PERIOD-1 until 0. (Currently only supported + * in streaming mode). + * + * - TRC_CUSTOM_TIMER_DECR + * A custom timer independent of the OS tick, counting downwards + * from TRC_HWTC_PERIOD-1 until 0. (Currently only supported + * in streaming mode). + * + * TRC_HWTC_PERIOD: The number of HWTC_COUNT ticks until the timer wraps + * around. If using TRC_FREE_RUNNING_32BIT_INCR/DECR, this should be 0. + * + * TRC_HWTC_FREQ_HZ: The clock rate of the TRC_HWTC_COUNT counter in Hz. If using + * TRC_OS_TIMER_INCR/DECR, this is should be TRC_HWTC_PERIOD * TRACE_TICK_RATE_HZ. + * If using a free-running timer, this is often TRACE_CPU_CLOCK_HZ (if running at + * the core clock rate). If using TRC_CUSTOM_TIMER_INCR/DECR, this should match + * the clock rate of your custom timer (i.e., TRC_HWTC_COUNT). If the default value + * of TRC_HWTC_FREQ_HZ is incorrect for your setup, you can override it by calling + * vTraceSetFrequency before calling vTraceEnable. + * + * TRC_HWTC_DIVISOR (used in snapshot mode only): + * In snapshot mode, the timestamp resolution is TRC_HWTC_FREQ_HZ/TRC_HWTC_DIVISOR. + * If the timer frequency is very high (hundreds of MHz), we recommend increasing + * the TRC_HWTC_DIVISOR prescaler, to reduce the bandwidth needed to store + * timestamps. This since extra "XTS" events are inserted if the time since the + * previous event exceeds a certain limit (255 or 65535 depending on event type). + * It is advised to keep the time between most events below 65535 native ticks + * (after division by TRC_HWTC_DIVISOR) to avoid frequent XTS events. + ******************************************************************************/ + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NOT_SET) + #error "TRC_CFG_HARDWARE_PORT not selected - see trcConfig.h" +#endif + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win32) + /* This can be used as a template for any free-running 32-bit counter */ + #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR + #define TRC_HWTC_COUNT (ulGetRunTimeCounterValue()) + #define TRC_HWTC_PERIOD 0 + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ 100000 + + #define TRC_IRQ_PRIORITY_ORDER 1 + + #define TRC_PORT_SPECIFIC_INIT() + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_HWIndependent) + /* Timestamping by OS tick only (typically 1 ms resolution) */ + #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR + #define TRC_HWTC_COUNT 0 + #define TRC_HWTC_PERIOD 1 + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ TRACE_TICK_RATE_HZ + + /* Set the meaning of IRQ priorities in ISR tracing - see above */ + #define TRC_IRQ_PRIORITY_ORDER NOT_SET + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) + + #ifndef __CORTEX_M + #error "Can't find the CMSIS API. Please include your processor's header file in trcConfig.h" + #endif + + /************************************************************************** + * For Cortex-M3, M4 and M7, the DWT cycle counter is used for timestamping. + * For Cortex-M0 and M0+, the SysTick timer is used since DWT is not + * available. Systick timestamping can also be forced on Cortex-M3, M4 and + * M7 by defining the preprocessor directive TRC_CFG_ARM_CM_USE_SYSTICK, + * either directly below or in trcConfig.h. + * + * #define TRC_CFG_ARM_CM_USE_SYSTICK + **************************************************************************/ + + #if ((__CORTEX_M >= 0x03) && (! defined TRC_CFG_ARM_CM_USE_SYSTICK)) + + void prvTraceInitCortexM(void); + + #define TRC_REG_DEMCR (*(volatile uint32_t*)0xE000EDFC) + #define TRC_REG_DWT_CTRL (*(volatile uint32_t*)0xE0001000) + #define TRC_REG_DWT_CYCCNT (*(volatile uint32_t*)0xE0001004) + #define TRC_REG_DWT_EXCCNT (*(volatile uint32_t*)0xE000100C) + + #define TRC_REG_ITM_LOCKACCESS (*(volatile uint32_t*)0xE0001FB0) + #define TRC_ITM_LOCKACCESS_UNLOCK (0xC5ACCE55) + + /* Bit mask for TRCENA bit in DEMCR - Global enable for DWT and ITM */ + #define TRC_DEMCR_TRCENA (1 << 24) + + /* Bit mask for NOPRFCNT bit in DWT_CTRL. If 1, DWT_EXCCNT is not supported */ + #define TRC_DWT_CTRL_NOPRFCNT (1 << 24) + + /* Bit mask for NOCYCCNT bit in DWT_CTRL. If 1, DWT_CYCCNT is not supported */ + #define TRC_DWT_CTRL_NOCYCCNT (1 << 25) + + /* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_EXCCNT */ + #define TRC_DWT_CTRL_EXCEVTENA (1 << 18) + + /* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_CYCCNT */ + #define TRC_DWT_CTRL_CYCCNTENA (1) + + #define TRC_PORT_SPECIFIC_INIT() prvTraceInitCortexM() + + #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR + #define TRC_HWTC_COUNT TRC_REG_DWT_CYCCNT + #define TRC_HWTC_PERIOD 0 + #define TRC_HWTC_DIVISOR 4 + #define TRC_HWTC_FREQ_HZ TRACE_CPU_CLOCK_HZ + #define TRC_IRQ_PRIORITY_ORDER 0 + + #else + + #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR + #define TRC_HWTC_COUNT (*((volatile uint32_t*)0xE000E018)) + #define TRC_HWTC_PERIOD ((*((volatile uint32_t*)0xE000E014)) + 1) + #define TRC_HWTC_DIVISOR 4 + #define TRC_HWTC_FREQ_HZ TRACE_CPU_CLOCK_HZ + #define TRC_IRQ_PRIORITY_ORDER 0 + + #endif + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Renesas_RX600) + + #include "iodefine.h" + + #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + + #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR + #define TRC_HWTC_COUNT (CMT0.CMCNT) + + #elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + + /* Decreasing counters better for Tickless Idle? */ + #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR + #define TRC_HWTC_COUNT (CMT0.CMCOR - CMT0.CMCNT) + + #endif + + #define TRC_HWTC_PERIOD (CMT0.CMCOR + 1) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 1 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_MICROCHIP_PIC24_PIC32) + + #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR + #define TRC_HWTC_COUNT (TMR1) + #define TRC_HWTC_PERIOD (PR1 + 1) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 1 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_TMS570_RM48) + + #define TRC_RTIFRC0 *((uint32_t *)0xFFFFFC10) + #define TRC_RTICOMP0 *((uint32_t *)0xFFFFFC50) + #define TRC_RTIUDCP0 *((uint32_t *)0xFFFFFC54) + + #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR + #define TRC_HWTC_COUNT (TRC_RTIFRC0 - (TRC_RTICOMP0 - TRC_RTIUDCP0)) + #define TRC_HWTC_PERIOD (TRC_RTIUDCP0) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 0 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Atmel_AT91SAM7) + + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + + #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR + #define TRC_HWTC_COUNT ((uint32_t)(AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF)) + #define TRC_HWTC_PERIOD ((uint32_t)(AT91C_BASE_PITC->PITC_PIMR + 1)) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 1 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Atmel_UC3A0) + + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO*/ + + /* For Atmel AVR32 (AT32UC3A) */ + + #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR + #define TRC_HWTC_COUNT ((uint32_t)sysreg_read(AVR32_COUNT)) + #define TRC_HWTC_PERIOD ((uint32_t)(sysreg_read(AVR32_COMPARE) + 1)) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 1 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NXP_LPC210X) + + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + + /* Tested with LPC2106, but should work with most LPC21XX chips. */ + + #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR + #define TRC_HWTC_COUNT *((uint32_t *)0xE0004008 ) + #define TRC_HWTC_PERIOD *((uint32_t *)0xE0004018 ) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 0 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_MSP430) + + /* UNOFFICIAL PORT - NOT YET VERIFIED */ + + #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR + #define TRC_HWTC_COUNT (TA0R) + #define TRC_HWTC_PERIOD (((uint16_t)TACCR0)+1) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 1 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_PPC405) + + /* UNOFFICIAL PORT - NOT YET VERIFIED */ + + #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR + #define TRC_HWTC_COUNT mfspr(0x3db) + #define TRC_HWTC_PERIOD (TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 0 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_PPC440) + + /* UNOFFICIAL PORT */ + + /* This should work with most PowerPC chips */ + + #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR + #define TRC_HWTC_COUNT mfspr(0x016) + #define TRC_HWTC_PERIOD (TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 0 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_MICROBLAZE) + + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + + /* This should work with most Microblaze configurations. + * It uses the AXI Timer 0 - the tick interrupt source. + * If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required. + */ + #include "xtmrctr_l.h" + + #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR + #define TRC_HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 ) + #define TRC_HWTC_PERIOD (XTmrCtr_mGetLoadReg( XPAR_TMRCTR_0_BASEADDR, 0) + 1) + #define TRC_HWTC_DIVISOR 16 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 0 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_ZyncUltraScaleR5) + + #include "xttcps_hw.h" + + #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR + #define TRC_HWTC_COUNT (*(volatile uint32_t *)(configTIMER_BASEADDR + XTTCPS_COUNT_VALUE_OFFSET)) + #define TRC_HWTC_PERIOD (*(volatile uint32_t *)(configTIMER_BASEADDR + XTTCPS_INTERVAL_VAL_OFFSET)) + #define TRC_HWTC_DIVISOR 16 + #define TRC_HWTC_FREQ_HZ (TRC_HWTC_PERIOD * TRACE_TICK_RATE_HZ) + #define TRC_IRQ_PRIORITY_ORDER 0 + + #ifdef __GNUC__ + /* For Arm Cortex-A and Cortex-R in general. */ + static inline uint32_t prvGetCPSR(void) + { + unsigned long ret; + /* GCC-style assembly for getting the CPSR/APSR register, where the system execution mode is found. */ + asm volatile (" mrs %0, cpsr" : "=r" (ret) : /* no inputs */ ); + return ret; + } + #else + #error "Only GCC Supported!" + #endif + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Altera_NiosII) + + /* OFFICIAL PORT */ + + #include <system.h> + #include <altera_avalon_timer_regs.h> + + #define NOT_SET 1 + + /* The base address for the sustem timer set. + * The name user for the system timer can be found in the BSP editor. + * If the name of the timer is sys_tmr SYSTEM_TIMER_BASE should be set to SYS_TMR_BASE. + */ + #define SYSTEM_TIMER_BASE NOT_SET + + #if (SYSTEM_TIMER == NOT_SET) + #error "Set SYSTEM_TIMER_BASE to the timer base used for system ticks." + #endif + + static inline uint32_t altera_nios2_GetTimerSnapReg(void) + { + /* A processor can read the current counter value by first writing to either snapl or snaph to request a coherent snapshot of the counter, + * and then reading snapl and snaph for the full 32-bit value. + */ + IOWR_ALTERA_AVALON_TIMER_SNAPL(SYSTEM_TIMER_BASE, 0); + return (IORD_ALTERA_AVALON_TIMER_SNAPH(SYSTEM_TIMER_BASE) << 16) | IORD_ALTERA_AVALON_TIMER_SNAPL(SYSTEM_TIMER_BASE); + } + + #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR + #define TRC_HWTC_COUNT altera_nios2_GetTimerSnapReg() + #define TRC_HWTC_PERIOD (configCPU_CLOCK_HZ / configTICK_RATE_HZ ) + #define TRC_HWTC_DIVISOR 16 + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 0 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9) + + /************************************************************************** + * This hardware port only supports FreeRTOS and the GCC compiler at the + * moment, due to the implementation of critical sections (trcKernelPort.h). + * + * Assuming FreeRTOS is used: + * + * For critical sections, this uses vTaskEnterCritical is when called from + * task context and ulPortSetInterruptMask when called from ISR context. + * Thus, it does not disable all ISRs. This means that the trace recorder + * can only be called from ISRs with priority less or equal to + * configMAX_API_CALL_INTERRUPT_PRIORITY (like FreeRTOS fromISR functions). + * + * This hardware port has been tested on it a Xilinx Zync 7000 (Cortex-A9), + * but should work with all Cortex-A and R processors assuming that + * TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS is set accordingly. + **************************************************************************/ + + /* INPUT YOUR PERIPHERAL BASE ADDRESS HERE (0xF8F00000 for Xilinx Zynq 7000)*/ + #define TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS 0 + + #if (TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS == 0) + #error "Please specify TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS." + #endif + + #define TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET 0x0600 + #define TRC_CA9_MPCORE_PRIVCTR_PERIOD_REG (*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x00)) + #define TRC_CA9_MPCORE_PRIVCTR_COUNTER_REG (*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x04)) + #define TRC_CA9_MPCORE_PRIVCTR_CONTROL_REG (*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x08)) + + #define TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_MASK 0x0000FF00 + #define TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_SHIFT 8 + #define TRC_CA9_MPCORE_PRIVCTR_PRESCALER (((TRC_CA9_MPCORE_PRIVCTR_CONTROL_REG & TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_MASK) >> TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_SHIFT) + 1) + + #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR + #define TRC_HWTC_COUNT TRC_CA9_MPCORE_PRIVCTR_COUNTER_REG + #define TRC_HWTC_PERIOD (TRC_CA9_MPCORE_PRIVCTR_PERIOD_REG + 1) + + /**************************************************************************************** + NOTE: The private timer ticks with a very high frequency (half the core-clock usually), + depending on the prescaler used. If a low prescaler is used, the number of HW ticks between + the trace events gets large, and thereby inefficient to store (sometimes extra events are + needed). To improve efficiency, you may use the TRC_HWTC_DIVISOR as an additional prescaler. + *****************************************************************************************/ + #define TRC_HWTC_DIVISOR 1 + + #define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 0 + + #ifdef __GNUC__ + /* For Arm Cortex-A and Cortex-R in general. */ + static inline uint32_t prvGetCPSR(void) + { + unsigned long ret; + /* GCC-style assembly for getting the CPSR/APSR register, where the system execution mode is found. */ + asm volatile (" mrs %0, cpsr" : "=r" (ret) : /* no inputs */ ); + return ret; + } + #else + #error "Only GCC Supported!" + #endif + + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_POWERPC_Z4) + + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + + #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR + //#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING + #define TRC_HWTC_COUNT PIT.TIMER[configTICK_PIT_CHANNEL].CVAL.R // must be the PIT channel used for the systick + #define TRC_HWTC_PERIOD ((configPIT_CLOCK_HZ / configTICK_RATE_HZ) - 1U) // TODO FIXME or maybe not -1? what's the right "period" value? + #define TRC_HWTC_FREQ_HZ configPIT_CLOCK_HZ + #define TRC_HWTC_DIVISOR 1 + #define TRC_IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_APPLICATION_DEFINED) + + #if !( defined (TRC_HWTC_TYPE) && defined (TRC_HWTC_COUNT) && defined (TRC_HWTC_PERIOD) && defined (TRC_HWTC_FREQ_HZ) && defined (TRC_IRQ_PRIORITY_ORDER) ) + #error "The hardware port is not completely defined!" + #endif + +#elif (TRC_CFG_HARDWARE_PORT != TRC_HARDWARE_PORT_NOT_SET) + + #error "TRC_CFG_HARDWARE_PORT had unsupported value!" + #define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_NOT_SET + +#endif + +#ifndef TRC_HWTC_DIVISOR + #define TRC_HWTC_DIVISOR 1 +#endif + +#ifndef TRC_PORT_SPECIFIC_INIT + #define TRC_PORT_SPECIFIC_INIT() +#endif + +/* If Win32 port */ +#ifdef WIN32 + + #undef _WIN32_WINNT + #define _WIN32_WINNT 0x0600 + + /* Standard includes. */ + #include <stdio.h> + #include <windows.h> + #include <direct.h> + + /*************************************************************************** + * The Win32 port by default saves the trace to file and then kills the + * program when the recorder is stopped, to facilitate quick, simple tests + * of the recorder. + ***************************************************************************/ + #define WIN32_PORT_SAVE_WHEN_STOPPED 1 + #define WIN32_PORT_EXIT_WHEN_STOPPED 1 + +#endif + +#if (TRC_CFG_HARDWARE_PORT != TRC_HARDWARE_PORT_NOT_SET) + + #ifndef TRC_HWTC_TYPE + #error "TRC_HWTC_TYPE is not set!" + #endif + + #ifndef TRC_HWTC_COUNT + #error "TRC_HWTC_COUNT is not set!" + #endif + + #ifndef TRC_HWTC_PERIOD + #error "TRC_HWTC_PERIOD is not set!" + #endif + + #ifndef TRC_HWTC_DIVISOR + #error "TRC_HWTC_DIVISOR is not set!" + #endif + + #ifndef TRC_IRQ_PRIORITY_ORDER + #error "TRC_IRQ_PRIORITY_ORDER is not set!" + #elif (TRC_IRQ_PRIORITY_ORDER != 0) && (TRC_IRQ_PRIORITY_ORDER != 1) + #error "TRC_IRQ_PRIORITY_ORDER has bad value!" + #endif + + #if (TRC_HWTC_DIVISOR < 1) + #error "TRC_HWTC_DIVISOR must be a non-zero positive value!" + #endif + + #ifndef TRC_HWTC_FREQ_HZ + #error "TRC_HWTC_FREQ_HZ not defined!" + #endif + +#endif + +#endif /*TRC_SNAPSHOT_HARDWARE_PORT_H*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h index 965dabad9..d877e81c6 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h @@ -1,2565 +1,2791 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 has been
- * advised of the possibility of such damages, or for any claim by any third
- * party. Some jurisdictions do not allow the exclusion or limitation of
- * incidental, consequential or special damages, or the exclusion of implied
- * warranties or limitations on how long an implied warranty may last, so the
- * above limitations may not apply to you.
- *
- * FreeRTOS-specific definitions needed by the trace recorder
- *
- * <LICENSE INFO>
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_KERNEL_PORT_H
-#define TRC_KERNEL_PORT_H
-
-#include "FreeRTOS.h" /* Defines configUSE_TRACE_FACILITY */
-#include "trcPortDefines.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define TRC_USE_TRACEALYZER_RECORDER configUSE_TRACE_FACILITY
-
-/*** FreeRTOS version codes **************************************************/
-#define FREERTOS_VERSION_NOT_SET 0
-#define TRC_FREERTOS_VERSION_7_3 1 /* v7.3 is earliest supported.*/
-#define TRC_FREERTOS_VERSION_7_4 2
-#define TRC_FREERTOS_VERSION_7_5_OR_7_6 3
-#define TRC_FREERTOS_VERSION_8_X 4 /* Any v8.x.x*/
-#define TRC_FREERTOS_VERSION_9_0_0 5
-#define TRC_FREERTOS_VERSION_9_0_1 6
-#define TRC_FREERTOS_VERSION_9_0_2 7
-#define TRC_FREERTOS_VERSION_10_0_0 8 /* If using FreeRTOS v10.0.0 or later version */
-
-#define TRC_FREERTOS_VERSION_9_X 42 /* Not allowed anymore */
-
-#if (TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_9_X)
-/* This setting for TRC_CFG_FREERTOS_VERSION is no longer allowed as v9.0.1 needs special handling. */
-#error "Please specify your exact FreeRTOS version in trcConfig.h, from the options listed above."
-#endif
-
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-#define prvGetStreamBufferType(x) ((( StreamBuffer_t * )x )->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER)
-#else
-#define prvGetStreamBufferType(x) 0
-#endif
-
-/* Added mainly for our internal testing. This makes it easier to create test applications that
- runs on multiple FreeRTOS versions. */
-#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X)
- /* FreeRTOS v7.0 and later */
- #define STRING_CAST(x) ( (signed char*) x )
- #define TickType portTickType
-#else
- /* FreeRTOS v8.0 and later */
- #define STRING_CAST(x) x
- #define TickType TickType_t
-#endif
-
-#if (defined(TRC_USE_TRACEALYZER_RECORDER)) && (TRC_USE_TRACEALYZER_RECORDER == 1)
-
-/*******************************************************************************
- * INCLUDE_xTaskGetCurrentTaskHandle must be set to 1 for tracing to work properly
- ******************************************************************************/
-#undef INCLUDE_xTaskGetCurrentTaskHandle
-#define INCLUDE_xTaskGetCurrentTaskHandle 1
-
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-/*******************************************************************************
- * vTraceSetQueueName(void* object, const char* name)
- *
- * Parameter object: pointer to the Queue that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for Queue objects for display in Tracealyzer.
- ******************************************************************************/
-void vTraceSetQueueName(void* object, const char* name);
-
-/*******************************************************************************
- * vTraceSetSemaphoreName(void* object, const char* name)
- *
- * Parameter object: pointer to the Semaphore that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for Semaphore objects for display in Tracealyzer.
- ******************************************************************************/
-void vTraceSetSemaphoreName(void* object, const char* name);
-
-/*******************************************************************************
- * vTraceSetMutexName(void* object, const char* name)
- *
- * Parameter object: pointer to the Mutex that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for Semaphore objects for display in Tracealyzer.
- ******************************************************************************/
-void vTraceSetMutexName(void* object, const char* name);
-
-#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1)
-/*******************************************************************************
-* vTraceSetEventGroupName(void* object, const char* name)
-*
-* Parameter object: pointer to the EventGroup that shall be named
-* Parameter name: the name to set (const string literal)
-*
-* Sets a name for EventGroup objects for display in Tracealyzer.
-******************************************************************************/
-void vTraceSetEventGroupName(void* object, const char* name);
-#else /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */
-#define vTraceSetEventGroupName(object, name) /* Do nothing */
-#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */
-
-#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1)
-/*******************************************************************************
-* vTraceSetStreamBufferName(void* object, const char* name)
-*
-* Parameter object: pointer to the StreamBuffer that shall be named
-* Parameter name: the name to set (const string literal)
-*
-* Sets a name for StreamBuffer objects for display in Tracealyzer.
-******************************************************************************/
-void vTraceSetStreamBufferName(void* object, const char* name);
-#else /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */
-#define vTraceSetStreamBufferName(object, name) /* Do nothing */
-#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */
-
-#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1)
-/*******************************************************************************
- * vTraceSetMessageBufferName(void* object, const char* name)
- *
- * Parameter object: pointer to the MessageBuffer that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for MessageBuffer objects for display in Tracealyzer.
- ******************************************************************************/
-void vTraceSetMessageBufferName(void* object, const char* name);
-#else /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */
-#define vTraceSetMessageBufferName(object, name) /* Do nothing */
-#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */
-
-#else /* (TRC_CFG_SCHEDULING_ONLY == 0) */
-
-#define vTraceSetQueueName(object, name) /* Do nothing */
-#define vTraceSetSemaphoreName(object, name) /* Do nothing */
-#define vTraceSetMutexName(object, name) /* Do nothing */
-#define vTraceSetEventGroupName(object, name) /* Do nothing */
-#define vTraceSetStreamBufferName(object, name) /* Do nothing */
-#define vTraceSetMessageBufferName(object, name) /* Do nothing */
-
-#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */
-
-/*******************************************************************************
- * Note: Setting names for event groups is difficult to support, this has been
- * excluded intentionally. This since we don't know if event_groups.c is
- * included in the build, so referencing it from the recorder may cause errors.
- ******************************************************************************/
-
-/* Gives the currently executing task (wrapper for RTOS-specific function) */
-void* prvTraceGetCurrentTaskHandle(void);
-
-#if (((TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) && (TRC_CFG_INCLUDE_ISR_TRACING == 1)) || (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING))
-/* Tells if the scheduler currently is suspended (task-switches can't occur) */
-unsigned char prvTraceIsSchedulerSuspended(void);
-
-/*******************************************************************************
- * INCLUDE_xTaskGetSchedulerState must be set to 1 for tracing to work properly
- ******************************************************************************/
-#undef INCLUDE_xTaskGetSchedulerState
-#define INCLUDE_xTaskGetSchedulerState 1
-
-#endif /* (((TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) && (TRC_CFG_INCLUDE_ISR_TRACING == 1)) || (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)) */
-
-#define TRACE_KERNEL_VERSION 0x1AA1
-#define TRACE_TICK_RATE_HZ configTICK_RATE_HZ /* Defined in "FreeRTOS.h" */
-#define TRACE_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOSConfig.h" */
-#define TRACE_GET_CURRENT_TASK() prvTraceGetCurrentTaskHandle()
-
-#define TRACE_GET_OS_TICKS() (uiTraceTickCount) /* Streaming only */
-
-/* If using dynamic allocation of snapshot trace buffer... */
-#define TRACE_MALLOC(size) pvPortMalloc(size)
-
-#if defined(configUSE_TIMERS)
-#if (configUSE_TIMERS == 1)
-#undef INCLUDE_xTimerGetTimerDaemonTaskHandle
-#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1
-#endif /* configUSE_TIMERS == 1*/
-#endif /* configUSE_TIMERS */
-
-/* For ARM Cortex-M devices - assumes the ARM CMSIS API is available */
-#if (defined (__CORTEX_M))
- #define TRACE_ALLOC_CRITICAL_SECTION() uint32_t __irq_status;
- #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = __get_PRIMASK(); __set_PRIMASK(1);} /* PRIMASK disables ALL interrupts - allows for tracing in any ISR */
- #define TRACE_EXIT_CRITICAL_SECTION() {__set_PRIMASK(__irq_status);}
-#endif
-
-#if ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Renesas_RX600) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_MICROCHIP_PIC24_PIC32) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Altera_NiosII))
- #define TRACE_ALLOC_CRITICAL_SECTION() int __irq_status;
- #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = portSET_INTERRUPT_MASK_FROM_ISR();}
- #define TRACE_EXIT_CRITICAL_SECTION() {portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status);}
-#endif
-
-#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win32)
- /* In the Win32 port, there are no real interrupts, so we can use the normal critical sections */
- #define TRACE_ALLOC_CRITICAL_SECTION()
- #define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL()
- #define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL()
-#endif
-
-#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_POWERPC_Z4)
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
- /* FreeRTOS v8.0 or later */
- #define TRACE_ALLOC_CRITICAL_SECTION() UBaseType_t __irq_status;
- #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = portSET_INTERRUPT_MASK_FROM_ISR();}
- #define TRACE_EXIT_CRITICAL_SECTION() {portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status);}
-#else
- /* FreeRTOS v7.x */
- #define TRACE_ALLOC_CRITICAL_SECTION() unsigned portBASE_TYPE __irq_status;
- #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = portSET_INTERRUPT_MASK_FROM_ISR();}
- #define TRACE_EXIT_CRITICAL_SECTION() {portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status);}
-#endif
-#endif
-
-#ifndef TRACE_ENTER_CRITICAL_SECTION
- #error "This hardware port has no definition for critical sections! See http://percepio.com/2014/10/27/how-to-define-critical-sections-for-the-recorder/"
-#endif
-
-
-#if (TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_9_0_1)
- /******************************************************************************
- * Fix for FreeRTOS v9.0.1 to correctly identify xQueuePeek events.
- *
- * In FreeRTOS v9.0.1, the below trace hooks are incorrectly used from three
- * different functions. This as the earlier function xQueueGenericReceive
- * has been replaced by xQueuePeek, xQueueSemaphoreTake and xQueueReceive.
- *
- * xQueueGenericReceive had a parameter "xJustPeeking", used by the trace hooks
- * to tell between xQueuePeek events and others. This is no longer present, so
- * we need another way to correctly identify peek events. Since all three
- * functions call the same trace macros, the context of these macro is unknown.
- *
- * We therefore check the __LINE__ macro inside of the trace macros. This gives
- * the line number of queue.c, where the macros are used. This can be used to
- * tell if the context is xQueuePeek or another function.
- * __LINE__ is a standard compiler feature since ancient times, so it should
- * work on all common compilers.
- *
- * This might seem as a quite brittle and unusual solution, but works in this
- * particular case and is only for FreeRTOS v9.0.1.
- * Future versions of FreeRTOS should not need this fix, as we have submitted
- * a correction of queue.c with individual trace macros for each function.
- ******************************************************************************/
-#define isQueueReceiveHookActuallyPeek (__LINE__ > 1674) /* Half way between the closes trace points */
-
-#elif (TRC_CFG_FREERTOS_VERSION <= TRC_FREERTOS_VERSION_9_0_0)
-#define isQueueReceiveHookActuallyPeek xJustPeeking
-
-#elif (TRC_CFG_FREERTOS_VERSION > TRC_FREERTOS_VERSION_9_0_1)
-#define isQueueReceiveHookActuallyPeek (__LINE__ < 0) /* instead of pdFALSE to fix a warning of "constant condition" */
-
-#endif
-
-extern uint16_t CurrentFilterMask;
-
-extern uint16_t CurrentFilterGroup;
-
-uint8_t prvTraceGetQueueType(void* handle);
-
-uint16_t prvTraceGetTaskNumberLow16(void* handle);
-uint16_t prvTraceGetTaskNumberHigh16(void* handle);
-void prvTraceSetTaskNumberLow16(void* handle, uint16_t value);
-void prvTraceSetTaskNumberHigh16(void* handle, uint16_t value);
-
-uint16_t prvTraceGetQueueNumberLow16(void* handle);
-uint16_t prvTraceGetQueueNumberHigh16(void* handle);
-void prvTraceSetQueueNumberLow16(void* handle, uint16_t value);
-void prvTraceSetQueueNumberHigh16(void* handle, uint16_t value);
-
-#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-uint16_t prvTraceGetTimerNumberLow16(void* handle);
-uint16_t prvTraceGetTimerNumberHigh16(void* handle);
-void prvTraceSetTimerNumberLow16(void* handle, uint16_t value);
-void prvTraceSetTimerNumberHigh16(void* handle, uint16_t value);
-#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-uint16_t prvTraceGetEventGroupNumberLow16(void* handle);
-uint16_t prvTraceGetEventGroupNumberHigh16(void* handle);
-void prvTraceSetEventGroupNumberLow16(void* handle, uint16_t value);
-void prvTraceSetEventGroupNumberHigh16(void* handle, uint16_t value);
-#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-uint16_t prvTraceGetStreamBufferNumberLow16(void* handle);
-uint16_t prvTraceGetStreamBufferNumberHigh16(void* handle);
-void prvTraceSetStreamBufferNumberLow16(void* handle, uint16_t value);
-void prvTraceSetStreamBufferNumberHigh16(void* handle, uint16_t value);
-#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#define TRACE_GET_TASK_FILTER(pxTask) prvTraceGetTaskNumberHigh16((void*)pxTask)
-#define TRACE_SET_TASK_FILTER(pxTask, group) prvTraceSetTaskNumberHigh16((void*)pxTask, group)
-
-#define TRACE_GET_QUEUE_FILTER(pxObject) prvTraceGetQueueNumberHigh16((void*)pxObject)
-#define TRACE_SET_QUEUE_FILTER(pxObject, group) prvTraceSetQueueNumberHigh16((void*)pxObject, group)
-
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-#define TRACE_GET_EVENTGROUP_FILTER(pxObject) prvTraceGetEventGroupNumberHigh16((void*)pxObject)
-#define TRACE_SET_EVENTGROUP_FILTER(pxObject, group) prvTraceSetEventGroupNumberHigh16((void*)pxObject, group)
-#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-/* FreeRTOS versions before v10.0 does not support filtering for event groups */
-#define TRACE_GET_EVENTGROUP_FILTER(pxObject) 1
-#define TRACE_SET_EVENTGROUP_FILTER(pxObject, group)
-#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-#define TRACE_GET_TIMER_FILTER(pxObject) prvTraceGetTimerNumberHigh16((void*)pxObject)
-#define TRACE_SET_TIMER_FILTER(pxObject, group) prvTraceSetTimerNumberHigh16((void*)pxObject, group)
-#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-/* FreeRTOS versions before v10.0 does not support filtering for timers */
-#define TRACE_GET_TIMER_FILTER(pxObject) 1
-#define TRACE_SET_TIMER_FILTER(pxObject, group)
-#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#define TRACE_GET_STREAMBUFFER_FILTER(pxObject) prvTraceGetStreamBufferNumberHigh16((void*)pxObject)
-#define TRACE_SET_STREAMBUFFER_FILTER(pxObject, group) prvTraceSetStreamBufferNumberHigh16((void*)pxObject, group)
-
-/* We can only support filtering if FreeRTOS is at least v7.4 */
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4)
-#define TRACE_GET_OBJECT_FILTER(CLASS, pxObject) TRACE_GET_##CLASS##_FILTER(pxObject)
-#define TRACE_SET_OBJECT_FILTER(CLASS, pxObject, group) TRACE_SET_##CLASS##_FILTER(pxObject, group)
-#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4) */
-#define TRACE_GET_OBJECT_FILTER(CLASS, pxObject) 1
-#define TRACE_SET_OBJECT_FILTER(CLASS, pxObject, group)
-#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4) */
-
-/******************************************************************************/
-/*** Definitions for Snapshot mode ********************************************/
-/******************************************************************************/
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
-
-/*** The object classes *******************************************************/
-
-#define TRACE_NCLASSES 9
-#define TRACE_CLASS_QUEUE ((traceObjectClass)0)
-#define TRACE_CLASS_SEMAPHORE ((traceObjectClass)1)
-#define TRACE_CLASS_MUTEX ((traceObjectClass)2)
-#define TRACE_CLASS_TASK ((traceObjectClass)3)
-#define TRACE_CLASS_ISR ((traceObjectClass)4)
-#define TRACE_CLASS_TIMER ((traceObjectClass)5)
-#define TRACE_CLASS_EVENTGROUP ((traceObjectClass)6)
-#define TRACE_CLASS_STREAMBUFFER ((traceObjectClass)7)
-#define TRACE_CLASS_MESSAGEBUFFER ((traceObjectClass)8)
-
-/*** Definitions for Object Table ********************************************/
-#define TRACE_KERNEL_OBJECT_COUNT ((TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) + (TRC_CFG_NMESSAGEBUFFER))
-
-/* Queue properties (except name): current number of message in queue */
-#define PropertyTableSizeQueue ((TRC_CFG_NAME_LEN_QUEUE) + 1)
-
-/* Semaphore properties (except name): state (signaled = 1, cleared = 0) */
-#define PropertyTableSizeSemaphore ((TRC_CFG_NAME_LEN_SEMAPHORE) + 1)
-
-/* Mutex properties (except name): owner (task handle, 0 = free) */
-#define PropertyTableSizeMutex ((TRC_CFG_NAME_LEN_MUTEX) + 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 ((TRC_CFG_NAME_LEN_TASK) + 4)
-
-/* ISR properties: Byte 0: priority
- Byte 1: state (if already active) */
-#define PropertyTableSizeISR ((TRC_CFG_NAME_LEN_ISR) + 2)
-
-/* TRC_CFG_NTIMER properties: Byte 0: state (unused for now) */
-#define PropertyTableSizeTimer ((TRC_CFG_NAME_LEN_TIMER) + 1)
-
-/* TRC_CFG_NEVENTGROUP properties: Byte 0-3: state (unused for now)*/
-#define PropertyTableSizeEventGroup ((TRC_CFG_NAME_LEN_EVENTGROUP) + 4)
-
-/* TRC_CFG_NSTREAMBUFFER properties: Byte 0-3: state (unused for now)*/
-#define PropertyTableSizeStreamBuffer ((TRC_CFG_NAME_LEN_STREAMBUFFER) + 4)
-
-/* TRC_CFG_NMESSAGEBUFFER properties: Byte 0-3: state (unused for now)*/
-#define PropertyTableSizeMessageBuffer ((TRC_CFG_NAME_LEN_MESSAGEBUFFER) + 4)
-
-
-/* The layout of the byte array representing the Object Property Table */
-#define StartIndexQueue (0)
-#define StartIndexSemaphore (StartIndexQueue + (TRC_CFG_NQUEUE) * PropertyTableSizeQueue)
-#define StartIndexMutex (StartIndexSemaphore + (TRC_CFG_NSEMAPHORE) * PropertyTableSizeSemaphore)
-#define StartIndexTask (StartIndexMutex + (TRC_CFG_NMUTEX) * PropertyTableSizeMutex)
-#define StartIndexISR (StartIndexTask + (TRC_CFG_NTASK) * PropertyTableSizeTask)
-#define StartIndexTimer (StartIndexISR + (TRC_CFG_NISR) * PropertyTableSizeISR)
-#define StartIndexEventGroup (StartIndexTimer + (TRC_CFG_NTIMER) * PropertyTableSizeTimer)
-#define StartIndexStreamBuffer (StartIndexEventGroup + (TRC_CFG_NEVENTGROUP) * PropertyTableSizeEventGroup)
-#define StartIndexMessageBuffer (StartIndexStreamBuffer + (TRC_CFG_NSTREAMBUFFER) * PropertyTableSizeStreamBuffer)
-
-/* Number of bytes used by the object table */
-#define TRACE_OBJECT_TABLE_SIZE (StartIndexMessageBuffer + (TRC_CFG_NMESSAGEBUFFER) * PropertyTableSizeMessageBuffer)
-
-/* Flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */
-extern int uiInEventGroupSetBitsFromISR;
-
-/* Initialization of the object property table */
-void vTraceInitObjectPropertyTable(void);
-
-/* Initialization of the handle mechanism, see e.g, prvTraceGetObjectHandle */
-void vTraceInitObjectHandleStack(void);
-
-/* Returns the "Not enough handles" error message for the specified object class */
-const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass);
-
-void* prvTraceGetCurrentTaskHandle(void);
-
-/******************************************************************************
- * TraceQueueClassTable
- * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).
- * Has one entry for each QueueType, gives TRACE_CLASS ID.
- ******************************************************************************/
-extern traceObjectClass TraceQueueClassTable[5];
-
-
-/*** Event codes for snapshot mode - must match Tracealyzer config files ******/
-
-#define NULL_EVENT (0x00UL)
-
-/*******************************************************************************
- * EVENTGROUP_DIV
- *
- * Miscellaneous events.
- ******************************************************************************/
-#define EVENTGROUP_DIV (NULL_EVENT + 1UL) /*0x01*/
-#define DIV_XPS (EVENTGROUP_DIV + 0UL) /*0x01*/
-#define DIV_TASK_READY (EVENTGROUP_DIV + 1UL) /*0x02*/
-#define DIV_NEW_TIME (EVENTGROUP_DIV + 2UL) /*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 + 3UL) /*0x04*/
-#define TS_ISR_BEGIN (EVENTGROUP_TS + 0UL) /*0x04*/
-#define TS_ISR_RESUME (EVENTGROUP_TS + 1UL) /*0x05*/
-#define TS_TASK_BEGIN (EVENTGROUP_TS + 2UL) /*0x06*/
-#define TS_TASK_RESUME (EVENTGROUP_TS + 3UL) /*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_TRCSUCCESS (EVENTGROUP_TS + 4UL) /*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_TRCSUCCESS (EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + 8UL) /*0x10*/
-
-/*******************************************************************************
- * EVENTGROUP_CREATE
- *
- * The events in this group are used to log Kernel object creations.
- * The lower three bits in the event code gives the object class, i.e., type of
- * create operation (task, queue, semaphore, etc).
- ******************************************************************************/
-#define EVENTGROUP_CREATE_OBJ_TRCSUCCESS (EVENTGROUP_OBJCLOSE_PROP_TRCSUCCESS + 8UL) /*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_TRCSUCCESS (EVENTGROUP_CREATE_OBJ_TRCSUCCESS + 8UL) /*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_TRCSUCCESS (EVENTGROUP_SEND_TRCSUCCESS + 8UL) /*0x28*/
-
-/* Send/Give operations, from ISR */
-#define EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS \
- (EVENTGROUP_RECEIVE_TRCSUCCESS + 8UL) /*0x30*/
-
-/* Receive/Take operations, from ISR */
-#define EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS \
- (EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS + 8UL) /*0x38*/
-
-/* "Failed" event type versions of above (timeout, failed allocation, etc) */
-#define EVENTGROUP_KSE_TRCFAILED \
- (EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS + 8UL) /*0x40*/
-
-/* Failed create calls - memory allocation failed */
-#define EVENTGROUP_CREATE_OBJ_TRCFAILED (EVENTGROUP_KSE_TRCFAILED) /*0x40*/
-
-/* Failed send/give - timeout! */
-#define EVENTGROUP_SEND_TRCFAILED (EVENTGROUP_CREATE_OBJ_TRCFAILED + 8UL) /*0x48*/
-
-/* Failed receive/take - timeout! */
-#define EVENTGROUP_RECEIVE_TRCFAILED (EVENTGROUP_SEND_TRCFAILED + 8UL) /*0x50*/
-
-/* Failed non-blocking send/give - queue full */
-#define EVENTGROUP_SEND_FROM_ISR_TRCFAILED (EVENTGROUP_RECEIVE_TRCFAILED + 8UL) /*0x58*/
-
-/* Failed non-blocking receive/take - queue empty */
-#define EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED \
- (EVENTGROUP_SEND_FROM_ISR_TRCFAILED + 8UL) /*0x60*/
-
-/* Events when blocking on receive/take */
-#define EVENTGROUP_RECEIVE_TRCBLOCK \
- (EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED + 8UL) /*0x68*/
-
-/* Events when blocking on send/give */
-#define EVENTGROUP_SEND_TRCBLOCK (EVENTGROUP_RECEIVE_TRCBLOCK + 8UL) /*0x70*/
-
-/* Events on queue peek (receive) */
-#define EVENTGROUP_PEEK_TRCSUCCESS (EVENTGROUP_SEND_TRCBLOCK + 8UL) /*0x78*/
-
-/* Events on object delete (vTaskDelete or vQueueDelete) */
-#define EVENTGROUP_DELETE_OBJ_TRCSUCCESS (EVENTGROUP_PEEK_TRCSUCCESS + 8UL) /*0x80*/
-
-/* Other events - object class is implied: TASK */
-#define EVENTGROUP_OTHERS (EVENTGROUP_DELETE_OBJ_TRCSUCCESS + 8UL) /*0x88*/
-#define TASK_DELAY_UNTIL (EVENTGROUP_OTHERS + 0UL) /*0x88*/
-#define TASK_DELAY (EVENTGROUP_OTHERS + 1UL) /*0x89*/
-#define TASK_SUSPEND (EVENTGROUP_OTHERS + 2UL) /*0x8A*/
-#define TASK_RESUME (EVENTGROUP_OTHERS + 3UL) /*0x8B*/
-#define TASK_RESUME_FROM_ISR (EVENTGROUP_OTHERS + 4UL) /*0x8C*/
-#define TASK_PRIORITY_SET (EVENTGROUP_OTHERS + 5UL) /*0x8D*/
-#define TASK_PRIORITY_INHERIT (EVENTGROUP_OTHERS + 6UL) /*0x8E*/
-#define TASK_PRIORITY_DISINHERIT (EVENTGROUP_OTHERS + 7UL) /*0x8F*/
-
-#define EVENTGROUP_MISC_PLACEHOLDER (EVENTGROUP_OTHERS + 8UL) /*0x90*/
-#define PEND_FUNC_CALL (EVENTGROUP_MISC_PLACEHOLDER+0UL) /*0x90*/
-#define PEND_FUNC_CALL_FROM_ISR (EVENTGROUP_MISC_PLACEHOLDER+1UL) /*0x91*/
-#define PEND_FUNC_CALL_TRCFAILED (EVENTGROUP_MISC_PLACEHOLDER+2UL) /*0x92*/
-#define PEND_FUNC_CALL_FROM_ISR_TRCFAILED (EVENTGROUP_MISC_PLACEHOLDER+3UL) /*0x93*/
-#define MEM_MALLOC_SIZE (EVENTGROUP_MISC_PLACEHOLDER+4UL) /*0x94*/
-#define MEM_MALLOC_ADDR (EVENTGROUP_MISC_PLACEHOLDER+5UL) /*0x95*/
-#define MEM_FREE_SIZE (EVENTGROUP_MISC_PLACEHOLDER+6UL) /*0x96*/
-#define MEM_FREE_ADDR (EVENTGROUP_MISC_PLACEHOLDER+7UL) /*0x97*/
-
-/* User events */
-#define EVENTGROUP_USEREVENT (EVENTGROUP_MISC_PLACEHOLDER + 8UL) /*0x98*/
-#define USER_EVENT (EVENTGROUP_USEREVENT + 0UL)
-
-/* Allow for 0-15 arguments (the number of args is added to event code) */
-#define USER_EVENT_LAST (EVENTGROUP_USEREVENT + 15UL) /*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 (255UL). The XTS16 is used when the original event
- * has a 16 bit DTS field and thereby can handle values up to 0xFFFF (65535UL).
- *
- * 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 + 16UL) /*0xA8*/
-#define XTS8 (EVENTGROUP_SYS + 0UL) /*0xA8*/
-#define XTS16 (EVENTGROUP_SYS + 1UL) /*0xA9*/
-#define EVENT_BEING_WRITTEN (EVENTGROUP_SYS + 2UL) /*0xAA*/
-#define RESERVED_DUMMY_CODE (EVENTGROUP_SYS + 3UL) /*0xAB*/
-#define LOW_POWER_BEGIN (EVENTGROUP_SYS + 4UL) /*0xAC*/
-#define LOW_POWER_END (EVENTGROUP_SYS + 5UL) /*0xAD*/
-#define XID (EVENTGROUP_SYS + 6UL) /*0xAE*/
-#define XTS16L (EVENTGROUP_SYS + 7UL) /*0xAF*/
-
-#define EVENTGROUP_TIMER (EVENTGROUP_SYS + 8UL) /*0xB0*/
-#define TIMER_CREATE (EVENTGROUP_TIMER + 0UL) /*0xB0*/
-#define TIMER_START (EVENTGROUP_TIMER + 1UL) /*0xB1*/
-#define TIMER_RST (EVENTGROUP_TIMER + 2UL) /*0xB2*/
-#define TIMER_STOP (EVENTGROUP_TIMER + 3UL) /*0xB3*/
-#define TIMER_CHANGE_PERIOD (EVENTGROUP_TIMER + 4UL) /*0xB4*/
-#define TIMER_DELETE_OBJ (EVENTGROUP_TIMER + 5UL) /*0xB5*/
-#define TIMER_START_FROM_ISR (EVENTGROUP_TIMER + 6UL) /*0xB6*/
-#define TIMER_RESET_FROM_ISR (EVENTGROUP_TIMER + 7UL) /*0xB7*/
-#define TIMER_STOP_FROM_ISR (EVENTGROUP_TIMER + 8UL) /*0xB8*/
-
-#define TIMER_CREATE_TRCFAILED (EVENTGROUP_TIMER + 9UL) /*0xB9*/
-#define TIMER_START_TRCFAILED (EVENTGROUP_TIMER + 10UL) /*0xBA*/
-#define TIMER_RESET_TRCFAILED (EVENTGROUP_TIMER + 11UL) /*0xBB*/
-#define TIMER_STOP_TRCFAILED (EVENTGROUP_TIMER + 12UL) /*0xBC*/
-#define TIMER_CHANGE_PERIOD_TRCFAILED (EVENTGROUP_TIMER + 13UL) /*0xBD*/
-#define TIMER_DELETE_TRCFAILED (EVENTGROUP_TIMER + 14UL) /*0xBE*/
-#define TIMER_START_FROM_ISR_TRCFAILED (EVENTGROUP_TIMER + 15UL) /*0xBF*/
-#define TIMER_RESET_FROM_ISR_TRCFAILED (EVENTGROUP_TIMER + 16UL) /*0xC0*/
-#define TIMER_STOP_FROM_ISR_TRCFAILED (EVENTGROUP_TIMER + 17UL) /*0xC1*/
-
-#define EVENTGROUP_EG (EVENTGROUP_TIMER + 18UL) /*0xC2*/
-#define EVENT_GROUP_CREATE (EVENTGROUP_EG + 0UL) /*0xC2*/
-#define EVENT_GROUP_CREATE_TRCFAILED (EVENTGROUP_EG + 1UL) /*0xC3*/
-#define EVENT_GROUP_SYNC_TRCBLOCK (EVENTGROUP_EG + 2UL) /*0xC4*/
-#define EVENT_GROUP_SYNC_END (EVENTGROUP_EG + 3UL) /*0xC5*/
-#define EVENT_GROUP_WAIT_BITS_TRCBLOCK (EVENTGROUP_EG + 4UL) /*0xC6*/
-#define EVENT_GROUP_WAIT_BITS_END (EVENTGROUP_EG + 5UL) /*0xC7*/
-#define EVENT_GROUP_CLEAR_BITS (EVENTGROUP_EG + 6UL) /*0xC8*/
-#define EVENT_GROUP_CLEAR_BITS_FROM_ISR (EVENTGROUP_EG + 7UL) /*0xC9*/
-#define EVENT_GROUP_SET_BITS (EVENTGROUP_EG + 8UL) /*0xCA*/
-#define EVENT_GROUP_DELETE_OBJ (EVENTGROUP_EG + 9UL) /*0xCB*/
-#define EVENT_GROUP_SYNC_END_TRCFAILED (EVENTGROUP_EG + 10UL) /*0xCC*/
-#define EVENT_GROUP_WAIT_BITS_END_TRCFAILED (EVENTGROUP_EG + 11UL) /*0xCD*/
-#define EVENT_GROUP_SET_BITS_FROM_ISR (EVENTGROUP_EG + 12UL) /*0xCE*/
-#define EVENT_GROUP_SET_BITS_FROM_ISR_TRCFAILED (EVENTGROUP_EG + 13UL) /*0xCF*/
-
-#define TASK_INSTANCE_FINISHED_NEXT_KSE (EVENTGROUP_EG + 14UL) /*0xD0*/
-#define TASK_INSTANCE_FINISHED_DIRECT (EVENTGROUP_EG + 15UL) /*0xD1*/
-
-#define TRACE_TASK_NOTIFY_GROUP (EVENTGROUP_EG + 16UL) /*0xD2*/
-#define TRACE_TASK_NOTIFY (TRACE_TASK_NOTIFY_GROUP + 0UL) /*0xD2*/
-#define TRACE_TASK_NOTIFY_TAKE (TRACE_TASK_NOTIFY_GROUP + 1UL) /*0xD3*/
-#define TRACE_TASK_NOTIFY_TAKE_TRCBLOCK (TRACE_TASK_NOTIFY_GROUP + 2UL) /*0xD4*/
-#define TRACE_TASK_NOTIFY_TAKE_TRCFAILED (TRACE_TASK_NOTIFY_GROUP + 3UL) /*0xD5*/
-#define TRACE_TASK_NOTIFY_WAIT (TRACE_TASK_NOTIFY_GROUP + 4UL) /*0xD6*/
-#define TRACE_TASK_NOTIFY_WAIT_TRCBLOCK (TRACE_TASK_NOTIFY_GROUP + 5UL) /*0xD7*/
-#define TRACE_TASK_NOTIFY_WAIT_TRCFAILED (TRACE_TASK_NOTIFY_GROUP + 6UL) /*0xD8*/
-#define TRACE_TASK_NOTIFY_FROM_ISR (TRACE_TASK_NOTIFY_GROUP + 7UL) /*0xD9*/
-#define TRACE_TASK_NOTIFY_GIVE_FROM_ISR (TRACE_TASK_NOTIFY_GROUP + 8UL) /*0xDA*/
-
-#define TIMER_EXPIRED (TRACE_TASK_NOTIFY_GROUP + 9UL) /* 0xDB */
-
- /* Events on queue peek (receive) */
-#define EVENTGROUP_PEEK_TRCBLOCK (TRACE_TASK_NOTIFY_GROUP + 10UL) /*0xDC*/
-/* peek block on queue: 0xDC */
-/* peek block on semaphore: 0xDD */
-/* peek block on mutex: 0xDE */
-
-/* Events on queue peek (receive) */
-#define EVENTGROUP_PEEK_TRCFAILED (EVENTGROUP_PEEK_TRCBLOCK + 3UL) /*0xDF*/
-/* peek failed on queue: 0xDF */
-/* peek failed on semaphore: 0xE0 */
-/* peek failed on mutex: 0xE1 */
-
-#define EVENTGROUP_STREAMBUFFER_DIV (EVENTGROUP_PEEK_TRCFAILED + 3UL) /*0xE2*/
-#define TRACE_STREAMBUFFER_RESET (EVENTGROUP_STREAMBUFFER_DIV + 0) /*0xE2*/
-#define TRACE_MESSAGEBUFFER_RESET (EVENTGROUP_STREAMBUFFER_DIV + 1UL) /*0xE3*/
-#define TRACE_STREAMBUFFER_OBJCLOSE_NAME_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 2UL) /*0xE4*/
-#define TRACE_MESSAGEBUFFER_OBJCLOSE_NAME_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 3UL) /*0xE5*/
-#define TRACE_STREAMBUFFER_OBJCLOSE_PROP_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 4UL) /*0xE6*/
-#define TRACE_MESSAGEBUFFER_OBJCLOSE_PROP_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 5UL) /*0xE7*/
-
-/* The following are using previously "lost" event codes */
-#define TRACE_STREAMBUFFER_CREATE_OBJ_TRCSUCCESS (EVENTGROUP_CREATE_OBJ_TRCSUCCESS + 4UL) /*0x1C*/
-#define TRACE_STREAMBUFFER_CREATE_OBJ_TRCFAILED (EVENTGROUP_CREATE_OBJ_TRCFAILED + 4UL) /*0x44*/
-#define TRACE_STREAMBUFFER_DELETE_OBJ_TRCSUCCESS (EVENTGROUP_DELETE_OBJ_TRCSUCCESS + 4UL) /*0x84*/
-#define TRACE_STREAMBUFFER_SEND_TRCSUCCESS (EVENTGROUP_SEND_TRCSUCCESS + 3UL) /*0x23*/
-#define TRACE_STREAMBUFFER_SEND_TRCBLOCK (EVENTGROUP_SEND_TRCBLOCK + 3UL) /*0x73*/
-#define TRACE_STREAMBUFFER_SEND_TRCFAILED (EVENTGROUP_SEND_TRCFAILED + 3UL) /*0x4B*/
-#define TRACE_STREAMBUFFER_RECEIVE_TRCSUCCESS (EVENTGROUP_RECEIVE_TRCSUCCESS + 3UL) /*0x2B*/
-#define TRACE_STREAMBUFFER_RECEIVE_TRCBLOCK (EVENTGROUP_RECEIVE_TRCBLOCK + 3UL) /*0x6B*/
-#define TRACE_STREAMBUFFER_RECEIVE_TRCFAILED (EVENTGROUP_RECEIVE_TRCFAILED + 3UL) /*0x53*/
-#define TRACE_STREAMBUFFER_SEND_FROM_ISR_TRCSUCCESS (EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS + 3UL) /*0x33*/
-#define TRACE_STREAMBUFFER_SEND_FROM_ISR_TRCFAILED (EVENTGROUP_SEND_FROM_ISR_TRCFAILED + 3UL) /*0x5B*/
-#define TRACE_STREAMBUFFER_RECEIVE_FROM_ISR_TRCSUCCESS (EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS + 3UL) /*0x3B*/
-#define TRACE_STREAMBUFFER_RECEIVE_FROM_ISR_TRCFAILED (EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED + 3UL) /*0x63*/
-
-/* The following are using previously "lost" event codes. These macros aren't even directly referenced, instead we do (equivalent STREAMBUFFER code) + 1. */
-#define TRACE_MESSAGEBUFFER_CREATE_OBJ_TRCSUCCESS (EVENTGROUP_CREATE_OBJ_TRCSUCCESS + 5UL) /*0x1D*/
-#define TRACE_MESSAGEBUFFER_CREATE_OBJ_TRCFAILED (EVENTGROUP_CREATE_OBJ_TRCFAILED + 5UL) /*0x45*/
-#define TRACE_MESSAGEBUFFER_DELETE_OBJ_TRCSUCCESS (EVENTGROUP_DELETE_OBJ_TRCSUCCESS + 5UL) /*0x85*/
-#define TRACE_MESSAGEBUFFER_SEND_TRCSUCCESS (EVENTGROUP_SEND_TRCSUCCESS + 4UL) /*0x24*/
-#define TRACE_MESSAGEBUFFER_SEND_TRCBLOCK (EVENTGROUP_SEND_TRCBLOCK + 4UL) /*0x74*/
-#define TRACE_MESSAGEBUFFER_SEND_TRCFAILED (EVENTGROUP_SEND_TRCFAILED + 4UL) /*0x4C*/
-#define TRACE_MESSAGEBUFFER_RECEIVE_TRCSUCCESS (EVENTGROUP_RECEIVE_TRCSUCCESS + 4UL) /*0x2C*/
-#define TRACE_MESSAGEBUFFER_RECEIVE_TRCBLOCK (EVENTGROUP_RECEIVE_TRCBLOCK + 4UL) /*0x6C*/
-#define TRACE_MESSAGEBUFFER_RECEIVE_TRCFAILED (EVENTGROUP_RECEIVE_TRCFAILED + 4UL) /*0x54*/
-#define TRACE_MESSAGEBUFFER_SEND_FROM_ISR_TRCSUCCESS (EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS + 4UL) /*0x34*/
-#define TRACE_MESSAGEBUFFER_SEND_FROM_ISR_TRCFAILED (EVENTGROUP_SEND_FROM_ISR_TRCFAILED + 4UL) /*0x5C*/
-#define TRACE_MESSAGEBUFFER_RECEIVE_FROM_ISR_TRCSUCCESS (EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS + 4UL) /*0x3C*/
-#define TRACE_MESSAGEBUFFER_RECEIVE_FROM_ISR_TRCFAILED (EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED + 4UL) /*0x64*/
-
-/* LAST EVENT (0xE7) */
-
-/****************************
-* MACROS TO GET TRACE CLASS *
-****************************/
-#define TRACE_GET_TRACE_CLASS_FROM_TASK_CLASS(kernelClass) (TRACE_CLASS_TASK)
-#define TRACE_GET_TRACE_CLASS_FROM_TASK_OBJECT(pxObject) (TRACE_CLASS_TASK)
-
-#define TRACE_GET_TRACE_CLASS_FROM_QUEUE_CLASS(kernelClass) TraceQueueClassTable[kernelClass]
-#define TRACE_GET_TRACE_CLASS_FROM_QUEUE_OBJECT(pxObject) TRACE_GET_TRACE_CLASS_FROM_QUEUE_CLASS(prvTraceGetQueueType(pxObject))
-
-#define TRACE_GET_TRACE_CLASS_FROM_TIMER_CLASS(kernelClass) (TRACE_CLASS_TIMER)
-#define TRACE_GET_TRACE_CLASS_FROM_TIMER_OBJECT(pxObject) (TRACE_CLASS_TIMER)
-
-#define TRACE_GET_TRACE_CLASS_FROM_EVENTGROUP_CLASS(kernelClass) (TRACE_CLASS_EVENTGROUP)
-#define TRACE_GET_TRACE_CLASS_FROM_EVENTGROUP_OBJECT(pxObject) (TRACE_CLASS_EVENTGROUP)
-
-/* TRACE_GET_TRACE_CLASS_FROM_STREAMBUFFER_CLASS can only be accessed with a parameter indicating if it is a MessageBuffer */
-#define TRACE_GET_TRACE_CLASS_FROM_STREAMBUFFER_CLASS(xIsMessageBuffer) (xIsMessageBuffer == 1 ? TRACE_CLASS_MESSAGEBUFFER : TRACE_CLASS_STREAMBUFFER)
-#define TRACE_GET_TRACE_CLASS_FROM_STREAMBUFFER_OBJECT(pxObject) (prvGetStreamBufferType(pxObject) == 1 ? TRACE_CLASS_MESSAGEBUFFER : TRACE_CLASS_STREAMBUFFER)
-
-/* Generic versions */
-#define TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass) TRACE_GET_TRACE_CLASS_FROM_##CLASS##_CLASS(kernelClass)
-#define TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject) TRACE_GET_TRACE_CLASS_FROM_##CLASS##_OBJECT(pxObject)
-
-/******************************
-* MACROS TO GET OBJECT NUMBER *
-******************************/
-#define TRACE_GET_TASK_NUMBER(pxTCB) (traceHandle)(prvTraceGetTaskNumberLow16(pxTCB))
-#define TRACE_SET_TASK_NUMBER(pxTCB) prvTraceSetTaskNumberLow16(pxTCB, prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(TASK, pxTCB)));
-
-#define TRACE_GET_QUEUE_NUMBER(queue) ( ( traceHandle ) prvTraceGetQueueNumberLow16(queue) )
-#define TRACE_SET_QUEUE_NUMBER(queue) prvTraceSetQueueNumberLow16(queue, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, queue)));
-
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-#define TRACE_GET_TIMER_NUMBER(tmr) ( ( traceHandle ) prvTraceGetTimerNumberLow16(tmr) )
-#define TRACE_SET_TIMER_NUMBER(tmr) prvTraceSetTimerNumberLow16(tmr, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr)));
-#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-#define TRACE_GET_TIMER_NUMBER(tmr) ( ( traceHandle ) ((Timer_t*)tmr)->uxTimerNumber )
-#define TRACE_SET_TIMER_NUMBER(tmr) ((Timer_t*)tmr)->uxTimerNumber = prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr));
-#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-#define TRACE_GET_EVENTGROUP_NUMBER(eg) ( ( traceHandle ) prvTraceGetEventGroupNumberLow16(eg) )
-#define TRACE_SET_EVENTGROUP_NUMBER(eg) prvTraceSetEventGroupNumberLow16(eg, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg)));
-#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-#define TRACE_GET_EVENTGROUP_NUMBER(eg) ( ( traceHandle ) uxEventGroupGetNumber(eg) )
-#define TRACE_SET_EVENTGROUP_NUMBER(eg) ((EventGroup_t*)eg)->uxEventGroupNumber = prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg));
-#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-
-#define TRACE_GET_STREAMBUFFER_NUMBER(sb) ( ( traceHandle ) prvTraceGetStreamBufferNumberLow16(sb) )
-#define TRACE_SET_STREAMBUFFER_NUMBER(sb) prvTraceSetStreamBufferNumberLow16(sb, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(STREAMBUFFER, sb)));
-
-/* Generic versions */
-#define TRACE_GET_OBJECT_NUMBER(CLASS, pxObject) TRACE_GET_##CLASS##_NUMBER(pxObject)
-#define TRACE_SET_OBJECT_NUMBER(CLASS, pxObject) TRACE_SET_##CLASS##_NUMBER(pxObject)
-
-/******************************
-* MACROS TO GET EVENT CODES *
-******************************/
-#define TRACE_GET_TASK_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_CLASS_TRACE_CLASS(TASK, kernelClass))
-#define TRACE_GET_QUEUE_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_CLASS_TRACE_CLASS(QUEUE, kernelClass))
-#define TRACE_GET_TIMER_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) -- THIS IS NOT USED --
-#define TRACE_GET_EVENTGROUP_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) -- THIS IS NOT USED --
-#define TRACE_GET_STREAMBUFFER_CLASS_EVENT_CODE(SERVICE, RESULT, isMessageBuffer) (uint8_t)(TRACE_STREAMBUFFER_##SERVICE##_##RESULT + (uint8_t)isMessageBuffer)
-
-#define TRACE_GET_TASK_OBJECT_EVENT_CODE(SERVICE, RESULT, pxTCB) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_CLASS_TASK)
-#define TRACE_GET_QUEUE_OBJECT_EVENT_CODE(SERVICE, RESULT, pxObject) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxObject))
-#define TRACE_GET_TIMER_OBJECT_EVENT_CODE(SERVICE, RESULT, UNUSED) -- THIS IS NOT USED --
-#define TRACE_GET_EVENTGROUP_OBJECT_EVENT_CODE(SERVICE, RESULT, UNUSED) -- THIS IS NOT USED --
-#define TRACE_GET_STREAMBUFFER_OBJECT_EVENT_CODE(SERVICE, RESULT, pxObject) (uint8_t)(TRACE_STREAMBUFFER_##SERVICE##_##RESULT + prvGetStreamBufferType(pxObject))
-
-/* Generic versions */
-#define TRACE_GET_CLASS_EVENT_CODE(SERVICE, RESULT, CLASS, kernelClass) TRACE_GET_##CLASS##_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass)
-#define TRACE_GET_OBJECT_EVENT_CODE(SERVICE, RESULT, CLASS, pxObject) TRACE_GET_##CLASS##_OBJECT_EVENT_CODE(SERVICE, RESULT, pxObject)
-
-/******************************
-* SPECIAL MACROS FOR TASKS *
-******************************/
-#define TRACE_GET_TASK_PRIORITY(pxTCB) ((uint8_t)pxTCB->uxPriority)
-#define TRACE_GET_TASK_NAME(pxTCB) ((char*)pxTCB->pcTaskName)
-
-/*** The trace macros for snapshot mode **************************************/
-
-/* A macro that will update the tick count when returning from tickless idle */
-#undef traceINCREASE_TICK_COUNT
-#define traceINCREASE_TICK_COUNT( xCount )
-
-/* 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
-
-#if (TRC_CFG_FREERTOS_VERSION <= TRC_FREERTOS_VERSION_7_4)
-
-#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); }
-
-#else
-
-#define traceTASK_INCREMENT_TICK( xTickCount ) \
- if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || xPendedTicks == 0) { trcKERNEL_HOOKS_INCREMENT_TICK(); } \
- if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE) { trcKERNEL_HOOKS_NEW_TIME(DIV_NEW_TIME, xTickCount + 1); }
-
-#endif
-
-/* Called on each task-switch */
-#undef traceTASK_SWITCHED_IN
-#define traceTASK_SWITCHED_IN() \
- trcKERNEL_HOOKS_TASK_SWITCH(TRACE_GET_CURRENT_TASK());
-
-/* Called on vTaskCreate */
-#undef traceTASK_CREATE
-#define traceTASK_CREATE(pxNewTCB) \
- if (pxNewTCB != NULL) \
- { \
- trcKERNEL_HOOKS_TASK_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, TASK, pxNewTCB), TASK, pxNewTCB); \
- }
-
-/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */
-#undef traceTASK_CREATE_FAILED
-#define traceTASK_CREATE_FAILED() \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, TASK, NOT_USED), 0);
-
-/* Called on vTaskDelete */
-#undef traceTASK_DELETE
-#define traceTASK_DELETE( pxTaskToDelete ) \
- { TRACE_ALLOC_CRITICAL_SECTION(); \
- TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_TASK_DELETE(TRACE_GET_OBJECT_EVENT_CODE(DELETE_OBJ, TRCSUCCESS, TASK, pxTaskToDelete), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_NAME, TRCSUCCESS, TASK, pxTaskToDelete), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_PROP, TRCSUCCESS, TASK, pxTaskToDelete), pxTaskToDelete); \
- TRACE_EXIT_CRITICAL_SECTION(); }
-
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-
-#if defined(configUSE_TICKLESS_IDLE)
-#if (configUSE_TICKLESS_IDLE != 0)
-
-#undef traceLOW_POWER_IDLE_BEGIN
-#define traceLOW_POWER_IDLE_BEGIN() \
- { \
- extern uint32_t trace_disable_timestamp; \
- prvTraceStoreLowPower(0); \
- trace_disable_timestamp = 1; \
- }
-
-#undef traceLOW_POWER_IDLE_END
-#define traceLOW_POWER_IDLE_END() \
- { \
- extern uint32_t trace_disable_timestamp; \
- trace_disable_timestamp = 0; \
- prvTraceStoreLowPower(1); \
- }
-
-#endif /* (configUSE_TICKLESS_IDLE != 0) */
-#endif /* defined(configUSE_TICKLESS_IDLE) */
-
-/* Called on vTaskSuspend */
-#undef traceTASK_SUSPEND
-#define traceTASK_SUSPEND( pxTaskToSuspend ) \
- trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend);
-
-/* Called from special case with timer only */
-#undef traceTASK_DELAY_SUSPEND
-#define traceTASK_DELAY_SUSPEND( pxTaskToSuspend ) \
- trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend); \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
-
-/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */
-#undef traceTASK_DELAY
-#define traceTASK_DELAY() \
- trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY, pxCurrentTCB, xTicksToDelay); \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
-
-/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */
-#undef traceTASK_DELAY_UNTIL
-#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0
-#define traceTASK_DELAY_UNTIL(xTimeToWake) \
- trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
-#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */
-#define traceTASK_DELAY_UNTIL() \
- trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
-#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */
-
-/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */
-#undef traceQUEUE_CREATE
-#define traceQUEUE_CREATE( pxNewQueue ) \
- trcKERNEL_HOOKS_OBJECT_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, QUEUE, pxNewQueue), QUEUE, pxNewQueue);
-
-/* Called in xQueueCreate, if the queue creation fails */
-#undef traceQUEUE_CREATE_FAILED
-#define traceQUEUE_CREATE_FAILED( queueType ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, QUEUE, queueType), 0);
-
-/* Called on vQueueDelete */
-#undef traceQUEUE_DELETE
-#define traceQUEUE_DELETE( pxQueue ) \
- { TRACE_ALLOC_CRITICAL_SECTION(); \
- TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_OBJECT_DELETE(TRACE_GET_OBJECT_EVENT_CODE(DELETE_OBJ, TRCSUCCESS, QUEUE, pxQueue), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_NAME, TRCSUCCESS, QUEUE, pxQueue), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_PROP, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \
- TRACE_EXIT_CRITICAL_SECTION(); }
-
-/* This macro is not necessary as of FreeRTOS v9.0.0 */
-#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0)
-/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */
-#undef traceCREATE_MUTEX
-#define traceCREATE_MUTEX( pxNewQueue ) \
- trcKERNEL_HOOKS_OBJECT_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, QUEUE, pxNewQueue), QUEUE, pxNewQueue);
-
-/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */
-#undef traceCREATE_MUTEX_FAILED
-#define traceCREATE_MUTEX_FAILED() \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, QUEUE, queueQUEUE_TYPE_MUTEX), 0);
-#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */
-
-/* Called when the Mutex can not be given, since not holder */
-#undef traceGIVE_MUTEX_RECURSIVE_FAILED
-#define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCFAILED, QUEUE, pxMutex), QUEUE, pxMutex);
-
-/* Called when a message is sent to a queue */ /* CS IS NEW ! */
-#undef traceQUEUE_SEND
-#define traceQUEUE_SEND( pxQueue ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) == TRACE_CLASS_MUTEX ? (uint8_t)0 : (uint8_t)(pxQueue->uxMessagesWaiting + 1));
-
-/* Called when a message failed to be sent to a queue (timeout) */
-#undef traceQUEUE_SEND_FAILED
-#define traceQUEUE_SEND_FAILED( pxQueue ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue);
-
-/* Called when the task is blocked due to a send operation on a full queue */
-#undef traceBLOCKING_ON_QUEUE_SEND
-#define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue);
-
-/* Called when a message is received from a queue */
-#undef traceQUEUE_RECEIVE
-#define traceQUEUE_RECEIVE( pxQueue ) \
- if (isQueueReceiveHookActuallyPeek) \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \
- } \
- else \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \
- } \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) == TRACE_CLASS_MUTEX ? (uint8_t)TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()) : (uint8_t)(pxQueue->uxMessagesWaiting - 1));
-
-/* Called when a receive operation on a queue fails (timeout) */
-#undef traceQUEUE_RECEIVE_FAILED
-#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \
- if (isQueueReceiveHookActuallyPeek) \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); \
- } \
- else \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); \
- }
-
-/* Called when the task is blocked due to a receive operation on an empty queue */
-#undef traceBLOCKING_ON_QUEUE_RECEIVE
-#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \
- if (isQueueReceiveHookActuallyPeek) \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue); \
- } \
- else \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue); \
- } \
- if (TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) != TRACE_CLASS_MUTEX) \
- { \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); \
- }
-
-/* Called on xQueuePeek */
-#undef traceQUEUE_PEEK
-#define traceQUEUE_PEEK( pxQueue ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue);
-
-/* Called on xQueuePeek fail/timeout (added in FreeRTOS v9.0.2) */
-#undef traceQUEUE_PEEK_FAILED
-#define traceQUEUE_PEEK_FAILED( pxQueue ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue);
-
-/* Called on xQueuePeek blocking (added in FreeRTOS v9.0.2) */
-#undef traceBLOCKING_ON_QUEUE_PEEK
-#define traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue); \
- if (TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) != TRACE_CLASS_MUTEX) \
- { \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); \
- }
-
-/* 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_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, 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_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCFAILED, QUEUE, pxQueue), QUEUE, 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_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, 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_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue);
-
-#undef traceQUEUE_REGISTRY_ADD
-#define traceQUEUE_REGISTRY_ADD(object, name) prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, object), TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);
-
-/* 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_FROM_ISR(TASK_RESUME_FROM_ISR, pxTaskToResume);
-
-
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
-
-#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1)
-
-extern void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t size);
-
-/* MALLOC and FREE are always stored, no matter if they happen inside filtered task */
-#undef traceMALLOC
-#define traceMALLOC( pvAddress, uiSize ) \
- if (pvAddress != 0) \
- vTraceStoreMemMangEvent(MEM_MALLOC_SIZE, ( uint32_t ) pvAddress, (int32_t)uiSize);
-
-#undef traceFREE
-#define traceFREE( pvAddress, uiSize ) \
- vTraceStoreMemMangEvent(MEM_FREE_SIZE, ( uint32_t ) pvAddress, -((int32_t)uiSize));
-
-#endif /* (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) */
-
-#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1)
-
-/* Called in timer.c - xTimerCreate */
-#undef traceTIMER_CREATE
-#define traceTIMER_CREATE(tmr) \
- trcKERNEL_HOOKS_OBJECT_CREATE(TIMER_CREATE, TIMER, tmr);
-
-#undef traceTIMER_CREATE_FAILED
-#define traceTIMER_CREATE_FAILED() \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TIMER_CREATE_TRCFAILED, 0);
-
-/* Note that xCommandID can never be tmrCOMMAND_EXECUTE_CALLBACK (-1) since the trace macro is not called in that case */
-#undef traceTIMER_COMMAND_SEND
-#define traceTIMER_COMMAND_SEND(tmr, xCommandID, xOptionalValue, xReturn) \
- if (xCommandID > tmrCOMMAND_START_DONT_TRACE) \
- { \
- if (xCommandID == tmrCOMMAND_CHANGE_PERIOD) \
- { \
- if (xReturn == pdPASS) { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TIMER_CHANGE_PERIOD, TIMER, tmr, xOptionalValue); \
- } \
- else \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TIMER_CHANGE_PERIOD_TRCFAILED, TIMER, tmr, xOptionalValue); \
- } \
- } \
- else if ((xCommandID == tmrCOMMAND_DELETE) && (xReturn == pdPASS)) \
- { \
- trcKERNEL_HOOKS_OBJECT_DELETE(TIMER_DELETE_OBJ, EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr), EVENTGROUP_OBJCLOSE_PROP_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr), TIMER, tmr); \
- } \
- else \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENTGROUP_TIMER + (uint32_t)xCommandID + ((xReturn == pdPASS) ? 0 : (TIMER_CREATE_TRCFAILED - TIMER_CREATE)), TIMER, tmr, xOptionalValue); \
- }\
- }
-
-#undef traceTIMER_EXPIRED
-#define traceTIMER_EXPIRED(tmr) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TIMER_EXPIRED, TIMER, tmr);
-
-#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) */
-
-#if (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1)
-
-#undef tracePEND_FUNC_CALL
-#define tracePEND_FUNC_CALL(func, arg1, arg2, ret) \
- if (ret == pdPASS){ \
- trcKERNEL_HOOKS_KERNEL_SERVICE(PEND_FUNC_CALL, TASK, xTimerGetTimerDaemonTaskHandle() ); \
- } \
- else \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE(PEND_FUNC_CALL_TRCFAILED, TASK, xTimerGetTimerDaemonTaskHandle() ); \
- }
-
-#undef tracePEND_FUNC_CALL_FROM_ISR
-#define tracePEND_FUNC_CALL_FROM_ISR(func, arg1, arg2, ret) \
- if (! uiInEventGroupSetBitsFromISR) \
- prvTraceStoreKernelCall(PEND_FUNC_CALL_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTimerGetTimerDaemonTaskHandle()) ); \
- uiInEventGroupSetBitsFromISR = 0;
-
-#endif /* (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) */
-
-#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
-
-#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1)
-
-#undef traceEVENT_GROUP_CREATE
-#define traceEVENT_GROUP_CREATE(eg) \
- trcKERNEL_HOOKS_OBJECT_CREATE(EVENT_GROUP_CREATE, EVENTGROUP, eg);
-
-#undef traceEVENT_GROUP_CREATE_FAILED
-#define traceEVENT_GROUP_CREATE_FAILED() \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(EVENT_GROUP_CREATE_TRCFAILED, 0);
-
-#undef traceEVENT_GROUP_DELETE
-#define traceEVENT_GROUP_DELETE(eg) \
- { TRACE_ALLOC_CRITICAL_SECTION(); \
- TRACE_ENTER_CRITICAL_SECTION(); \
- trcKERNEL_HOOKS_OBJECT_DELETE(EVENT_GROUP_DELETE_OBJ, EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg), EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg), EVENTGROUP, eg); \
- TRACE_EXIT_CRITICAL_SECTION(); }
-
-#undef traceEVENT_GROUP_SYNC_BLOCK
-#define traceEVENT_GROUP_SYNC_BLOCK(eg, bitsToSet, bitsToWaitFor) \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SYNC_TRCBLOCK, EVENTGROUP, eg, bitsToWaitFor);
-
-#undef traceEVENT_GROUP_SYNC_END
-#define traceEVENT_GROUP_SYNC_END(eg, bitsToSet, bitsToWaitFor, wasTimeout) \
- if (wasTimeout) \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SYNC_END_TRCFAILED, EVENTGROUP, eg, bitsToWaitFor); \
- } \
- else \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SYNC_END, EVENTGROUP, eg, bitsToWaitFor); \
- }
-
-#undef traceEVENT_GROUP_WAIT_BITS_BLOCK
-#define traceEVENT_GROUP_WAIT_BITS_BLOCK(eg, bitsToWaitFor) \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_WAIT_BITS_TRCBLOCK, EVENTGROUP, eg, bitsToWaitFor); \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
-
-#undef traceEVENT_GROUP_WAIT_BITS_END
-#define traceEVENT_GROUP_WAIT_BITS_END(eg, bitsToWaitFor, wasTimeout) \
- if (wasTimeout) \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_WAIT_BITS_END_TRCFAILED, EVENTGROUP, eg, bitsToWaitFor); \
- } \
- else \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_WAIT_BITS_END, EVENTGROUP, eg, bitsToWaitFor); \
- }
-
-#undef traceEVENT_GROUP_CLEAR_BITS
-#define traceEVENT_GROUP_CLEAR_BITS(eg, bitsToClear) \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_CLEAR_BITS, EVENTGROUP, eg, bitsToClear);
-
-#undef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR
-#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(eg, bitsToClear) \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(EVENT_GROUP_CLEAR_BITS_FROM_ISR, EVENTGROUP, eg, bitsToClear);
-
-#undef traceEVENT_GROUP_SET_BITS
-#define traceEVENT_GROUP_SET_BITS(eg, bitsToSet) \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SET_BITS, EVENTGROUP, eg, bitsToSet);
-
-#undef traceEVENT_GROUP_SET_BITS_FROM_ISR
-#define traceEVENT_GROUP_SET_BITS_FROM_ISR(eg, bitsToSet) \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(EVENT_GROUP_SET_BITS_FROM_ISR, EVENTGROUP, eg, bitsToSet); \
- uiInEventGroupSetBitsFromISR = 1;
-
-#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */
-
-#undef traceTASK_NOTIFY_TAKE
-#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0)
-#define traceTASK_NOTIFY_TAKE() \
- if (pxCurrentTCB->eNotifyState == eNotified){ \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE, TASK, pxCurrentTCB, xTicksToWait); \
- } \
- else{ \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCFAILED, TASK, pxCurrentTCB, xTicksToWait); \
- }
-#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */
-#define traceTASK_NOTIFY_TAKE( index ) \
- if (pxCurrentTCB->ucNotifyState[ ( index ) ] == taskNOTIFICATION_RECEIVED){ \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE, TASK, pxCurrentTCB, xTicksToWait); \
- }else{ \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCFAILED, TASK, pxCurrentTCB, xTicksToWait);}
-#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */
-
-#undef traceTASK_NOTIFY_TAKE_BLOCK
-#define traceTASK_NOTIFY_TAKE_BLOCK() \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCBLOCK, TASK, pxCurrentTCB, xTicksToWait); \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
-
-#undef traceTASK_NOTIFY_WAIT
-#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0)
-#define traceTASK_NOTIFY_WAIT() \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \
- { \
- if (pxCurrentTCB->eNotifyState == eNotified) \
- prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \
- else \
- prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCFAILED, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \
- }
-#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */
-#define traceTASK_NOTIFY_WAIT( index ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \
- { \
- if (pxCurrentTCB->ucNotifyState[ ( index ) ] == taskNOTIFICATION_RECEIVED) \
- prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \
- else \
- prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCFAILED, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \
- }
-#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */
-
-#undef traceTASK_NOTIFY_WAIT_BLOCK
-#define traceTASK_NOTIFY_WAIT_BLOCK() \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \
- prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCBLOCK, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \
- trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
-
-#undef traceTASK_NOTIFY
-#define traceTASK_NOTIFY() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \
- prvTraceStoreKernelCall(TRACE_TASK_NOTIFY, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify));
-
-#undef traceTASK_NOTIFY_FROM_ISR
-#define traceTASK_NOTIFY_FROM_ISR() \
- if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \
- prvTraceStoreKernelCall(TRACE_TASK_NOTIFY_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify));
-
-#undef traceTASK_NOTIFY_GIVE_FROM_ISR
-#define traceTASK_NOTIFY_GIVE_FROM_ISR() \
- if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \
- prvTraceStoreKernelCall(TRACE_TASK_NOTIFY_GIVE_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify));
-
-#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1)
-
-#undef traceSTREAM_BUFFER_CREATE
-#define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) \
- trcKERNEL_HOOKS_OBJECT_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, STREAMBUFFER, pxStreamBuffer), STREAMBUFFER, pxStreamBuffer);
-
-#undef traceSTREAM_BUFFER_CREATE_FAILED
-#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, STREAMBUFFER, xIsMessageBuffer), 0);
-
-#undef traceSTREAM_BUFFER_CREATE_STATIC_FAILED
-#define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ) \
- traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer )
-
-#undef traceSTREAM_BUFFER_DELETE
-#define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) \
- trcKERNEL_HOOKS_OBJECT_DELETE(TRACE_GET_OBJECT_EVENT_CODE(DELETE_OBJ, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_NAME, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_PROP, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer);
-
-#undef traceSTREAM_BUFFER_RESET
-#define traceSTREAM_BUFFER_RESET( xStreamBuffer ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(prvGetStreamBufferType(xStreamBuffer) > 0 ? TRACE_MESSAGEBUFFER_RESET : TRACE_STREAMBUFFER_RESET, STREAMBUFFER, xStreamBuffer); \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, 0);
-
-#undef traceSTREAM_BUFFER_SEND
-#define traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer));
-
-#undef traceBLOCKING_ON_STREAM_BUFFER_SEND
-#define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCBLOCK, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer);
-
-#undef traceSTREAM_BUFFER_SEND_FAILED
-#define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer);
-
-#undef traceSTREAM_BUFFER_RECEIVE
-#define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer));
-
-
-#undef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE
-#define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCBLOCK, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer);
-
-#undef traceSTREAM_BUFFER_RECEIVE_FAILED
-#define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) \
- trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer);
-
-#undef traceSTREAM_BUFFER_SEND_FROM_ISR
-#define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ) \
- if( xReturn > ( size_t ) 0 ) \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \
- } \
- else \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \
- }
-
-#undef traceSTREAM_BUFFER_RECEIVE_FROM_ISR
-#define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) \
- if( xReceivedLength > ( size_t ) 0 ) \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \
- trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \
- } \
- else \
- { \
- trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \
- }
-
-#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */
-
-#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */
-
-#endif /*#if TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT */
-
-/******************************************************************************/
-/*** Definitions for Streaming mode *******************************************/
-/******************************************************************************/
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-
-/*******************************************************************************
-* vTraceStoreKernelObjectName
-*
-* Set the name for a kernel object (defined by its address).
-******************************************************************************/
-void vTraceStoreKernelObjectName(void* object, const char* name);
-
-/*******************************************************************************
-* prvIsNewTCB
-*
-* Tells if this task is already executing, or if there has been a task-switch.
-* Assumed to be called within a trace hook in kernel context.
-*******************************************************************************/
-uint32_t prvIsNewTCB(void* pNewTCB);
-
-#define TRACE_GET_CURRENT_TASK() prvTraceGetCurrentTaskHandle()
-
-/*************************************************************************/
-/* KERNEL SPECIFIC OBJECT CONFIGURATION */
-/*************************************************************************/
-
-/*******************************************************************************
- * The event codes - should match the offline config file.
- ******************************************************************************/
-
-/*** Event codes for streaming - should match the Tracealyzer config file *****/
-#define PSF_EVENT_NULL_EVENT 0x00
-
-#define PSF_EVENT_TRACE_START 0x01
-#define PSF_EVENT_TS_CONFIG 0x02
-#define PSF_EVENT_OBJ_NAME 0x03
-#define PSF_EVENT_TASK_PRIORITY 0x04
-#define PSF_EVENT_TASK_PRIO_INHERIT 0x05
-#define PSF_EVENT_TASK_PRIO_DISINHERIT 0x06
-#define PSF_EVENT_DEFINE_ISR 0x07
-
-#define PSF_EVENT_TASK_CREATE 0x10
-#define PSF_EVENT_QUEUE_CREATE 0x11
-#define PSF_EVENT_SEMAPHORE_BINARY_CREATE 0x12
-#define PSF_EVENT_MUTEX_CREATE 0x13
-#define PSF_EVENT_TIMER_CREATE 0x14
-#define PSF_EVENT_EVENTGROUP_CREATE 0x15
-#define PSF_EVENT_SEMAPHORE_COUNTING_CREATE 0x16
-#define PSF_EVENT_MUTEX_RECURSIVE_CREATE 0x17
-#define PSF_EVENT_STREAMBUFFER_CREATE 0x18
-#define PSF_EVENT_MESSAGEBUFFER_CREATE 0x19
-
-#define PSF_EVENT_TASK_DELETE 0x20
-#define PSF_EVENT_QUEUE_DELETE 0x21
-#define PSF_EVENT_SEMAPHORE_DELETE 0x22
-#define PSF_EVENT_MUTEX_DELETE 0x23
-#define PSF_EVENT_TIMER_DELETE 0x24
-#define PSF_EVENT_EVENTGROUP_DELETE 0x25
-#define PSF_EVENT_STREAMBUFFER_DELETE 0x28
-#define PSF_EVENT_MESSAGEBUFFER_DELETE 0x29
-
-#define PSF_EVENT_TASK_READY 0x30
-#define PSF_EVENT_NEW_TIME 0x31
-#define PSF_EVENT_NEW_TIME_SCHEDULER_SUSPENDED 0x32
-#define PSF_EVENT_ISR_BEGIN 0x33
-#define PSF_EVENT_ISR_RESUME 0x34
-#define PSF_EVENT_TS_BEGIN 0x35
-#define PSF_EVENT_TS_RESUME 0x36
-#define PSF_EVENT_TASK_ACTIVATE 0x37
-
-#define PSF_EVENT_MALLOC 0x38
-#define PSF_EVENT_FREE 0x39
-
-#define PSF_EVENT_LOWPOWER_BEGIN 0x3A
-#define PSF_EVENT_LOWPOWER_END 0x3B
-
-#define PSF_EVENT_IFE_NEXT 0x3C
-#define PSF_EVENT_IFE_DIRECT 0x3D
-
-#define PSF_EVENT_TASK_CREATE_FAILED 0x40
-#define PSF_EVENT_QUEUE_CREATE_FAILED 0x41
-#define PSF_EVENT_SEMAPHORE_BINARY_CREATE_FAILED 0x42
-#define PSF_EVENT_MUTEX_CREATE_FAILED 0x43
-#define PSF_EVENT_TIMER_CREATE_FAILED 0x44
-#define PSF_EVENT_EVENTGROUP_CREATE_FAILED 0x45
-#define PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED 0x46
-#define PSF_EVENT_MUTEX_RECURSIVE_CREATE_FAILED 0x47
-#define PSF_EVENT_STREAMBUFFER_CREATE_FAILED 0x49
-#define PSF_EVENT_MESSAGEBUFFER_CREATE_FAILED 0x4A
-
-#define PSF_EVENT_TIMER_DELETE_FAILED 0x48
-
-#define PSF_EVENT_QUEUE_SEND 0x50
-#define PSF_EVENT_SEMAPHORE_GIVE 0x51
-#define PSF_EVENT_MUTEX_GIVE 0x52
-
-#define PSF_EVENT_QUEUE_SEND_FAILED 0x53
-#define PSF_EVENT_SEMAPHORE_GIVE_FAILED 0x54
-#define PSF_EVENT_MUTEX_GIVE_FAILED 0x55
-
-#define PSF_EVENT_QUEUE_SEND_BLOCK 0x56
-#define PSF_EVENT_SEMAPHORE_GIVE_BLOCK 0x57
-#define PSF_EVENT_MUTEX_GIVE_BLOCK 0x58
-
-#define PSF_EVENT_QUEUE_SEND_FROMISR 0x59
-#define PSF_EVENT_SEMAPHORE_GIVE_FROMISR 0x5A
-
-#define PSF_EVENT_QUEUE_SEND_FROMISR_FAILED 0x5C
-#define PSF_EVENT_SEMAPHORE_GIVE_FROMISR_FAILED 0x5D
-
-#define PSF_EVENT_QUEUE_RECEIVE 0x60
-#define PSF_EVENT_SEMAPHORE_TAKE 0x61
-#define PSF_EVENT_MUTEX_TAKE 0x62
-
-#define PSF_EVENT_QUEUE_RECEIVE_FAILED 0x63
-#define PSF_EVENT_SEMAPHORE_TAKE_FAILED 0x64
-#define PSF_EVENT_MUTEX_TAKE_FAILED 0x65
-
-#define PSF_EVENT_QUEUE_RECEIVE_BLOCK 0x66
-#define PSF_EVENT_SEMAPHORE_TAKE_BLOCK 0x67
-#define PSF_EVENT_MUTEX_TAKE_BLOCK 0x68
-
-#define PSF_EVENT_QUEUE_RECEIVE_FROMISR 0x69
-#define PSF_EVENT_SEMAPHORE_TAKE_FROMISR 0x6A
-
-#define PSF_EVENT_QUEUE_RECEIVE_FROMISR_FAILED 0x6C
-#define PSF_EVENT_SEMAPHORE_TAKE_FROMISR_FAILED 0x6D
-
-#define PSF_EVENT_QUEUE_PEEK 0x70
-#define PSF_EVENT_SEMAPHORE_PEEK 0x71
-#define PSF_EVENT_MUTEX_PEEK 0x72
-
-#define PSF_EVENT_QUEUE_PEEK_FAILED 0x73
-#define PSF_EVENT_SEMAPHORE_PEEK_FAILED 0x74
-#define PSF_EVENT_MUTEX_PEEK_FAILED 0x75
-
-#define PSF_EVENT_QUEUE_PEEK_BLOCK 0x76
-#define PSF_EVENT_SEMAPHORE_PEEK_BLOCK 0x77
-#define PSF_EVENT_MUTEX_PEEK_BLOCK 0x78
-
-#define PSF_EVENT_TASK_DELAY_UNTIL 0x79
-#define PSF_EVENT_TASK_DELAY 0x7A
-#define PSF_EVENT_TASK_SUSPEND 0x7B
-#define PSF_EVENT_TASK_RESUME 0x7C
-#define PSF_EVENT_TASK_RESUME_FROMISR 0x7D
-
-#define PSF_EVENT_TIMER_PENDFUNCCALL 0x80
-#define PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR 0x81
-#define PSF_EVENT_TIMER_PENDFUNCCALL_FAILED 0x82
-#define PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR_FAILED 0x83
-
-#define PSF_EVENT_USER_EVENT 0x90
-
-#define PSF_EVENT_TIMER_START 0xA0
-#define PSF_EVENT_TIMER_RESET 0xA1
-#define PSF_EVENT_TIMER_STOP 0xA2
-#define PSF_EVENT_TIMER_CHANGEPERIOD 0xA3
-#define PSF_EVENT_TIMER_START_FROMISR 0xA4
-#define PSF_EVENT_TIMER_RESET_FROMISR 0xA5
-#define PSF_EVENT_TIMER_STOP_FROMISR 0xA6
-#define PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR 0xA7
-#define PSF_EVENT_TIMER_START_FAILED 0xA8
-#define PSF_EVENT_TIMER_RESET_FAILED 0xA9
-#define PSF_EVENT_TIMER_STOP_FAILED 0xAA
-#define PSF_EVENT_TIMER_CHANGEPERIOD_FAILED 0xAB
-#define PSF_EVENT_TIMER_START_FROMISR_FAILED 0xAC
-#define PSF_EVENT_TIMER_RESET_FROMISR_FAILED 0xAD
-#define PSF_EVENT_TIMER_STOP_FROMISR_FAILED 0xAE
-#define PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR_FAILED 0xAF
-
-#define PSF_EVENT_EVENTGROUP_SYNC 0xB0
-#define PSF_EVENT_EVENTGROUP_WAITBITS 0xB1
-#define PSF_EVENT_EVENTGROUP_CLEARBITS 0xB2
-#define PSF_EVENT_EVENTGROUP_CLEARBITS_FROMISR 0xB3
-#define PSF_EVENT_EVENTGROUP_SETBITS 0xB4
-#define PSF_EVENT_EVENTGROUP_SETBITS_FROMISR 0xB5
-#define PSF_EVENT_EVENTGROUP_SYNC_BLOCK 0xB6
-#define PSF_EVENT_EVENTGROUP_WAITBITS_BLOCK 0xB7
-#define PSF_EVENT_EVENTGROUP_SYNC_FAILED 0xB8
-#define PSF_EVENT_EVENTGROUP_WAITBITS_FAILED 0xB9
-
-#define PSF_EVENT_QUEUE_SEND_FRONT 0xC0
-#define PSF_EVENT_QUEUE_SEND_FRONT_FAILED 0xC1
-#define PSF_EVENT_QUEUE_SEND_FRONT_BLOCK 0xC2
-#define PSF_EVENT_QUEUE_SEND_FRONT_FROMISR 0xC3
-#define PSF_EVENT_QUEUE_SEND_FRONT_FROMISR_FAILED 0xC4
-#define PSF_EVENT_MUTEX_GIVE_RECURSIVE 0xC5
-#define PSF_EVENT_MUTEX_GIVE_RECURSIVE_FAILED 0xC6
-#define PSF_EVENT_MUTEX_TAKE_RECURSIVE 0xC7
-#define PSF_EVENT_MUTEX_TAKE_RECURSIVE_FAILED 0xC8
-
-#define PSF_EVENT_TASK_NOTIFY 0xC9
-#define PSF_EVENT_TASK_NOTIFY_TAKE 0xCA
-#define PSF_EVENT_TASK_NOTIFY_TAKE_BLOCK 0xCB
-#define PSF_EVENT_TASK_NOTIFY_TAKE_FAILED 0xCC
-#define PSF_EVENT_TASK_NOTIFY_WAIT 0xCD
-#define PSF_EVENT_TASK_NOTIFY_WAIT_BLOCK 0xCE
-#define PSF_EVENT_TASK_NOTIFY_WAIT_FAILED 0xCF
-#define PSF_EVENT_TASK_NOTIFY_FROM_ISR 0xD0
-#define PSF_EVENT_TASK_NOTIFY_GIVE_FROM_ISR 0xD1
-
-#define PSF_EVENT_TIMER_EXPIRED 0xD2
-
-#define PSF_EVENT_STREAMBUFFER_SEND 0xD3
-#define PSF_EVENT_STREAMBUFFER_SEND_BLOCK 0xD4
-#define PSF_EVENT_STREAMBUFFER_SEND_FAILED 0xD5
-#define PSF_EVENT_STREAMBUFFER_RECEIVE 0xD6
-#define PSF_EVENT_STREAMBUFFER_RECEIVE_BLOCK 0xD7
-#define PSF_EVENT_STREAMBUFFER_RECEIVE_FAILED 0xD8
-#define PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR 0xD9
-#define PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR_FAILED 0xDA
-#define PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR 0xDB
-#define PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR_FAILED 0xDC
-#define PSF_EVENT_STREAMBUFFER_RESET 0xDD
-
-#define PSF_EVENT_MESSAGEBUFFER_SEND 0xDE
-#define PSF_EVENT_MESSAGEBUFFER_SEND_BLOCK 0xDF
-#define PSF_EVENT_MESSAGEBUFFER_SEND_FAILED 0xE0
-#define PSF_EVENT_MESSAGEBUFFER_RECEIVE 0xE1
-#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_BLOCK 0xE2
-#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_FAILED 0xE3
-#define PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR 0xE4
-#define PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR_FAILED 0xE5
-#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR 0xE6
-#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR_FAILED 0xE7
-#define PSF_EVENT_MESSAGEBUFFER_RESET 0xE8
-
-/*** The trace macros for streaming ******************************************/
-
-/* A macro that will update the tick count when returning from tickless idle */
-#undef traceINCREASE_TICK_COUNT
-/* Note: This can handle time adjustments of max 2^32 ticks, i.e., 35 seconds at 120 MHz. Thus, tick-less idle periods longer than 2^32 ticks will appear "compressed" on the time line.*/
-#define traceINCREASE_TICK_COUNT( xCount ) { extern uint32_t uiTraceTickCount; uiTraceTickCount += xCount; }
-
-#if (TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)
-#define OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) if (uxSchedulerSuspended == (unsigned portBASE_TYPE) pdFALSE) { prvTraceStoreEvent1(PSF_EVENT_NEW_TIME, (uint32_t)(xTickCount + 1)); }
-#else
-#define OS_TICK_EVENT(uxSchedulerSuspended, xTickCount)
-#endif
-
-/* Called on each OS tick. Will call uiPortGetTimestamp to make sure it is called at least once every OS tick. */
-#undef traceTASK_INCREMENT_TICK
-#if TRC_CFG_FREERTOS_VERSION <= TRC_FREERTOS_VERSION_7_4
-#define traceTASK_INCREMENT_TICK( xTickCount ) \
- if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxMissedTicks == 0) { extern uint32_t uiTraceTickCount; uiTraceTickCount++; } \
- OS_TICK_EVENT(uxSchedulerSuspended, xTickCount)
-#else
-#define traceTASK_INCREMENT_TICK( xTickCount ) \
- if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxPendedTicks == 0) { extern uint32_t uiTraceTickCount; uiTraceTickCount++; } \
- OS_TICK_EVENT(uxSchedulerSuspended, xTickCount)
-#endif /* TRC_CFG_FREERTOS_VERSION <= TRC_FREERTOS_VERSION_7_4 */
-
-/* Called on each task-switch */
-#undef traceTASK_SWITCHED_IN
-#define traceTASK_SWITCHED_IN() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- { \
- if (prvIsNewTCB(pxCurrentTCB)) \
- { \
- prvTraceStoreEvent2(PSF_EVENT_TASK_ACTIVATE, (uint32_t)pxCurrentTCB, pxCurrentTCB->uxPriority); \
- } \
- }
-
-/* Called for each task that becomes ready */
-#if (TRC_CFG_INCLUDE_READY_EVENTS == 1)
-#undef traceMOVED_TASK_TO_READY_STATE
-#define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_TASK_READY, (uint32_t)pxTCB);
-#endif
-
-#undef traceTASK_CREATE
-#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0
-#define traceTASK_CREATE(pxNewTCB) \
- if (pxNewTCB != NULL) \
- { \
- prvTraceSaveSymbol(pxNewTCB, pxNewTCB->pcTaskName); \
- prvTraceSaveObjectData(pxNewTCB, pxNewTCB->uxPriority); \
- prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, pxNewTCB->pcTaskName, pxNewTCB); \
- TRACE_SET_OBJECT_FILTER(TASK, pxNewTCB, CurrentFilterGroup); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxNewTCB) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_CREATE, (uint32_t)pxNewTCB, pxNewTCB->uxPriority); \
- }
-#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */
-#define traceTASK_CREATE(pxNewTCB) \
- if (pxNewTCB != NULL) \
- { \
- prvTraceSaveSymbol(pxNewTCB, (const char*)pcName); \
- prvTraceSaveObjectData(pxNewTCB, uxPriority); \
- prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, (const char*)pcName, pxNewTCB); \
- TRACE_SET_OBJECT_FILTER(TASK, pxNewTCB, CurrentFilterGroup); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxNewTCB) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_CREATE, (uint32_t)pxNewTCB, uxPriority); \
- }
-#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */
-
-/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */
-#undef traceTASK_CREATE_FAILED
-#define traceTASK_CREATE_FAILED() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent0(PSF_EVENT_TASK_CREATE_FAILED);
-
-/* Called on vTaskDelete */
-#undef traceTASK_DELETE // We don't allow for filtering out "delete" events. They are important and not very frequent. Moreover, we can't exclude create events, so this should be symmetrical.
-#define traceTASK_DELETE( pxTaskToDelete ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToDelete) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_DELETE, (uint32_t)pxTaskToDelete, (pxTaskToDelete != NULL) ? (pxTaskToDelete->uxPriority) : 0); \
- prvTraceDeleteSymbol(pxTaskToDelete); \
- prvTraceDeleteObjectData(pxTaskToDelete);
-
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-
-#if (defined(configUSE_TICKLESS_IDLE) && configUSE_TICKLESS_IDLE != 0)
-
-#undef traceLOW_POWER_IDLE_BEGIN
-#define traceLOW_POWER_IDLE_BEGIN() \
- { \
- prvTraceStoreEvent1(PSF_EVENT_LOWPOWER_BEGIN, xExpectedIdleTime); \
- }
-
-#undef traceLOW_POWER_IDLE_END
-#define traceLOW_POWER_IDLE_END() \
- { \
- prvTraceStoreEvent0(PSF_EVENT_LOWPOWER_END); \
- }
-
-#endif /* (defined(configUSE_TICKLESS_IDLE) && configUSE_TICKLESS_IDLE != 0) */
-
-/* Called on vTaskSuspend */
-#undef traceTASK_SUSPEND
-#define traceTASK_SUSPEND( pxTaskToSuspend ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToSuspend) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_TASK_SUSPEND, (uint32_t)pxTaskToSuspend);
-
-/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */
-#undef traceTASK_DELAY
-#define traceTASK_DELAY() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_TASK_DELAY, xTicksToDelay);
-
-/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */
-#undef traceTASK_DELAY_UNTIL
-#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0
-#define traceTASK_DELAY_UNTIL(xTimeToWake) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_TASK_DELAY_UNTIL, (uint32_t)xTimeToWake);
-#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */
-#define traceTASK_DELAY_UNTIL() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_TASK_DELAY_UNTIL, (uint32_t)xTimeToWake);
-#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */
-
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0)
-#define traceQUEUE_CREATE_HELPER() \
- case queueQUEUE_TYPE_MUTEX: \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE, (uint32_t)pxNewQueue); \
- break; \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_RECURSIVE_CREATE, (uint32_t)pxNewQueue); \
- break;
-#else
-#define traceQUEUE_CREATE_HELPER()
-#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */
-
-/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */
-#undef traceQUEUE_CREATE
-#define traceQUEUE_CREATE( pxNewQueue )\
- TRACE_SET_OBJECT_FILTER(QUEUE, pxNewQueue, CurrentFilterGroup); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- { \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxNewQueue) & CurrentFilterMask) \
- { \
- switch (pxNewQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent2(PSF_EVENT_QUEUE_CREATE, (uint32_t)pxNewQueue, uxQueueLength); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- prvTraceStoreEvent1(PSF_EVENT_SEMAPHORE_BINARY_CREATE, (uint32_t)pxNewQueue); \
- break; \
- traceQUEUE_CREATE_HELPER() \
- } \
- } \
- }
-
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0)
-#define traceQUEUE_CREATE_FAILED_HELPER() \
- case queueQUEUE_TYPE_MUTEX: \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE_FAILED, 0); \
- break; \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_RECURSIVE_CREATE_FAILED, 0); \
- break;
-#else
-#define traceQUEUE_CREATE_FAILED_HELPER()
-#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */
-
-/* Called in xQueueCreate, if the queue creation fails */
-#undef traceQUEUE_CREATE_FAILED
-#define traceQUEUE_CREATE_FAILED( queueType ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- { \
- switch (queueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent2(PSF_EVENT_QUEUE_CREATE_FAILED, 0, uxQueueLength); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- prvTraceStoreEvent1(PSF_EVENT_SEMAPHORE_BINARY_CREATE_FAILED, 0); \
- break; \
- traceQUEUE_CREATE_FAILED_HELPER() \
- } \
- }
-
-#undef traceQUEUE_DELETE // We don't allow for filtering out "delete" events. They are important and not very frequent. Moreover, we can't exclude create events, so this should be symmetrical.
-#define traceQUEUE_DELETE( pxQueue ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- { \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- { \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent2(PSF_EVENT_QUEUE_DELETE, (uint32_t)pxQueue, (pxQueue != NULL) ? (pxQueue->uxMessagesWaiting) : 0); \
- break; \
- case queueQUEUE_TYPE_MUTEX: \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent2(PSF_EVENT_MUTEX_DELETE, (uint32_t)pxQueue, (pxQueue != NULL) ? (pxQueue->uxMessagesWaiting) : 0); \
- break; \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_DELETE, (uint32_t)pxQueue, (pxQueue != NULL) ? (pxQueue->uxMessagesWaiting) : 0); \
- break; \
- } \
- } \
- } \
- prvTraceDeleteSymbol(pxQueue);
-
-/* Called in xQueueCreateCountingSemaphore, if the queue creation fails */
-#undef traceCREATE_COUNTING_SEMAPHORE
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
-#define traceCREATE_COUNTING_SEMAPHORE() \
- TRACE_SET_OBJECT_FILTER(QUEUE, xHandle, CurrentFilterGroup); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, xHandle) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)xHandle, uxMaxCount)
-#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_5_OR_7_6)
-#define traceCREATE_COUNTING_SEMAPHORE() \
- TRACE_SET_OBJECT_FILTER(QUEUE, xHandle, CurrentFilterGroup); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, xHandle) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)xHandle, uxInitialCount);
-#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4)
-#define traceCREATE_COUNTING_SEMAPHORE() \
- TRACE_SET_OBJECT_FILTER(QUEUE, xHandle, CurrentFilterGroup); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, xHandle) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)xHandle, uxCountValue);
-#else
-#define traceCREATE_COUNTING_SEMAPHORE() \
- TRACE_SET_OBJECT_FILTER(QUEUE, pxHandle, CurrentFilterGroup); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxHandle) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)pxHandle, uxCountValue);
-#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X */
-
-#undef traceCREATE_COUNTING_SEMAPHORE_FAILED
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
-#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxMaxCount);
-#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_5_OR_7_6)
-#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxInitialCount);
-#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4)
-#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxCountValue);
-#else
-#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxCountValue);
-#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X */
-
-
-/* This macro is not necessary as of FreeRTOS v9.0.0 */
-#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0)
-/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */
-#undef traceCREATE_MUTEX
-#define traceCREATE_MUTEX( pxNewQueue ) \
- TRACE_SET_OBJECT_FILTER(QUEUE, pxNewQueue, CurrentFilterGroup); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- { \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxNewQueue) & CurrentFilterMask) \
- { \
- switch (pxNewQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_MUTEX: \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE, (uint32_t)pxNewQueue); \
- break; \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_RECURSIVE_CREATE, (uint32_t)pxNewQueue); \
- break; \
- } \
- }\
- }
-
-/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */
-#undef traceCREATE_MUTEX_FAILED
-#define traceCREATE_MUTEX_FAILED() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE_FAILED, 0);
-#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */
-
-/* Called when a message is sent to a queue */ /* CS IS NEW ! */
-#undef traceQUEUE_SEND
-#define traceQUEUE_SEND( pxQueue ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND : PSF_EVENT_QUEUE_SEND_FRONT, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \
- break; \
- case queueQUEUE_TYPE_MUTEX: \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_GIVE, (uint32_t)pxQueue); \
- break; \
- }
-
-/* Called when a message failed to be sent to a queue (timeout) */
-#undef traceQUEUE_SEND_FAILED
-#define traceQUEUE_SEND_FAILED( pxQueue ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FAILED : PSF_EVENT_QUEUE_SEND_FRONT_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_MUTEX: \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_GIVE_FAILED, (uint32_t)pxQueue); \
- break; \
- }
-
-/* 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 ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_BLOCK : PSF_EVENT_QUEUE_SEND_FRONT_BLOCK, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_BLOCK, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_MUTEX: \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_GIVE_BLOCK, (uint32_t)pxQueue); \
- break; \
- }
-
-/**************************************************************************/
-/* Makes sure xQueueGiveFromISR also has a xCopyPosition parameter */
-/**************************************************************************/
-/* Helpers needed to correctly expand names */
-#define TZ__CAT2(a,b) a ## b
-#define TZ__CAT(a,b) TZ__CAT2(a, b)
-
-/* Expands name if this header is included... uxQueueType must be a macro that only exists in queue.c or whatever, and it must expand to nothing or to something that's valid in identifiers */
-#define xQueueGiveFromISR(a,b) TZ__CAT(xQueueGiveFromISR__, uxQueueType) (a,b)
-
-/* If in queue.c, the "uxQueueType" macro expands to "pcHead". queueSEND_TO_BACK is the value we need to send in */
-#define xQueueGiveFromISR__pcHead(__a, __b) MyWrapper(__a, __b, const BaseType_t xCopyPosition); \
-BaseType_t xQueueGiveFromISR(__a, __b) { return MyWrapper(xQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK); } \
-BaseType_t MyWrapper(__a, __b, const BaseType_t xCopyPosition)
-
-/* If not in queue.c, "uxQueueType" isn't expanded */
-#define xQueueGiveFromISR__uxQueueType(__a, __b) xQueueGiveFromISR(__a,__b)
-
-/**************************************************************************/
-/* End of xQueueGiveFromISR fix */
-/**************************************************************************/
-
-/* Called when a message is sent from interrupt context, e.g., using xQueueSendFromISR */
-#undef traceQUEUE_SEND_FROM_ISR
-#define traceQUEUE_SEND_FROM_ISR( pxQueue ) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FROMISR : PSF_EVENT_QUEUE_SEND_FRONT_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \
- break; \
- }
-
-/* 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 ) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FROMISR_FAILED : PSF_EVENT_QUEUE_SEND_FRONT_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \
- break; \
- }
-
-/* Called when a message is received from a queue */
-#undef traceQUEUE_RECEIVE
-#define traceQUEUE_RECEIVE( pxQueue ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- if (isQueueReceiveHookActuallyPeek) \
- prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \
- else\
- prvTraceStoreEvent3(PSF_EVENT_QUEUE_RECEIVE, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- if (isQueueReceiveHookActuallyPeek) \
- prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \
- else \
- prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_TAKE, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \
- break; \
- case queueQUEUE_TYPE_MUTEX: \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- if (isQueueReceiveHookActuallyPeek) \
- prvTraceStoreEvent2(PSF_EVENT_MUTEX_PEEK, (uint32_t)pxQueue, xTicksToWait); \
- else \
- prvTraceStoreEvent2(PSF_EVENT_MUTEX_TAKE, (uint32_t)pxQueue, xTicksToWait); \
- break; \
- }
-
-/* Called when a receive operation on a queue fails (timeout) */
-#undef traceQUEUE_RECEIVE_FAILED
-#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_QUEUE_PEEK_FAILED : PSF_EVENT_QUEUE_RECEIVE_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_SEMAPHORE_PEEK_FAILED : PSF_EVENT_SEMAPHORE_TAKE_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_MUTEX: \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent2(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK_FAILED : PSF_EVENT_MUTEX_TAKE_FAILED, (uint32_t)pxQueue, xTicksToWait); \
- break; \
- }
-
-/* 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 ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_QUEUE_PEEK_BLOCK : PSF_EVENT_QUEUE_RECEIVE_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_SEMAPHORE_PEEK_BLOCK : PSF_EVENT_SEMAPHORE_TAKE_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_MUTEX: \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent2(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK_BLOCK : PSF_EVENT_MUTEX_TAKE_BLOCK, (uint32_t)pxQueue, xTicksToWait); \
- break; \
- }
-
-#if (TRC_CFG_FREERTOS_VERSION > TRC_FREERTOS_VERSION_9_0_1)
-/* Called when a peek operation on a queue fails (timeout) */
-#undef traceQUEUE_PEEK_FAILED
-#define traceQUEUE_PEEK_FAILED( pxQueue ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_MUTEX: \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent2(PSF_EVENT_MUTEX_PEEK_FAILED, (uint32_t)pxQueue, xTicksToWait); \
- break; \
- }
-
-/* Called when the task is blocked due to a peek operation on an empty queue */
-#undef traceBLOCKING_ON_QUEUE_PEEK
-#define traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_MUTEX: \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent2(PSF_EVENT_MUTEX_PEEK_BLOCK, (uint32_t)pxQueue, xTicksToWait); \
- break; \
- }
-
-#endif /* (TRC_CFG_FREERTOS_VERSION > TRC_FREERTOS_VERSION_9_0_1) */
-
-/* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */
-#undef traceQUEUE_RECEIVE_FROM_ISR
-#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent2(PSF_EVENT_QUEUE_RECEIVE_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting - 1); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_TAKE_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting - 1); \
- break; \
- }
-
-/* 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 ) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent2(PSF_EVENT_QUEUE_RECEIVE_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_TAKE_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \
- break; \
- }
-
-/* Called on xQueuePeek */
-#undef traceQUEUE_PEEK
-#define traceQUEUE_PEEK( pxQueue ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \
- switch (pxQueue->ucQueueType) \
- { \
- case queueQUEUE_TYPE_BASE: \
- prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_BINARY_SEMAPHORE: \
- case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \
- prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \
- break; \
- case queueQUEUE_TYPE_MUTEX: \
- case queueQUEUE_TYPE_RECURSIVE_MUTEX: \
- prvTraceStoreEvent1(PSF_EVENT_MUTEX_PEEK, (uint32_t)pxQueue); \
- break; \
- }
-
-/* Called in vTaskPrioritySet */
-#undef traceTASK_PRIORITY_SET
-#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \
- prvTraceSaveObjectData(pxTask, uxNewPriority); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTask) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_PRIORITY, (uint32_t)pxTask, uxNewPriority);
-
-/* Called in vTaskPriorityInherit, which is called by Mutex operations */
-#undef traceTASK_PRIORITY_INHERIT
-#define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTask) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_PRIO_INHERIT, (uint32_t)pxTask, uxNewPriority);
-
-/* Called in vTaskPriorityDisinherit, which is called by Mutex operations */
-#undef traceTASK_PRIORITY_DISINHERIT
-#define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTask) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_PRIO_DISINHERIT, (uint32_t)pxTask, uxNewPriority);
-
-/* Called in vTaskResume */
-#undef traceTASK_RESUME
-#define traceTASK_RESUME( pxTaskToResume ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToResume) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_TASK_RESUME, (uint32_t)pxTaskToResume);
-
-/* Called in vTaskResumeFromISR */
-#undef traceTASK_RESUME_FROM_ISR
-#define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToResume) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_TASK_RESUME_FROMISR, (uint32_t)pxTaskToResume);
-
-#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1)
-
-#undef traceMALLOC
-#define traceMALLOC( pvAddress, uiSize ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_MALLOC, (uint32_t)pvAddress, uiSize);
-
-#undef traceFREE
-#define traceFREE( pvAddress, uiSize ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_FREE, (uint32_t)pvAddress, (uint32_t)(0 - uiSize)); /* "0 -" instead of just "-" to get rid of a warning... */
-
-#endif /* (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) */
-
-#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1)
-
-/* Called in timer.c - xTimerCreate */
-#undef traceTIMER_CREATE
-#define traceTIMER_CREATE(tmr) \
- TRACE_SET_OBJECT_FILTER(TIMER, tmr, CurrentFilterGroup); \
- prvTraceSaveSymbol(tmr, tmr->pcTimerName); \
- prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, tmr->pcTimerName, tmr); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TIMER, tmr) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_TIMER_CREATE, (uint32_t)tmr, tmr->xTimerPeriodInTicks);
-
-#undef traceTIMER_CREATE_FAILED
-#define traceTIMER_CREATE_FAILED() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent0(PSF_EVENT_TIMER_CREATE_FAILED);
-
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
-#define traceTIMER_COMMAND_SEND_8_0_CASES(tmr) \
- case tmrCOMMAND_RESET: \
- prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_RESET : PSF_EVENT_TIMER_RESET_FAILED, (uint32_t)tmr, xOptionalValue); \
- break; \
- case tmrCOMMAND_START_FROM_ISR: \
- prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_START_FROMISR : PSF_EVENT_TIMER_START_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \
- break; \
- case tmrCOMMAND_RESET_FROM_ISR: \
- prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_RESET_FROMISR : PSF_EVENT_TIMER_RESET_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \
- break; \
- case tmrCOMMAND_STOP_FROM_ISR: \
- prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_STOP_FROMISR : PSF_EVENT_TIMER_STOP_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \
- break; \
- case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR: \
- prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR : PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \
- break;
-#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X */
-#define traceTIMER_COMMAND_SEND_8_0_CASES(tmr)
-#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X */
-
-/* Note that xCommandID can never be tmrCOMMAND_EXECUTE_CALLBACK (-1) since the trace macro is not called in that case */
-#undef traceTIMER_COMMAND_SEND
-#define traceTIMER_COMMAND_SEND(tmr, xCommandID, xOptionalValue, xReturn) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TIMER, tmr) & CurrentFilterMask) \
- switch(xCommandID) \
- { \
- case tmrCOMMAND_START: \
- prvTraceStoreEvent1((xReturn == pdPASS) ? PSF_EVENT_TIMER_START : PSF_EVENT_TIMER_START_FAILED, (uint32_t)tmr); \
- break; \
- case tmrCOMMAND_STOP: \
- prvTraceStoreEvent1((xReturn == pdPASS) ? PSF_EVENT_TIMER_STOP : PSF_EVENT_TIMER_STOP_FAILED, (uint32_t)tmr); \
- break; \
- case tmrCOMMAND_CHANGE_PERIOD: \
- prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_CHANGEPERIOD : PSF_EVENT_TIMER_CHANGEPERIOD_FAILED, (uint32_t)tmr, xOptionalValue); \
- break; \
- case tmrCOMMAND_DELETE: \
- prvTraceStoreEvent1((xReturn == pdPASS) ? PSF_EVENT_TIMER_DELETE : PSF_EVENT_TIMER_DELETE_FAILED, (uint32_t)tmr); \
- break; \
- traceTIMER_COMMAND_SEND_8_0_CASES(tmr) \
- }
-
-#undef traceTIMER_EXPIRED
-#define traceTIMER_EXPIRED(tmr) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TIMER, tmr) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_TIMER_EXPIRED, (uint32_t)tmr->pxCallbackFunction, (uint32_t)tmr->pvTimerID);
-
-#endif /* #if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) */
-
-
-#if (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1)
-
-#undef tracePEND_FUNC_CALL
-#define tracePEND_FUNC_CALL(func, arg1, arg2, ret) \
- prvTraceStoreEvent1((ret == pdPASS) ? PSF_EVENT_TIMER_PENDFUNCCALL : PSF_EVENT_TIMER_PENDFUNCCALL_FAILED, (uint32_t)func);
-
-#undef tracePEND_FUNC_CALL_FROM_ISR
-#define tracePEND_FUNC_CALL_FROM_ISR(func, arg1, arg2, ret) \
- prvTraceStoreEvent1((ret == pdPASS) ? PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR : PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR_FAILED, (uint32_t)func);
-
-#endif /* (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) */
-
-#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1)
-
-#undef traceEVENT_GROUP_CREATE
-#define traceEVENT_GROUP_CREATE(eg) \
- TRACE_SET_OBJECT_FILTER(EVENTGROUP, eg, CurrentFilterGroup); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_EVENTGROUP_CREATE, (uint32_t)eg);
-
-#undef traceEVENT_GROUP_DELETE
-#define traceEVENT_GROUP_DELETE(eg) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_EVENTGROUP_DELETE, (uint32_t)eg); \
- prvTraceDeleteSymbol(eg);
-
-#undef traceEVENT_GROUP_CREATE_FAILED
-#define traceEVENT_GROUP_CREATE_FAILED() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent0(PSF_EVENT_EVENTGROUP_CREATE_FAILED);
-
-#undef traceEVENT_GROUP_SYNC_BLOCK
-#define traceEVENT_GROUP_SYNC_BLOCK(eg, bitsToSet, bitsToWaitFor) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_SYNC_BLOCK, (uint32_t)eg, bitsToWaitFor);
-
-#undef traceEVENT_GROUP_SYNC_END
-#define traceEVENT_GROUP_SYNC_END(eg, bitsToSet, bitsToWaitFor, wasTimeout) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \
- prvTraceStoreEvent2((wasTimeout != pdTRUE) ? PSF_EVENT_EVENTGROUP_SYNC : PSF_EVENT_EVENTGROUP_SYNC_FAILED, (uint32_t)eg, bitsToWaitFor);
-
-#undef traceEVENT_GROUP_WAIT_BITS_BLOCK
-#define traceEVENT_GROUP_WAIT_BITS_BLOCK(eg, bitsToWaitFor) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_WAITBITS_BLOCK, (uint32_t)eg, bitsToWaitFor);
-
-#undef traceEVENT_GROUP_WAIT_BITS_END
-#define traceEVENT_GROUP_WAIT_BITS_END(eg, bitsToWaitFor, wasTimeout) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \
- prvTraceStoreEvent2((wasTimeout != pdTRUE) ? PSF_EVENT_EVENTGROUP_WAITBITS : PSF_EVENT_EVENTGROUP_WAITBITS_FAILED, (uint32_t)eg, bitsToWaitFor);
-
-#undef traceEVENT_GROUP_CLEAR_BITS
-#define traceEVENT_GROUP_CLEAR_BITS(eg, bitsToClear) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_CLEARBITS, (uint32_t)eg, bitsToClear);
-
-#undef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR
-#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(eg, bitsToClear) \
- if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_CLEARBITS_FROMISR, (uint32_t)eg, bitsToClear);
-
-#undef traceEVENT_GROUP_SET_BITS
-#define traceEVENT_GROUP_SET_BITS(eg, bitsToSet) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_SETBITS, (uint32_t)eg, bitsToSet);
-
-#undef traceEVENT_GROUP_SET_BITS_FROM_ISR
-#define traceEVENT_GROUP_SET_BITS_FROM_ISR(eg, bitsToSet) \
- if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_SETBITS_FROMISR, (uint32_t)eg, bitsToSet);
-
-#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */
-
-#undef traceTASK_NOTIFY_TAKE
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0)
-#define traceTASK_NOTIFY_TAKE() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \
- if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE, (uint32_t)pxCurrentTCB, xTicksToWait); \
- else \
- prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);}
-#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */
-#define traceTASK_NOTIFY_TAKE() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \
- if (pxCurrentTCB->eNotifyState == eNotified) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE, (uint32_t)pxCurrentTCB, xTicksToWait); \
- else \
- prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);}
-#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */
-
-#undef traceTASK_NOTIFY_TAKE_BLOCK
-#define traceTASK_NOTIFY_TAKE_BLOCK() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_BLOCK, (uint32_t)pxCurrentTCB, xTicksToWait);
-
-#undef traceTASK_NOTIFY_WAIT
-#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0)
-#define traceTASK_NOTIFY_WAIT() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \
- if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT, (uint32_t)pxCurrentTCB, xTicksToWait); \
- else \
- prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);}
-#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */
-#define traceTASK_NOTIFY_WAIT() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \
- if (pxCurrentTCB->eNotifyState == eNotified) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT, (uint32_t)pxCurrentTCB, xTicksToWait); \
- else \
- prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);}
-#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */
-
-#undef traceTASK_NOTIFY_WAIT_BLOCK
-#define traceTASK_NOTIFY_WAIT_BLOCK() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_BLOCK, (uint32_t)pxCurrentTCB, xTicksToWait);
-
-#undef traceTASK_NOTIFY
-#define traceTASK_NOTIFY() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY, (uint32_t)xTaskToNotify);
-
-#undef traceTASK_NOTIFY_FROM_ISR
-#define traceTASK_NOTIFY_FROM_ISR() \
- if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY_FROM_ISR, (uint32_t)xTaskToNotify);
-
-#undef traceTASK_NOTIFY_GIVE_FROM_ISR
-#define traceTASK_NOTIFY_GIVE_FROM_ISR() \
- if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \
- prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY_GIVE_FROM_ISR, (uint32_t)xTaskToNotify);
-
-#undef traceQUEUE_REGISTRY_ADD
-#define traceQUEUE_REGISTRY_ADD(object, name) \
- prvTraceSaveSymbol(object, (const char*)name); \
- prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, name, object);
-
-#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1)
-
-#undef traceSTREAM_BUFFER_CREATE
-#define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) \
- TRACE_SET_OBJECT_FILTER(STREAMBUFFER, pxStreamBuffer, CurrentFilterGroup); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, pxStreamBuffer) & CurrentFilterMask) \
- prvTraceStoreEvent2(xIsMessageBuffer == 1 ? PSF_EVENT_MESSAGEBUFFER_CREATE : PSF_EVENT_STREAMBUFFER_CREATE, (uint32_t)pxStreamBuffer, xBufferSizeBytes);
-
-#undef traceSTREAM_BUFFER_CREATE_FAILED
-#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreEvent2(xIsMessageBuffer == 1 ? PSF_EVENT_MESSAGEBUFFER_CREATE_FAILED : PSF_EVENT_STREAMBUFFER_CREATE_FAILED, 0 , xBufferSizeBytes);
-
-#undef traceSTREAM_BUFFER_CREATE_STATIC_FAILED
-#define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ) \
- traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer )
-
-#undef traceSTREAM_BUFFER_DELETE
-#define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, pxStreamBuffer) & CurrentFilterMask) \
- prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_DELETE : PSF_EVENT_STREAMBUFFER_DELETE, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \
- prvTraceDeleteSymbol(xStreamBuffer);
-
-#undef traceSTREAM_BUFFER_RESET
-#define traceSTREAM_BUFFER_RESET( xStreamBuffer ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \
- prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RESET : PSF_EVENT_STREAMBUFFER_RESET, (uint32_t)xStreamBuffer, 0);
-
-#undef traceSTREAM_BUFFER_SEND
-#define traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \
- prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND : PSF_EVENT_STREAMBUFFER_SEND, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer));
-
-#undef traceBLOCKING_ON_STREAM_BUFFER_SEND
-#define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \
- prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_BLOCK : PSF_EVENT_STREAMBUFFER_SEND_BLOCK, (uint32_t)xStreamBuffer);
-
-#undef traceSTREAM_BUFFER_SEND_FAILED
-#define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \
- prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FAILED : PSF_EVENT_STREAMBUFFER_SEND_FAILED, (uint32_t)xStreamBuffer);
-
-#undef traceSTREAM_BUFFER_RECEIVE
-#define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \
- prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE: PSF_EVENT_STREAMBUFFER_RECEIVE, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer));
-
-#undef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE
-#define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \
- prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_BLOCK: PSF_EVENT_STREAMBUFFER_RECEIVE_BLOCK, (uint32_t)xStreamBuffer);
-
-#undef traceSTREAM_BUFFER_RECEIVE_FAILED
-#define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \
- prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FAILED: PSF_EVENT_STREAMBUFFER_RECEIVE_FAILED, (uint32_t)xStreamBuffer);
-
-#undef traceSTREAM_BUFFER_SEND_FROM_ISR
-#define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ) \
- if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \
- { \
- if ( xReturn > ( size_t ) 0 ) \
- { \
- prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR : PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \
- } \
- else \
- { \
- prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR_FAILED : PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR_FAILED, (uint32_t)xStreamBuffer); \
- } \
- }
-
-#undef traceSTREAM_BUFFER_RECEIVE_FROM_ISR
-#define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) \
-if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \
- { \
- if ( xReceivedLength > ( size_t ) 0 ) \
- { \
- prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR : PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \
- } \
- else \
- { \
- prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR_FAILED : PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR_FAILED, (uint32_t)xStreamBuffer); \
- } \
- }
-
-#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */
-
-#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */
-
-#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
-
-#else /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
-
-/* When recorder is disabled */
-#define vTraceSetQueueName(object, name)
-#define vTraceSetSemaphoreName(object, name)
-#define vTraceSetMutexName(object, name)
-#define vTraceSetEventGroupName(object, name)
-#define vTraceSetStreamBufferName(object, name)
-#define vTraceSetMessageBufferName(object, name)
-
-#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TRC_KERNEL_PORT_H */
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 has been + * advised of the possibility of such damages, or for any claim by any third + * party. Some jurisdictions do not allow the exclusion or limitation of + * incidental, consequential or special damages, or the exclusion of implied + * warranties or limitations on how long an implied warranty may last, so the + * above limitations may not apply to you. + * + * FreeRTOS-specific definitions needed by the trace recorder + * + * <LICENSE INFO> + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_KERNEL_PORT_H +#define TRC_KERNEL_PORT_H + +#include "FreeRTOS.h" /* Defines configUSE_TRACE_FACILITY */ +#include "trcPortDefines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRC_USE_TRACEALYZER_RECORDER configUSE_TRACE_FACILITY + +/*** FreeRTOS version codes **************************************************/ +#define FREERTOS_VERSION_NOT_SET 0 +#define TRC_FREERTOS_VERSION_7_3_X 1 /* v7.3 is earliest supported.*/ +#define TRC_FREERTOS_VERSION_7_4_X 2 +#define TRC_FREERTOS_VERSION_7_5_X 3 +#define TRC_FREERTOS_VERSION_7_6_X TRC_FREERTOS_VERSION_7_5_X +#define TRC_FREERTOS_VERSION_8_X_X 4 +#define TRC_FREERTOS_VERSION_9_0_0 5 +#define TRC_FREERTOS_VERSION_9_0_1 6 +#define TRC_FREERTOS_VERSION_9_0_2 7 +#define TRC_FREERTOS_VERSION_10_0_0 8 +#define TRC_FREERTOS_VERSION_10_0_1 TRC_FREERTOS_VERSION_10_0_0 +#define TRC_FREERTOS_VERSION_10_1_0 TRC_FREERTOS_VERSION_10_0_0 +#define TRC_FREERTOS_VERSION_10_1_1 TRC_FREERTOS_VERSION_10_0_0 +#define TRC_FREERTOS_VERSION_10_2_0 TRC_FREERTOS_VERSION_10_0_0 +#define TRC_FREERTOS_VERSION_10_2_1 TRC_FREERTOS_VERSION_10_0_0 +#define TRC_FREERTOS_VERSION_10_3_0 9 +#define TRC_FREERTOS_VERSION_10_3_1 TRC_FREERTOS_VERSION_10_3_0 +#define TRC_FREERTOS_VERSION_10_4_0 10 + +/* Legacy FreeRTOS version codes for backwards compatibility with old trace configurations */ +#define TRC_FREERTOS_VERSION_7_3 TRC_FREERTOS_VERSION_7_3_X +#define TRC_FREERTOS_VERSION_7_4 TRC_FREERTOS_VERSION_7_4_X +#define TRC_FREERTOS_VERSION_7_5_OR_7_6 TRC_FREERTOS_VERSION_7_5_X +#define TRC_FREERTOS_VERSION_8_X TRC_FREERTOS_VERSION_8_X_X + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +#define prvGetStreamBufferType(x) ((( StreamBuffer_t * )x )->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER) +#else +#define prvGetStreamBufferType(x) 0 +#endif + +/* Added mainly for our internal testing. This makes it easier to create test applications that + runs on multiple FreeRTOS versions. */ +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X_X) + /* FreeRTOS v7.x */ + #define STRING_CAST(x) ( (signed char*) x ) + #define TickType portTickType + #define TaskType xTaskHandle +#else + /* FreeRTOS v8.0 and later */ + #define STRING_CAST(x) x + #define TickType TickType_t + #define TaskType TaskHandle_t +#endif + + + +#if (defined(TRC_USE_TRACEALYZER_RECORDER)) && (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) + /* Required for this feature */ +#undef INCLUDE_uxTaskGetStackHighWaterMark +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#endif /* defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ + +/******************************************************************************* + * INCLUDE_xTaskGetCurrentTaskHandle must be set to 1 for tracing to work properly + ******************************************************************************/ +#undef INCLUDE_xTaskGetCurrentTaskHandle +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + +#if (TRC_CFG_SCHEDULING_ONLY == 0) +/******************************************************************************* + * vTraceSetQueueName(void* object, const char* name) + * + * Parameter object: pointer to the Queue that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for Queue objects for display in Tracealyzer. + ******************************************************************************/ +void vTraceSetQueueName(void* object, const char* name); + +/******************************************************************************* + * vTraceSetSemaphoreName(void* object, const char* name) + * + * Parameter object: pointer to the Semaphore that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for Semaphore objects for display in Tracealyzer. + ******************************************************************************/ +void vTraceSetSemaphoreName(void* object, const char* name); + +/******************************************************************************* + * vTraceSetMutexName(void* object, const char* name) + * + * Parameter object: pointer to the Mutex that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for Semaphore objects for display in Tracealyzer. + ******************************************************************************/ +void vTraceSetMutexName(void* object, const char* name); + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) +/******************************************************************************* +* vTraceSetEventGroupName(void* object, const char* name) +* +* Parameter object: pointer to the EventGroup that shall be named +* Parameter name: the name to set (const string literal) +* +* Sets a name for EventGroup objects for display in Tracealyzer. +******************************************************************************/ +void vTraceSetEventGroupName(void* object, const char* name); +#else /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */ +#define vTraceSetEventGroupName(object, name) /* Do nothing */ +#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */ + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) +/******************************************************************************* +* vTraceSetStreamBufferName(void* object, const char* name) +* +* Parameter object: pointer to the StreamBuffer that shall be named +* Parameter name: the name to set (const string literal) +* +* Sets a name for StreamBuffer objects for display in Tracealyzer. +******************************************************************************/ +void vTraceSetStreamBufferName(void* object, const char* name); +#else /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ +#define vTraceSetStreamBufferName(object, name) /* Do nothing */ +#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) +/******************************************************************************* + * vTraceSetMessageBufferName(void* object, const char* name) + * + * Parameter object: pointer to the MessageBuffer that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for MessageBuffer objects for display in Tracealyzer. + ******************************************************************************/ +void vTraceSetMessageBufferName(void* object, const char* name); +#else /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ +#define vTraceSetMessageBufferName(object, name) /* Do nothing */ +#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ + +#if defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) +void prvAddTaskToStackMonitor(void* task); +void prvRemoveTaskFromStackMonitor(void* task); +#else /* defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) */ +#define prvAddTaskToStackMonitor(task) +#define prvRemoveTaskFromStackMonitor(task) +#endif /* defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) */ + +#else /* (TRC_CFG_SCHEDULING_ONLY == 0) */ + +#define vTraceSetQueueName(object, name) /* Do nothing */ +#define vTraceSetSemaphoreName(object, name) /* Do nothing */ +#define vTraceSetMutexName(object, name) /* Do nothing */ +#define vTraceSetEventGroupName(object, name) /* Do nothing */ +#define vTraceSetStreamBufferName(object, name) /* Do nothing */ +#define vTraceSetMessageBufferName(object, name) /* Do nothing */ +#define prvAddTaskToStackMonitor(task) /* Do nothing */ +#define prvRemoveTaskFromStackMonitor(task) /* Do nothing */ + +#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */ + +/******************************************************************************* + * Note: Setting names for event groups is difficult to support, this has been + * excluded intentionally. This since we don't know if event_groups.c is + * included in the build, so referencing it from the recorder may cause errors. + ******************************************************************************/ + +/* Gives the currently executing task (wrapper for RTOS-specific function) */ +void* prvTraceGetCurrentTaskHandle(void); + +#if (((TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) && (TRC_CFG_INCLUDE_ISR_TRACING == 1)) || (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)) +/* Tells if the scheduler currently is suspended (task-switches can't occur) */ +unsigned char prvTraceIsSchedulerSuspended(void); + +/******************************************************************************* + * INCLUDE_xTaskGetSchedulerState must be set to 1 for tracing to work properly + ******************************************************************************/ +#undef INCLUDE_xTaskGetSchedulerState +#define INCLUDE_xTaskGetSchedulerState 1 + +#endif /* (((TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) && (TRC_CFG_INCLUDE_ISR_TRACING == 1)) || (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)) */ + +#define TRACE_KERNEL_VERSION 0x1AA1 +#define TRACE_TICK_RATE_HZ configTICK_RATE_HZ /* Defined in "FreeRTOS.h" */ +#define TRACE_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOSConfig.h" */ +#define TRACE_GET_CURRENT_TASK() prvTraceGetCurrentTaskHandle() + +#define TRACE_GET_OS_TICKS() (uiTraceTickCount) /* Streaming only */ + +/* If using dynamic allocation of snapshot trace buffer... */ +#define TRACE_MALLOC(size) pvPortMalloc(size) + +#if defined(configUSE_TIMERS) +#if (configUSE_TIMERS == 1) +#undef INCLUDE_xTimerGetTimerDaemonTaskHandle +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#endif /* configUSE_TIMERS == 1*/ +#endif /* configUSE_TIMERS */ + +/* For ARM Cortex-M devices - assumes the ARM CMSIS API is available */ +#if (defined (__CORTEX_M)) + #define TRACE_ALLOC_CRITICAL_SECTION() uint32_t __irq_status; + #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = __get_PRIMASK(); __set_PRIMASK(1);} /* PRIMASK disables ALL interrupts - allows for tracing in any ISR */ + #define TRACE_EXIT_CRITICAL_SECTION() {__set_PRIMASK(__irq_status);} +#endif + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_ZyncUltraScaleR5) + + /************************************************************************** + * Disables "FreeRTOS-enabled" interrupts only , i.e. with priorities up to + * configMAX_API_CALL_INTERRUPT_PRIORITY. Don't add tracing in ISRs with + * greater priority. + *************************************************************************/ + + extern int cortex_a9_r5_enter_critical(void); + extern void cortex_a9_r5_exit_critical(int irq_already_masked_at_enter); + + #define TRACE_ALLOC_CRITICAL_SECTION() uint32_t __irq_mask_status; + + #define TRACE_ENTER_CRITICAL_SECTION() { __irq_mask_status = cortex_a9_r5_enter_critical(); } + + #define TRACE_EXIT_CRITICAL_SECTION() { cortex_a9_r5_exit_critical(__irq_mask_status); } + +#endif + +#if ( (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Renesas_RX600) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_MICROCHIP_PIC24_PIC32)) + #define TRACE_ALLOC_CRITICAL_SECTION() int __irq_status; + #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = portSET_INTERRUPT_MASK_FROM_ISR();} + #define TRACE_EXIT_CRITICAL_SECTION() {portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status);} +#endif + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Altera_NiosII) + #include "system.h" + #include "sys/alt_irq.h" + #define TRACE_ALLOC_CRITICAL_SECTION() alt_irq_context __irq_status; + #define TRACE_ENTER_CRITICAL_SECTION(){__irq_status = alt_irq_disable_all();} + #define TRACE_EXIT_CRITICAL_SECTION() {alt_irq_enable_all(__irq_status);} +#endif + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win32) + /* In the Win32 port, there are no real interrupts, so we can use the normal critical sections */ + #define TRACE_ALLOC_CRITICAL_SECTION() + #define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL() + #define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL() +#endif + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_POWERPC_Z4) +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) + /* FreeRTOS v8.0 or later */ + #define TRACE_ALLOC_CRITICAL_SECTION() UBaseType_t __irq_status; + #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = portSET_INTERRUPT_MASK_FROM_ISR();} + #define TRACE_EXIT_CRITICAL_SECTION() {portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status);} +#else + /* FreeRTOS v7.x */ + #define TRACE_ALLOC_CRITICAL_SECTION() unsigned portBASE_TYPE __irq_status; + #define TRACE_ENTER_CRITICAL_SECTION() {__irq_status = portSET_INTERRUPT_MASK_FROM_ISR();} + #define TRACE_EXIT_CRITICAL_SECTION() {portCLEAR_INTERRUPT_MASK_FROM_ISR(__irq_status);} +#endif +#endif + +#ifndef TRACE_ENTER_CRITICAL_SECTION + #error "This hardware port has no definition for critical sections! See http://percepio.com/2014/10/27/how-to-define-critical-sections-for-the-recorder/" +#endif + + +#if (TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_9_0_1) + /****************************************************************************** + * Fix for FreeRTOS v9.0.1 to correctly identify xQueuePeek events. + * + * In FreeRTOS v9.0.1, the below trace hooks are incorrectly used from three + * different functions. This as the earlier function xQueueGenericReceive + * has been replaced by xQueuePeek, xQueueSemaphoreTake and xQueueReceive. + * + * xQueueGenericReceive had a parameter "xJustPeeking", used by the trace hooks + * to tell between xQueuePeek events and others. This is no longer present, so + * we need another way to correctly identify peek events. Since all three + * functions call the same trace macros, the context of these macro is unknown. + * + * We therefore check the __LINE__ macro inside of the trace macros. This gives + * the line number of queue.c, where the macros are used. This can be used to + * tell if the context is xQueuePeek or another function. + * __LINE__ is a standard compiler feature since ancient times, so it should + * work on all common compilers. + * + * This might seem as a quite brittle and unusual solution, but works in this + * particular case and is only for FreeRTOS v9.0.1. + * Future versions of FreeRTOS should not need this fix, as we have submitted + * a correction of queue.c with individual trace macros for each function. + ******************************************************************************/ +#define isQueueReceiveHookActuallyPeek (__LINE__ > 1674) /* Half way between the closes trace points */ + +#elif (TRC_CFG_FREERTOS_VERSION <= TRC_FREERTOS_VERSION_9_0_0) +#define isQueueReceiveHookActuallyPeek xJustPeeking + +#elif (TRC_CFG_FREERTOS_VERSION > TRC_FREERTOS_VERSION_9_0_1) +#define isQueueReceiveHookActuallyPeek (__LINE__ < 0) /* instead of pdFALSE to fix a warning of "constant condition" */ + +#endif + +extern uint16_t CurrentFilterMask; + +extern uint16_t CurrentFilterGroup; + +uint8_t prvTraceGetQueueType(void* handle); +uint16_t prvTraceGetTaskNumberLow16(void* handle); +uint16_t prvTraceGetTaskNumberHigh16(void* handle); +void prvTraceSetTaskNumberLow16(void* handle, uint16_t value); +void prvTraceSetTaskNumberHigh16(void* handle, uint16_t value); + +uint16_t prvTraceGetQueueNumberLow16(void* handle); +uint16_t prvTraceGetQueueNumberHigh16(void* handle); +void prvTraceSetQueueNumberLow16(void* handle, uint16_t value); +void prvTraceSetQueueNumberHigh16(void* handle, uint16_t value); + +#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +uint16_t prvTraceGetTimerNumberLow16(void* handle); +uint16_t prvTraceGetTimerNumberHigh16(void* handle); +void prvTraceSetTimerNumberLow16(void* handle, uint16_t value); +void prvTraceSetTimerNumberHigh16(void* handle, uint16_t value); +#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +uint16_t prvTraceGetEventGroupNumberLow16(void* handle); +uint16_t prvTraceGetEventGroupNumberHigh16(void* handle); +void prvTraceSetEventGroupNumberLow16(void* handle, uint16_t value); +void prvTraceSetEventGroupNumberHigh16(void* handle, uint16_t value); +#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +uint16_t prvTraceGetStreamBufferNumberLow16(void* handle); +uint16_t prvTraceGetStreamBufferNumberHigh16(void* handle); +void prvTraceSetStreamBufferNumberLow16(void* handle, uint16_t value); +void prvTraceSetStreamBufferNumberHigh16(void* handle, uint16_t value); +#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#define TRACE_GET_TASK_FILTER(pxTask) prvTraceGetTaskNumberHigh16((void*)pxTask) +#define TRACE_SET_TASK_FILTER(pxTask, group) prvTraceSetTaskNumberHigh16((void*)pxTask, group) + +#define TRACE_GET_QUEUE_FILTER(pxObject) prvTraceGetQueueNumberHigh16((void*)pxObject) +#define TRACE_SET_QUEUE_FILTER(pxObject, group) prvTraceSetQueueNumberHigh16((void*)pxObject, group) + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +#define TRACE_GET_EVENTGROUP_FILTER(pxObject) prvTraceGetEventGroupNumberHigh16((void*)pxObject) +#define TRACE_SET_EVENTGROUP_FILTER(pxObject, group) prvTraceSetEventGroupNumberHigh16((void*)pxObject, group) +#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ +/* FreeRTOS versions before v10.0 does not support filtering for event groups */ +#define TRACE_GET_EVENTGROUP_FILTER(pxObject) 1 +#define TRACE_SET_EVENTGROUP_FILTER(pxObject, group) +#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +#define TRACE_GET_TIMER_FILTER(pxObject) prvTraceGetTimerNumberHigh16((void*)pxObject) +#define TRACE_SET_TIMER_FILTER(pxObject, group) prvTraceSetTimerNumberHigh16((void*)pxObject, group) +#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ +/* FreeRTOS versions before v10.0 does not support filtering for timers */ +#define TRACE_GET_TIMER_FILTER(pxObject) 1 +#define TRACE_SET_TIMER_FILTER(pxObject, group) +#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#define TRACE_GET_STREAMBUFFER_FILTER(pxObject) prvTraceGetStreamBufferNumberHigh16((void*)pxObject) +#define TRACE_SET_STREAMBUFFER_FILTER(pxObject, group) prvTraceSetStreamBufferNumberHigh16((void*)pxObject, group) + +/* We can only support filtering if FreeRTOS is at least v8.0 */ +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) +#define TRACE_GET_OBJECT_FILTER(CLASS, pxObject) TRACE_GET_##CLASS##_FILTER(pxObject) +#define TRACE_SET_OBJECT_FILTER(CLASS, pxObject, group) TRACE_SET_##CLASS##_FILTER(pxObject, group) +#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) */ +#define TRACE_GET_OBJECT_FILTER(CLASS, pxObject) 0xFFFF +#define TRACE_SET_OBJECT_FILTER(CLASS, pxObject, group) +#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) */ + +/* Helpers needed to correctly expand names */ +#define TZ__CAT2(a,b) a ## b +#define TZ__CAT(a,b) TZ__CAT2(a, b) + +/**************************************************************************/ +/* Makes sure xQueueGiveFromISR also has a xCopyPosition parameter */ +/**************************************************************************/ + +/* Expands name if this header is included... uxQueueType must be a macro that only exists in queue.c or whatever, and it must expand to nothing or to something that's valid in identifiers */ +#define xQueueGiveFromISR(a,b) TZ__CAT(xQueueGiveFromISR__, uxQueueType) (a,b) + +/* If in queue.c, the "uxQueueType" macro expands to "pcHead". queueSEND_TO_BACK is the value we need to send in */ +#define xQueueGiveFromISR__pcHead(__a, __b) MyWrapper_xQueueGiveFromISR(__a, __b, const BaseType_t xCopyPosition); \ +BaseType_t xQueueGiveFromISR(__a, __b) { return MyWrapper_xQueueGiveFromISR(xQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK); } \ +BaseType_t MyWrapper_xQueueGiveFromISR(__a, __b, const BaseType_t xCopyPosition) + +/* If not in queue.c, "uxQueueType" isn't expanded */ +#define xQueueGiveFromISR__uxQueueType(__a, __b) xQueueGiveFromISR(__a,__b) + +/**************************************************************************/ +/* End of xQueueGiveFromISR fix */ +/**************************************************************************/ + +/******************************************************************************/ +/*** Definitions for Snapshot mode ********************************************/ +/******************************************************************************/ +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + +/*** The object classes *******************************************************/ + +#define TRACE_NCLASSES 9 +#define TRACE_CLASS_QUEUE ((traceObjectClass)0) +#define TRACE_CLASS_SEMAPHORE ((traceObjectClass)1) +#define TRACE_CLASS_MUTEX ((traceObjectClass)2) +#define TRACE_CLASS_TASK ((traceObjectClass)3) +#define TRACE_CLASS_ISR ((traceObjectClass)4) +#define TRACE_CLASS_TIMER ((traceObjectClass)5) +#define TRACE_CLASS_EVENTGROUP ((traceObjectClass)6) +#define TRACE_CLASS_STREAMBUFFER ((traceObjectClass)7) +#define TRACE_CLASS_MESSAGEBUFFER ((traceObjectClass)8) + +/*** Definitions for Object Table ********************************************/ +#define TRACE_KERNEL_OBJECT_COUNT ((TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) + (TRC_CFG_NMESSAGEBUFFER)) + +/* Queue properties (except name): current number of message in queue */ +#define PropertyTableSizeQueue ((TRC_CFG_NAME_LEN_QUEUE) + 1) + +/* Semaphore properties (except name): state (signaled = 1, cleared = 0) */ +#define PropertyTableSizeSemaphore ((TRC_CFG_NAME_LEN_SEMAPHORE) + 1) + +/* Mutex properties (except name): owner (task handle, 0 = free) */ +#define PropertyTableSizeMutex ((TRC_CFG_NAME_LEN_MUTEX) + 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 ((TRC_CFG_NAME_LEN_TASK) + 4) + +/* ISR properties: Byte 0: priority + Byte 1: state (if already active) */ +#define PropertyTableSizeISR ((TRC_CFG_NAME_LEN_ISR) + 2) + +/* TRC_CFG_NTIMER properties: Byte 0: state (unused for now) */ +#define PropertyTableSizeTimer ((TRC_CFG_NAME_LEN_TIMER) + 1) + +/* TRC_CFG_NEVENTGROUP properties: Byte 0-3: state (unused for now)*/ +#define PropertyTableSizeEventGroup ((TRC_CFG_NAME_LEN_EVENTGROUP) + 4) + +/* TRC_CFG_NSTREAMBUFFER properties: Byte 0-3: state (unused for now)*/ +#define PropertyTableSizeStreamBuffer ((TRC_CFG_NAME_LEN_STREAMBUFFER) + 4) + +/* TRC_CFG_NMESSAGEBUFFER properties: Byte 0-3: state (unused for now)*/ +#define PropertyTableSizeMessageBuffer ((TRC_CFG_NAME_LEN_MESSAGEBUFFER) + 4) + + +/* The layout of the byte array representing the Object Property Table */ +#define StartIndexQueue (0) +#define StartIndexSemaphore (StartIndexQueue + (TRC_CFG_NQUEUE) * PropertyTableSizeQueue) +#define StartIndexMutex (StartIndexSemaphore + (TRC_CFG_NSEMAPHORE) * PropertyTableSizeSemaphore) +#define StartIndexTask (StartIndexMutex + (TRC_CFG_NMUTEX) * PropertyTableSizeMutex) +#define StartIndexISR (StartIndexTask + (TRC_CFG_NTASK) * PropertyTableSizeTask) +#define StartIndexTimer (StartIndexISR + (TRC_CFG_NISR) * PropertyTableSizeISR) +#define StartIndexEventGroup (StartIndexTimer + (TRC_CFG_NTIMER) * PropertyTableSizeTimer) +#define StartIndexStreamBuffer (StartIndexEventGroup + (TRC_CFG_NEVENTGROUP) * PropertyTableSizeEventGroup) +#define StartIndexMessageBuffer (StartIndexStreamBuffer + (TRC_CFG_NSTREAMBUFFER) * PropertyTableSizeStreamBuffer) + +/* Number of bytes used by the object table */ +#define TRACE_OBJECT_TABLE_SIZE (StartIndexMessageBuffer + (TRC_CFG_NMESSAGEBUFFER) * PropertyTableSizeMessageBuffer) + +/* Flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */ +extern int uiInEventGroupSetBitsFromISR; + +/* Initialization of the object property table */ +void vTraceInitObjectPropertyTable(void); + +/* Initialization of the handle mechanism, see e.g, prvTraceGetObjectHandle */ +void vTraceInitObjectHandleStack(void); + +/* Returns the "Not enough handles" error message for the specified object class */ +const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass); + +void* prvTraceGetCurrentTaskHandle(void); + +/****************************************************************************** + * TraceQueueClassTable + * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_). + * Has one entry for each QueueType, gives TRACE_CLASS ID. + ******************************************************************************/ +extern traceObjectClass TraceQueueClassTable[5]; + + +/*** Event codes for snapshot mode - must match Tracealyzer config files ******/ + +#define NULL_EVENT (0x00UL) + +/******************************************************************************* + * EVENTGROUP_DIV + * + * Miscellaneous events. + ******************************************************************************/ +#define EVENTGROUP_DIV (NULL_EVENT + 1UL) /*0x01*/ +#define DIV_XPS (EVENTGROUP_DIV + 0UL) /*0x01*/ +#define DIV_TASK_READY (EVENTGROUP_DIV + 1UL) /*0x02*/ +#define DIV_NEW_TIME (EVENTGROUP_DIV + 2UL) /*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 + 3UL) /*0x04*/ +#define TS_ISR_BEGIN (EVENTGROUP_TS + 0UL) /*0x04*/ +#define TS_ISR_RESUME (EVENTGROUP_TS + 1UL) /*0x05*/ +#define TS_TASK_BEGIN (EVENTGROUP_TS + 2UL) /*0x06*/ +#define TS_TASK_RESUME (EVENTGROUP_TS + 3UL) /*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_TRCSUCCESS (EVENTGROUP_TS + 4UL) /*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_TRCSUCCESS (EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + 8UL) /*0x10*/ + +/******************************************************************************* + * EVENTGROUP_CREATE + * + * The events in this group are used to log Kernel object creations. + * The lower three bits in the event code gives the object class, i.e., type of + * create operation (task, queue, semaphore, etc). + ******************************************************************************/ +#define EVENTGROUP_CREATE_OBJ_TRCSUCCESS (EVENTGROUP_OBJCLOSE_PROP_TRCSUCCESS + 8UL) /*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_TRCSUCCESS (EVENTGROUP_CREATE_OBJ_TRCSUCCESS + 8UL) /*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_TRCSUCCESS (EVENTGROUP_SEND_TRCSUCCESS + 8UL) /*0x28*/ + +/* Send/Give operations, from ISR */ +#define EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS \ + (EVENTGROUP_RECEIVE_TRCSUCCESS + 8UL) /*0x30*/ + +/* Receive/Take operations, from ISR */ +#define EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS \ + (EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS + 8UL) /*0x38*/ + +/* "Failed" event type versions of above (timeout, failed allocation, etc) */ +#define EVENTGROUP_KSE_TRCFAILED \ + (EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS + 8UL) /*0x40*/ + +/* Failed create calls - memory allocation failed */ +#define EVENTGROUP_CREATE_OBJ_TRCFAILED (EVENTGROUP_KSE_TRCFAILED) /*0x40*/ + +/* Failed send/give - timeout! */ +#define EVENTGROUP_SEND_TRCFAILED (EVENTGROUP_CREATE_OBJ_TRCFAILED + 8UL) /*0x48*/ + +/* Failed receive/take - timeout! */ +#define EVENTGROUP_RECEIVE_TRCFAILED (EVENTGROUP_SEND_TRCFAILED + 8UL) /*0x50*/ + +/* Failed non-blocking send/give - queue full */ +#define EVENTGROUP_SEND_FROM_ISR_TRCFAILED (EVENTGROUP_RECEIVE_TRCFAILED + 8UL) /*0x58*/ + +/* Failed non-blocking receive/take - queue empty */ +#define EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED \ + (EVENTGROUP_SEND_FROM_ISR_TRCFAILED + 8UL) /*0x60*/ + +/* Events when blocking on receive/take */ +#define EVENTGROUP_RECEIVE_TRCBLOCK \ + (EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED + 8UL) /*0x68*/ + +/* Events when blocking on send/give */ +#define EVENTGROUP_SEND_TRCBLOCK (EVENTGROUP_RECEIVE_TRCBLOCK + 8UL) /*0x70*/ + +/* Events on queue peek (receive) */ +#define EVENTGROUP_PEEK_TRCSUCCESS (EVENTGROUP_SEND_TRCBLOCK + 8UL) /*0x78*/ + +/* Events on object delete (vTaskDelete or vQueueDelete) */ +#define EVENTGROUP_DELETE_OBJ_TRCSUCCESS (EVENTGROUP_PEEK_TRCSUCCESS + 8UL) /*0x80*/ + +/* Other events - object class is implied: TASK */ +#define EVENTGROUP_OTHERS (EVENTGROUP_DELETE_OBJ_TRCSUCCESS + 8UL) /*0x88*/ +#define TASK_DELAY_UNTIL (EVENTGROUP_OTHERS + 0UL) /*0x88*/ +#define TASK_DELAY (EVENTGROUP_OTHERS + 1UL) /*0x89*/ +#define TASK_SUSPEND (EVENTGROUP_OTHERS + 2UL) /*0x8A*/ +#define TASK_RESUME (EVENTGROUP_OTHERS + 3UL) /*0x8B*/ +#define TASK_RESUME_FROM_ISR (EVENTGROUP_OTHERS + 4UL) /*0x8C*/ +#define TASK_PRIORITY_SET (EVENTGROUP_OTHERS + 5UL) /*0x8D*/ +#define TASK_PRIORITY_INHERIT (EVENTGROUP_OTHERS + 6UL) /*0x8E*/ +#define TASK_PRIORITY_DISINHERIT (EVENTGROUP_OTHERS + 7UL) /*0x8F*/ + +#define EVENTGROUP_MISC_PLACEHOLDER (EVENTGROUP_OTHERS + 8UL) /*0x90*/ +#define PEND_FUNC_CALL (EVENTGROUP_MISC_PLACEHOLDER+0UL) /*0x90*/ +#define PEND_FUNC_CALL_FROM_ISR (EVENTGROUP_MISC_PLACEHOLDER+1UL) /*0x91*/ +#define PEND_FUNC_CALL_TRCFAILED (EVENTGROUP_MISC_PLACEHOLDER+2UL) /*0x92*/ +#define PEND_FUNC_CALL_FROM_ISR_TRCFAILED (EVENTGROUP_MISC_PLACEHOLDER+3UL) /*0x93*/ +#define MEM_MALLOC_SIZE (EVENTGROUP_MISC_PLACEHOLDER+4UL) /*0x94*/ +#define MEM_MALLOC_ADDR (EVENTGROUP_MISC_PLACEHOLDER+5UL) /*0x95*/ +#define MEM_FREE_SIZE (EVENTGROUP_MISC_PLACEHOLDER+6UL) /*0x96*/ +#define MEM_FREE_ADDR (EVENTGROUP_MISC_PLACEHOLDER+7UL) /*0x97*/ + +/* User events */ +#define EVENTGROUP_USEREVENT (EVENTGROUP_MISC_PLACEHOLDER + 8UL) /*0x98*/ +#define USER_EVENT (EVENTGROUP_USEREVENT + 0UL) + +/* Allow for 0-15 arguments (the number of args is added to event code) */ +#define USER_EVENT_LAST (EVENTGROUP_USEREVENT + 15UL) /*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 (255UL). The XTS16 is used when the original event + * has a 16 bit DTS field and thereby can handle values up to 0xFFFF (65535UL). + * + * 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 + 16UL) /*0xA8*/ +#define XTS8 (EVENTGROUP_SYS + 0UL) /*0xA8*/ +#define XTS16 (EVENTGROUP_SYS + 1UL) /*0xA9*/ +#define EVENT_BEING_WRITTEN (EVENTGROUP_SYS + 2UL) /*0xAA*/ +#define RESERVED_DUMMY_CODE (EVENTGROUP_SYS + 3UL) /*0xAB*/ +#define LOW_POWER_BEGIN (EVENTGROUP_SYS + 4UL) /*0xAC*/ +#define LOW_POWER_END (EVENTGROUP_SYS + 5UL) /*0xAD*/ +#define XID (EVENTGROUP_SYS + 6UL) /*0xAE*/ +#define XTS16L (EVENTGROUP_SYS + 7UL) /*0xAF*/ + +#define EVENTGROUP_TIMER (EVENTGROUP_SYS + 8UL) /*0xB0*/ +#define TIMER_CREATE (EVENTGROUP_TIMER + 0UL) /*0xB0*/ +#define TIMER_START (EVENTGROUP_TIMER + 1UL) /*0xB1*/ +#define TIMER_RST (EVENTGROUP_TIMER + 2UL) /*0xB2*/ +#define TIMER_STOP (EVENTGROUP_TIMER + 3UL) /*0xB3*/ +#define TIMER_CHANGE_PERIOD (EVENTGROUP_TIMER + 4UL) /*0xB4*/ +#define TIMER_DELETE_OBJ (EVENTGROUP_TIMER + 5UL) /*0xB5*/ +#define TIMER_START_FROM_ISR (EVENTGROUP_TIMER + 6UL) /*0xB6*/ +#define TIMER_RESET_FROM_ISR (EVENTGROUP_TIMER + 7UL) /*0xB7*/ +#define TIMER_STOP_FROM_ISR (EVENTGROUP_TIMER + 8UL) /*0xB8*/ + +#define TIMER_CREATE_TRCFAILED (EVENTGROUP_TIMER + 9UL) /*0xB9*/ +#define TIMER_START_TRCFAILED (EVENTGROUP_TIMER + 10UL) /*0xBA*/ +#define TIMER_RESET_TRCFAILED (EVENTGROUP_TIMER + 11UL) /*0xBB*/ +#define TIMER_STOP_TRCFAILED (EVENTGROUP_TIMER + 12UL) /*0xBC*/ +#define TIMER_CHANGE_PERIOD_TRCFAILED (EVENTGROUP_TIMER + 13UL) /*0xBD*/ +#define TIMER_DELETE_TRCFAILED (EVENTGROUP_TIMER + 14UL) /*0xBE*/ +#define TIMER_START_FROM_ISR_TRCFAILED (EVENTGROUP_TIMER + 15UL) /*0xBF*/ +#define TIMER_RESET_FROM_ISR_TRCFAILED (EVENTGROUP_TIMER + 16UL) /*0xC0*/ +#define TIMER_STOP_FROM_ISR_TRCFAILED (EVENTGROUP_TIMER + 17UL) /*0xC1*/ + +#define EVENTGROUP_EG (EVENTGROUP_TIMER + 18UL) /*0xC2*/ +#define EVENT_GROUP_CREATE (EVENTGROUP_EG + 0UL) /*0xC2*/ +#define EVENT_GROUP_CREATE_TRCFAILED (EVENTGROUP_EG + 1UL) /*0xC3*/ +#define EVENT_GROUP_SYNC_TRCBLOCK (EVENTGROUP_EG + 2UL) /*0xC4*/ +#define EVENT_GROUP_SYNC_END (EVENTGROUP_EG + 3UL) /*0xC5*/ +#define EVENT_GROUP_WAIT_BITS_TRCBLOCK (EVENTGROUP_EG + 4UL) /*0xC6*/ +#define EVENT_GROUP_WAIT_BITS_END (EVENTGROUP_EG + 5UL) /*0xC7*/ +#define EVENT_GROUP_CLEAR_BITS (EVENTGROUP_EG + 6UL) /*0xC8*/ +#define EVENT_GROUP_CLEAR_BITS_FROM_ISR (EVENTGROUP_EG + 7UL) /*0xC9*/ +#define EVENT_GROUP_SET_BITS (EVENTGROUP_EG + 8UL) /*0xCA*/ +#define EVENT_GROUP_DELETE_OBJ (EVENTGROUP_EG + 9UL) /*0xCB*/ +#define EVENT_GROUP_SYNC_END_TRCFAILED (EVENTGROUP_EG + 10UL) /*0xCC*/ +#define EVENT_GROUP_WAIT_BITS_END_TRCFAILED (EVENTGROUP_EG + 11UL) /*0xCD*/ +#define EVENT_GROUP_SET_BITS_FROM_ISR (EVENTGROUP_EG + 12UL) /*0xCE*/ +#define EVENT_GROUP_SET_BITS_FROM_ISR_TRCFAILED (EVENTGROUP_EG + 13UL) /*0xCF*/ + +#define TASK_INSTANCE_FINISHED_NEXT_KSE (EVENTGROUP_EG + 14UL) /*0xD0*/ +#define TASK_INSTANCE_FINISHED_DIRECT (EVENTGROUP_EG + 15UL) /*0xD1*/ + +#define TRACE_TASK_NOTIFY_GROUP (EVENTGROUP_EG + 16UL) /*0xD2*/ +#define TRACE_TASK_NOTIFY (TRACE_TASK_NOTIFY_GROUP + 0UL) /*0xD2*/ +#define TRACE_TASK_NOTIFY_TAKE (TRACE_TASK_NOTIFY_GROUP + 1UL) /*0xD3*/ +#define TRACE_TASK_NOTIFY_TAKE_TRCBLOCK (TRACE_TASK_NOTIFY_GROUP + 2UL) /*0xD4*/ +#define TRACE_TASK_NOTIFY_TAKE_TRCFAILED (TRACE_TASK_NOTIFY_GROUP + 3UL) /*0xD5*/ +#define TRACE_TASK_NOTIFY_WAIT (TRACE_TASK_NOTIFY_GROUP + 4UL) /*0xD6*/ +#define TRACE_TASK_NOTIFY_WAIT_TRCBLOCK (TRACE_TASK_NOTIFY_GROUP + 5UL) /*0xD7*/ +#define TRACE_TASK_NOTIFY_WAIT_TRCFAILED (TRACE_TASK_NOTIFY_GROUP + 6UL) /*0xD8*/ +#define TRACE_TASK_NOTIFY_FROM_ISR (TRACE_TASK_NOTIFY_GROUP + 7UL) /*0xD9*/ +#define TRACE_TASK_NOTIFY_GIVE_FROM_ISR (TRACE_TASK_NOTIFY_GROUP + 8UL) /*0xDA*/ + +#define TIMER_EXPIRED (TRACE_TASK_NOTIFY_GROUP + 9UL) /*0xDB*/ + + /* Events on queue peek (receive) */ +#define EVENTGROUP_PEEK_TRCBLOCK (TRACE_TASK_NOTIFY_GROUP + 10UL) /*0xDC*/ +/* peek block on queue: 0xDC */ +/* peek block on semaphore: 0xDD */ +/* peek block on mutex: 0xDE */ + +/* Events on queue peek (receive) */ +#define EVENTGROUP_PEEK_TRCFAILED (EVENTGROUP_PEEK_TRCBLOCK + 3UL) /*0xDF*/ +/* peek failed on queue: 0xDF */ +/* peek failed on semaphore: 0xE0 */ +/* peek failed on mutex: 0xE1 */ + +#define EVENTGROUP_STREAMBUFFER_DIV (EVENTGROUP_PEEK_TRCFAILED + 3UL) /*0xE2*/ +#define TRACE_STREAMBUFFER_RESET (EVENTGROUP_STREAMBUFFER_DIV + 0) /*0xE2*/ +#define TRACE_MESSAGEBUFFER_RESET (EVENTGROUP_STREAMBUFFER_DIV + 1UL) /*0xE3*/ +#define TRACE_STREAMBUFFER_OBJCLOSE_NAME_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 2UL) /*0xE4*/ +#define TRACE_MESSAGEBUFFER_OBJCLOSE_NAME_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 3UL) /*0xE5*/ +#define TRACE_STREAMBUFFER_OBJCLOSE_PROP_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 4UL) /*0xE6*/ +#define TRACE_MESSAGEBUFFER_OBJCLOSE_PROP_TRCSUCCESS (EVENTGROUP_STREAMBUFFER_DIV + 5UL) /*0xE7*/ + +#define EVENTGROUP_MALLOC_FAILED (EVENTGROUP_STREAMBUFFER_DIV + 6UL) /*0xE8*/ +#define MEM_MALLOC_SIZE_TRCFAILED (EVENTGROUP_MALLOC_FAILED + 0UL) /*0xE8*/ +#define MEM_MALLOC_ADDR_TRCFAILED (EVENTGROUP_MALLOC_FAILED + 1UL) /*0xE9*/ + +/* The following are using previously "lost" event codes */ +#define TRACE_STREAMBUFFER_CREATE_OBJ_TRCSUCCESS (EVENTGROUP_CREATE_OBJ_TRCSUCCESS + 4UL) /*0x1C*/ +#define TRACE_STREAMBUFFER_CREATE_OBJ_TRCFAILED (EVENTGROUP_CREATE_OBJ_TRCFAILED + 4UL) /*0x44*/ +#define TRACE_STREAMBUFFER_DELETE_OBJ_TRCSUCCESS (EVENTGROUP_DELETE_OBJ_TRCSUCCESS + 4UL) /*0x84*/ +#define TRACE_STREAMBUFFER_SEND_TRCSUCCESS (EVENTGROUP_SEND_TRCSUCCESS + 3UL) /*0x23*/ +#define TRACE_STREAMBUFFER_SEND_TRCBLOCK (EVENTGROUP_SEND_TRCBLOCK + 3UL) /*0x73*/ +#define TRACE_STREAMBUFFER_SEND_TRCFAILED (EVENTGROUP_SEND_TRCFAILED + 3UL) /*0x4B*/ +#define TRACE_STREAMBUFFER_RECEIVE_TRCSUCCESS (EVENTGROUP_RECEIVE_TRCSUCCESS + 3UL) /*0x2B*/ +#define TRACE_STREAMBUFFER_RECEIVE_TRCBLOCK (EVENTGROUP_RECEIVE_TRCBLOCK + 3UL) /*0x6B*/ +#define TRACE_STREAMBUFFER_RECEIVE_TRCFAILED (EVENTGROUP_RECEIVE_TRCFAILED + 3UL) /*0x53*/ +#define TRACE_STREAMBUFFER_SEND_FROM_ISR_TRCSUCCESS (EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS + 3UL) /*0x33*/ +#define TRACE_STREAMBUFFER_SEND_FROM_ISR_TRCFAILED (EVENTGROUP_SEND_FROM_ISR_TRCFAILED + 3UL) /*0x5B*/ +#define TRACE_STREAMBUFFER_RECEIVE_FROM_ISR_TRCSUCCESS (EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS + 3UL) /*0x3B*/ +#define TRACE_STREAMBUFFER_RECEIVE_FROM_ISR_TRCFAILED (EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED + 3UL) /*0x63*/ + +/* The following are using previously "lost" event codes. These macros aren't even directly referenced, instead we do (equivalent STREAMBUFFER code) + 1. */ +#define TRACE_MESSAGEBUFFER_CREATE_OBJ_TRCSUCCESS (EVENTGROUP_CREATE_OBJ_TRCSUCCESS + 5UL) /*0x1D*/ +#define TRACE_MESSAGEBUFFER_CREATE_OBJ_TRCFAILED (EVENTGROUP_CREATE_OBJ_TRCFAILED + 5UL) /*0x45*/ +#define TRACE_MESSAGEBUFFER_DELETE_OBJ_TRCSUCCESS (EVENTGROUP_DELETE_OBJ_TRCSUCCESS + 5UL) /*0x85*/ +#define TRACE_MESSAGEBUFFER_SEND_TRCSUCCESS (EVENTGROUP_SEND_TRCSUCCESS + 4UL) /*0x24*/ +#define TRACE_MESSAGEBUFFER_SEND_TRCBLOCK (EVENTGROUP_SEND_TRCBLOCK + 4UL) /*0x74*/ +#define TRACE_MESSAGEBUFFER_SEND_TRCFAILED (EVENTGROUP_SEND_TRCFAILED + 4UL) /*0x4C*/ +#define TRACE_MESSAGEBUFFER_RECEIVE_TRCSUCCESS (EVENTGROUP_RECEIVE_TRCSUCCESS + 4UL) /*0x2C*/ +#define TRACE_MESSAGEBUFFER_RECEIVE_TRCBLOCK (EVENTGROUP_RECEIVE_TRCBLOCK + 4UL) /*0x6C*/ +#define TRACE_MESSAGEBUFFER_RECEIVE_TRCFAILED (EVENTGROUP_RECEIVE_TRCFAILED + 4UL) /*0x54*/ +#define TRACE_MESSAGEBUFFER_SEND_FROM_ISR_TRCSUCCESS (EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS + 4UL) /*0x34*/ +#define TRACE_MESSAGEBUFFER_SEND_FROM_ISR_TRCFAILED (EVENTGROUP_SEND_FROM_ISR_TRCFAILED + 4UL) /*0x5C*/ +#define TRACE_MESSAGEBUFFER_RECEIVE_FROM_ISR_TRCSUCCESS (EVENTGROUP_RECEIVE_FROM_ISR_TRCSUCCESS + 4UL) /*0x3C*/ +#define TRACE_MESSAGEBUFFER_RECEIVE_FROM_ISR_TRCFAILED (EVENTGROUP_RECEIVE_FROM_ISR_TRCFAILED + 4UL) /*0x64*/ + +#define TRACE_QUEUE_SEND_TO_FRONT_TRCSUCCESS (EVENTGROUP_SEND_TRCSUCCESS + 5UL) /*0x25*/ +#define TRACE_QUEUE_SEND_TO_FRONT_TRCBLOCK (EVENTGROUP_SEND_TRCBLOCK + 5UL) /*0x75*/ +#define TRACE_QUEUE_SEND_TO_FRONT_TRCFAILED (EVENTGROUP_SEND_TRCFAILED + 5UL) /*0x4D*/ +#define TRACE_QUEUE_SEND_TO_FRONT_FROM_ISR_TRCSUCCESS (EVENTGROUP_SEND_FROM_ISR_TRCSUCCESS + 5UL) /*0x35*/ +#define TRACE_QUEUE_SEND_TO_FRONT_FROM_ISR_TRCFAILED (EVENTGROUP_SEND_FROM_ISR_TRCFAILED + 5UL) /*0x5D*/ + +#define TRACE_UNUSED_STACK (EVENTGROUP_MALLOC_FAILED + 2UL) /*0xEA*/ + +/* LAST EVENT (0xEA) */ + +/**************************** +* MACROS TO GET TRACE CLASS * +****************************/ +#define TRACE_GET_TRACE_CLASS_FROM_TASK_CLASS(kernelClass) (TRACE_CLASS_TASK) +#define TRACE_GET_TRACE_CLASS_FROM_TASK_OBJECT(pxObject) (TRACE_CLASS_TASK) + +#define TRACE_GET_TRACE_CLASS_FROM_QUEUE_CLASS(kernelClass) TraceQueueClassTable[kernelClass] +#define TRACE_GET_TRACE_CLASS_FROM_QUEUE_OBJECT(pxObject) TRACE_GET_TRACE_CLASS_FROM_QUEUE_CLASS(prvTraceGetQueueType(pxObject)) + +#define TRACE_GET_TRACE_CLASS_FROM_TIMER_CLASS(kernelClass) (TRACE_CLASS_TIMER) +#define TRACE_GET_TRACE_CLASS_FROM_TIMER_OBJECT(pxObject) (TRACE_CLASS_TIMER) + +#define TRACE_GET_TRACE_CLASS_FROM_EVENTGROUP_CLASS(kernelClass) (TRACE_CLASS_EVENTGROUP) +#define TRACE_GET_TRACE_CLASS_FROM_EVENTGROUP_OBJECT(pxObject) (TRACE_CLASS_EVENTGROUP) + +/* TRACE_GET_TRACE_CLASS_FROM_STREAMBUFFER_CLASS can only be accessed with a parameter indicating if it is a MessageBuffer */ +#define TRACE_GET_TRACE_CLASS_FROM_STREAMBUFFER_CLASS(xIsMessageBuffer) (xIsMessageBuffer == 1 ? TRACE_CLASS_MESSAGEBUFFER : TRACE_CLASS_STREAMBUFFER) +#define TRACE_GET_TRACE_CLASS_FROM_STREAMBUFFER_OBJECT(pxObject) (prvGetStreamBufferType(pxObject) == 1 ? TRACE_CLASS_MESSAGEBUFFER : TRACE_CLASS_STREAMBUFFER) + +/* Generic versions */ +#define TRACE_GET_CLASS_TRACE_CLASS(CLASS, kernelClass) TRACE_GET_TRACE_CLASS_FROM_##CLASS##_CLASS(kernelClass) +#define TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject) TRACE_GET_TRACE_CLASS_FROM_##CLASS##_OBJECT(pxObject) + +/****************************** +* MACROS TO GET OBJECT NUMBER * +******************************/ +#define TRACE_GET_TASK_NUMBER(pxTCB) (traceHandle)(prvTraceGetTaskNumberLow16(pxTCB)) +#define TRACE_SET_TASK_NUMBER(pxTCB) prvTraceSetTaskNumberLow16(pxTCB, prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(TASK, pxTCB))); + +#define TRACE_GET_QUEUE_NUMBER(queue) ( ( traceHandle ) prvTraceGetQueueNumberLow16(queue) ) +#define TRACE_SET_QUEUE_NUMBER(queue) prvTraceSetQueueNumberLow16(queue, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, queue))); + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +#define TRACE_GET_TIMER_NUMBER(tmr) ( ( traceHandle ) prvTraceGetTimerNumberLow16(tmr) ) +#define TRACE_SET_TIMER_NUMBER(tmr) prvTraceSetTimerNumberLow16(tmr, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr))); +#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ +#define TRACE_GET_TIMER_NUMBER(tmr) ( ( traceHandle ) ((Timer_t*)tmr)->uxTimerNumber ) +#define TRACE_SET_TIMER_NUMBER(tmr) ((Timer_t*)tmr)->uxTimerNumber = prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr)); +#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +#define TRACE_GET_EVENTGROUP_NUMBER(eg) ( ( traceHandle ) prvTraceGetEventGroupNumberLow16(eg) ) +#define TRACE_SET_EVENTGROUP_NUMBER(eg) prvTraceSetEventGroupNumberLow16(eg, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg))); +#else /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ +#define TRACE_GET_EVENTGROUP_NUMBER(eg) ( ( traceHandle ) uxEventGroupGetNumber(eg) ) +#define TRACE_SET_EVENTGROUP_NUMBER(eg) ((EventGroup_t*)eg)->uxEventGroupNumber = prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg)); +#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + + +#define TRACE_GET_STREAMBUFFER_NUMBER(sb) ( ( traceHandle ) prvTraceGetStreamBufferNumberLow16(sb) ) +#define TRACE_SET_STREAMBUFFER_NUMBER(sb) prvTraceSetStreamBufferNumberLow16(sb, (uint16_t)prvTraceGetObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(STREAMBUFFER, sb))); + +/* Generic versions */ +#define TRACE_GET_OBJECT_NUMBER(CLASS, pxObject) TRACE_GET_##CLASS##_NUMBER(pxObject) +#define TRACE_SET_OBJECT_NUMBER(CLASS, pxObject) TRACE_SET_##CLASS##_NUMBER(pxObject) + +/****************************** +* MACROS TO GET EVENT CODES * +******************************/ +#define TRACE_GET_TASK_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_CLASS_TRACE_CLASS(TASK, kernelClass)) +#define TRACE_GET_QUEUE_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_CLASS_TRACE_CLASS(QUEUE, kernelClass)) +#define TRACE_GET_TIMER_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) -- THIS IS NOT USED -- +#define TRACE_GET_EVENTGROUP_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) -- THIS IS NOT USED -- +#define TRACE_GET_STREAMBUFFER_CLASS_EVENT_CODE(SERVICE, RESULT, isMessageBuffer) (uint8_t)(TRACE_STREAMBUFFER_##SERVICE##_##RESULT + (uint8_t)isMessageBuffer) + +#define TRACE_GET_TASK_OBJECT_EVENT_CODE(SERVICE, RESULT, pxTCB) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_CLASS_TASK) +#define TRACE_GET_QUEUE_OBJECT_EVENT_CODE(SERVICE, RESULT, pxObject) (uint8_t)(EVENTGROUP_##SERVICE##_##RESULT + TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxObject)) +#define TRACE_GET_TIMER_OBJECT_EVENT_CODE(SERVICE, RESULT, UNUSED) -- THIS IS NOT USED -- +#define TRACE_GET_EVENTGROUP_OBJECT_EVENT_CODE(SERVICE, RESULT, UNUSED) -- THIS IS NOT USED -- +#define TRACE_GET_STREAMBUFFER_OBJECT_EVENT_CODE(SERVICE, RESULT, pxObject) (uint8_t)(TRACE_STREAMBUFFER_##SERVICE##_##RESULT + prvGetStreamBufferType(pxObject)) + +/* Generic versions */ +#define TRACE_GET_CLASS_EVENT_CODE(SERVICE, RESULT, CLASS, kernelClass) TRACE_GET_##CLASS##_CLASS_EVENT_CODE(SERVICE, RESULT, kernelClass) +#define TRACE_GET_OBJECT_EVENT_CODE(SERVICE, RESULT, CLASS, pxObject) TRACE_GET_##CLASS##_OBJECT_EVENT_CODE(SERVICE, RESULT, pxObject) + +/****************************** +* SPECIAL MACROS FOR TASKS * +******************************/ +#define TRACE_GET_TASK_PRIORITY(pxTCB) ((uint8_t)pxTCB->uxPriority) +#define TRACE_GET_TASK_NAME(pxTCB) ((char*)pxTCB->pcTaskName) + +/*** The trace macros for snapshot mode **************************************/ + +/* A macro that will update the tick count when returning from tickless idle */ +#undef traceINCREASE_TICK_COUNT +#define traceINCREASE_TICK_COUNT( xCount ) + +/* 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 + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_3_0) + +#define traceTASK_INCREMENT_TICK( xTickCount ) \ + if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || xPendedTicks == 0) { trcKERNEL_HOOKS_INCREMENT_TICK(); } \ + if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE) { trcKERNEL_HOOKS_NEW_TIME(DIV_NEW_TIME, xTickCount + 1); } + +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_5_X) + +#define traceTASK_INCREMENT_TICK( xTickCount ) \ + if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxPendedTicks == 0) { trcKERNEL_HOOKS_INCREMENT_TICK(); } \ + if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE) { trcKERNEL_HOOKS_NEW_TIME(DIV_NEW_TIME, xTickCount + 1); } + +#else + +#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); } + +#endif + +extern volatile uint32_t uiTraceSystemState; + +/* Called on each task-switch */ +#undef traceTASK_SWITCHED_IN +#define traceTASK_SWITCHED_IN() \ + uiTraceSystemState = TRC_STATE_IN_TASKSWITCH; \ + trcKERNEL_HOOKS_TASK_SWITCH(TRACE_GET_CURRENT_TASK()); \ + uiTraceSystemState = TRC_STATE_IN_APPLICATION; + +/* Called on vTaskCreate */ +#undef traceTASK_CREATE +#define traceTASK_CREATE(pxNewTCB) \ + if (pxNewTCB != NULL) \ + { \ + trcKERNEL_HOOKS_TASK_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, TASK, pxNewTCB), TASK, pxNewTCB); \ + prvAddTaskToStackMonitor(pxNewTCB); \ + } + +/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */ +#undef traceTASK_CREATE_FAILED +#define traceTASK_CREATE_FAILED() \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, TASK, NOT_USED), 0); + +/* Called on vTaskDelete */ +#undef traceTASK_DELETE +#define traceTASK_DELETE( pxTaskToDelete ) \ + { TRACE_ALLOC_CRITICAL_SECTION(); \ + TRACE_ENTER_CRITICAL_SECTION(); \ + trcKERNEL_HOOKS_TASK_DELETE(TRACE_GET_OBJECT_EVENT_CODE(DELETE_OBJ, TRCSUCCESS, TASK, pxTaskToDelete), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_NAME, TRCSUCCESS, TASK, pxTaskToDelete), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_PROP, TRCSUCCESS, TASK, pxTaskToDelete), pxTaskToDelete); \ + prvRemoveTaskFromStackMonitor(pxTaskToDelete); \ + TRACE_EXIT_CRITICAL_SECTION(); } + +#if (TRC_CFG_SCHEDULING_ONLY == 0) + +#if defined(configUSE_TICKLESS_IDLE) +#if (configUSE_TICKLESS_IDLE != 0) + +#undef traceLOW_POWER_IDLE_BEGIN +#define traceLOW_POWER_IDLE_BEGIN() \ + { \ + extern uint32_t trace_disable_timestamp; \ + prvTraceStoreLowPower(0); \ + trace_disable_timestamp = 1; \ + } + +#undef traceLOW_POWER_IDLE_END +#define traceLOW_POWER_IDLE_END() \ + { \ + extern uint32_t trace_disable_timestamp; \ + trace_disable_timestamp = 0; \ + prvTraceStoreLowPower(1); \ + } + +#endif /* (configUSE_TICKLESS_IDLE != 0) */ +#endif /* defined(configUSE_TICKLESS_IDLE) */ + +/* Called on vTaskSuspend */ +#undef traceTASK_SUSPEND +#define traceTASK_SUSPEND( pxTaskToSuspend ) \ + trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend); + +/* Called from special case with timer only */ +#undef traceTASK_DELAY_SUSPEND +#define traceTASK_DELAY_SUSPEND( pxTaskToSuspend ) \ + trcKERNEL_HOOKS_TASK_SUSPEND(TASK_SUSPEND, pxTaskToSuspend); \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); + +/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */ +#undef traceTASK_DELAY +#define traceTASK_DELAY() \ + trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY, pxCurrentTCB, xTicksToDelay); \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); + +/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */ +#undef traceTASK_DELAY_UNTIL +#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 +#define traceTASK_DELAY_UNTIL(xTimeToWake) \ + trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ +#define traceTASK_DELAY_UNTIL() \ + trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ + +/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */ +#undef traceQUEUE_CREATE +#define traceQUEUE_CREATE( pxNewQueue ) \ + trcKERNEL_HOOKS_OBJECT_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, QUEUE, pxNewQueue), QUEUE, pxNewQueue); + +/* Called in xQueueCreate, if the queue creation fails */ +#undef traceQUEUE_CREATE_FAILED +#define traceQUEUE_CREATE_FAILED( queueType ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, QUEUE, queueType), 0); + +/* Called on vQueueDelete */ +#undef traceQUEUE_DELETE +#define traceQUEUE_DELETE( pxQueue ) \ + { TRACE_ALLOC_CRITICAL_SECTION(); \ + TRACE_ENTER_CRITICAL_SECTION(); \ + trcKERNEL_HOOKS_OBJECT_DELETE(TRACE_GET_OBJECT_EVENT_CODE(DELETE_OBJ, TRCSUCCESS, QUEUE, pxQueue), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_NAME, TRCSUCCESS, QUEUE, pxQueue), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_PROP, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ + TRACE_EXIT_CRITICAL_SECTION(); } + +/* This macro is not necessary as of FreeRTOS v9.0.0 */ +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) +/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */ +#undef traceCREATE_MUTEX +#define traceCREATE_MUTEX( pxNewQueue ) \ + trcKERNEL_HOOKS_OBJECT_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, QUEUE, pxNewQueue), QUEUE, pxNewQueue); + +/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */ +#undef traceCREATE_MUTEX_FAILED +#define traceCREATE_MUTEX_FAILED() \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, QUEUE, queueQUEUE_TYPE_MUTEX), 0); +#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */ + +/* Called when the Mutex can not be given, since not holder */ +#undef traceGIVE_MUTEX_RECURSIVE_FAILED +#define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCFAILED, QUEUE, pxMutex), QUEUE, pxMutex); + +/* Called when a message is sent to a queue */ /* CS IS NEW ! */ +#undef traceQUEUE_SEND +#define traceQUEUE_SEND( pxQueue ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(xCopyPosition == queueSEND_TO_BACK ? (TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCSUCCESS, QUEUE, pxQueue)) : TRACE_QUEUE_SEND_TO_FRONT_TRCSUCCESS, QUEUE, pxQueue); \ + trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) == TRACE_CLASS_MUTEX ? (uint8_t)0 : (uint8_t)(pxQueue->uxMessagesWaiting + 1)); + +/* Called when a message is sent to a queue set */ +#undef traceQUEUE_SET_SEND +#define traceQUEUE_SET_SEND( pxQueue ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ + trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, pxQueue, (uint8_t)(pxQueue->uxMessagesWaiting + 1)); + +/* Called when a message failed to be sent to a queue (timeout) */ +#undef traceQUEUE_SEND_FAILED +#define traceQUEUE_SEND_FAILED( pxQueue ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(xCopyPosition == queueSEND_TO_BACK ? (TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCFAILED, QUEUE, pxQueue)) : TRACE_QUEUE_SEND_TO_FRONT_TRCFAILED, QUEUE, pxQueue); + +/* Called when the task is blocked due to a send operation on a full queue */ +#undef traceBLOCKING_ON_QUEUE_SEND +#define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(xCopyPosition == queueSEND_TO_BACK ? (TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCBLOCK, QUEUE, pxQueue)) : TRACE_QUEUE_SEND_TO_FRONT_TRCBLOCK, QUEUE, pxQueue); + +/* Called when a message is received from a queue */ +#undef traceQUEUE_RECEIVE +#define traceQUEUE_RECEIVE( pxQueue ) \ + if (isQueueReceiveHookActuallyPeek) \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ + } \ + else \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ + } \ + trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, pxQueue, TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) == TRACE_CLASS_MUTEX ? (uint8_t)TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()) : (uint8_t)(pxQueue->uxMessagesWaiting - 1)); + +/* Called when a receive operation on a queue fails (timeout) */ +#undef traceQUEUE_RECEIVE_FAILED +#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \ + if (isQueueReceiveHookActuallyPeek) \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); \ + } \ + else \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); \ + } + +/* Called when the task is blocked due to a receive operation on an empty queue */ +#undef traceBLOCKING_ON_QUEUE_RECEIVE +#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) \ + if (isQueueReceiveHookActuallyPeek) \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue); \ + } \ + else \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue); \ + } \ + if (TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) != TRACE_CLASS_MUTEX) \ + { \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); \ + } + +/* Called on xQueuePeek */ +#undef traceQUEUE_PEEK +#define traceQUEUE_PEEK( pxQueue ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); + +/* Called on xQueuePeek fail/timeout (added in FreeRTOS v9.0.2) */ +#undef traceQUEUE_PEEK_FAILED +#define traceQUEUE_PEEK_FAILED( pxQueue ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); + +/* Called on xQueuePeek blocking (added in FreeRTOS v9.0.2) */ +#undef traceBLOCKING_ON_QUEUE_PEEK +#define traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(PEEK, TRCBLOCK, QUEUE, pxQueue), QUEUE, pxQueue); \ + if (TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, pxQueue) != TRACE_CLASS_MUTEX) \ + { \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); \ + } + +/* 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_FROM_ISR(xCopyPosition == queueSEND_TO_BACK ? (TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCSUCCESS, QUEUE, pxQueue)) : TRACE_QUEUE_SEND_TO_FRONT_FROM_ISR_TRCSUCCESS, QUEUE, pxQueue); \ + trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, 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_FROM_ISR(xCopyPosition == queueSEND_TO_BACK ? (TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCFAILED, QUEUE, pxQueue)) : TRACE_QUEUE_SEND_TO_FRONT_FROM_ISR_TRCFAILED, QUEUE, 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_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCSUCCESS, QUEUE, pxQueue), QUEUE, pxQueue); \ + trcKERNEL_HOOKS_SET_OBJECT_STATE(QUEUE, 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_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCFAILED, QUEUE, pxQueue), QUEUE, pxQueue); + +#undef traceQUEUE_REGISTRY_ADD +#define traceQUEUE_REGISTRY_ADD(object, name) prvTraceSetObjectName(TRACE_GET_OBJECT_TRACE_CLASS(QUEUE, object), TRACE_GET_OBJECT_NUMBER(QUEUE, object), name); + +/* 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_FROM_ISR(TASK_RESUME_FROM_ISR, pxTaskToResume); + + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) + +#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) + +extern void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t size); + +/* MALLOC and FREE are always stored, no matter if they happen inside filtered task */ +#undef traceMALLOC +#define traceMALLOC( pvAddress, uiSize ) \ + if (pvAddress != 0) \ + { \ + vTraceStoreMemMangEvent(MEM_MALLOC_SIZE, ( uint32_t ) pvAddress, (int32_t)uiSize); \ + } \ + else \ + { \ + vTraceStoreMemMangEvent(MEM_MALLOC_SIZE_TRCFAILED, ( uint32_t ) pvAddress, (int32_t)uiSize); \ + } + +#undef traceFREE +#define traceFREE( pvAddress, uiSize ) \ + vTraceStoreMemMangEvent(MEM_FREE_SIZE, ( uint32_t ) pvAddress, -((int32_t)uiSize)); + +#endif /* (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) */ + +#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) + +/* Called in timer.c - xTimerCreate */ +#undef traceTIMER_CREATE +#define traceTIMER_CREATE(tmr) \ + trcKERNEL_HOOKS_OBJECT_CREATE(TIMER_CREATE, TIMER, tmr); + +#undef traceTIMER_CREATE_FAILED +#define traceTIMER_CREATE_FAILED() \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TIMER_CREATE_TRCFAILED, 0); + +/* Note that xCommandID can never be tmrCOMMAND_EXECUTE_CALLBACK (-1) since the trace macro is not called in that case */ +#undef traceTIMER_COMMAND_SEND +#define traceTIMER_COMMAND_SEND(tmr, xCommandID, xOptionalValue, xReturn) \ + if (xCommandID > tmrCOMMAND_START_DONT_TRACE) \ + { \ + if (xCommandID == tmrCOMMAND_CHANGE_PERIOD) \ + { \ + if (xReturn == pdPASS) { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TIMER_CHANGE_PERIOD, TIMER, tmr, xOptionalValue); \ + } \ + else \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TIMER_CHANGE_PERIOD_TRCFAILED, TIMER, tmr, xOptionalValue); \ + } \ + } \ + else if ((xCommandID == tmrCOMMAND_DELETE) && (xReturn == pdPASS)) \ + { \ + trcKERNEL_HOOKS_OBJECT_DELETE(TIMER_DELETE_OBJ, EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr), EVENTGROUP_OBJCLOSE_PROP_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(TIMER, tmr), TIMER, tmr); \ + } \ + else \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENTGROUP_TIMER + (uint32_t)xCommandID + ((xReturn == pdPASS) ? 0 : (TIMER_CREATE_TRCFAILED - TIMER_CREATE)), TIMER, tmr, xOptionalValue); \ + }\ + } + +#undef traceTIMER_EXPIRED +#define traceTIMER_EXPIRED(tmr) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TIMER_EXPIRED, TIMER, tmr); + +#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) */ + +#if (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) + +#undef tracePEND_FUNC_CALL +#define tracePEND_FUNC_CALL(func, arg1, arg2, ret) \ + if (ret == pdPASS){ \ + trcKERNEL_HOOKS_KERNEL_SERVICE(PEND_FUNC_CALL, TASK, xTimerGetTimerDaemonTaskHandle() ); \ + } \ + else \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE(PEND_FUNC_CALL_TRCFAILED, TASK, xTimerGetTimerDaemonTaskHandle() ); \ + } + +#undef tracePEND_FUNC_CALL_FROM_ISR +#define tracePEND_FUNC_CALL_FROM_ISR(func, arg1, arg2, ret) \ + if (! uiInEventGroupSetBitsFromISR) \ + prvTraceStoreKernelCall(PEND_FUNC_CALL_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTimerGetTimerDaemonTaskHandle()) ); \ + uiInEventGroupSetBitsFromISR = 0; + +#endif /* (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) */ + +#endif /* (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) */ + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) + +#undef traceEVENT_GROUP_CREATE +#define traceEVENT_GROUP_CREATE(eg) \ + trcKERNEL_HOOKS_OBJECT_CREATE(EVENT_GROUP_CREATE, EVENTGROUP, eg); + +#undef traceEVENT_GROUP_CREATE_FAILED +#define traceEVENT_GROUP_CREATE_FAILED() \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(EVENT_GROUP_CREATE_TRCFAILED, 0); + +#undef traceEVENT_GROUP_DELETE +#define traceEVENT_GROUP_DELETE(eg) \ + { TRACE_ALLOC_CRITICAL_SECTION(); \ + TRACE_ENTER_CRITICAL_SECTION(); \ + trcKERNEL_HOOKS_OBJECT_DELETE(EVENT_GROUP_DELETE_OBJ, EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg), EVENTGROUP_OBJCLOSE_NAME_TRCSUCCESS + TRACE_GET_OBJECT_TRACE_CLASS(EVENTGROUP, eg), EVENTGROUP, eg); \ + TRACE_EXIT_CRITICAL_SECTION(); } + +#undef traceEVENT_GROUP_SYNC_BLOCK +#define traceEVENT_GROUP_SYNC_BLOCK(eg, bitsToSet, bitsToWaitFor) \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SYNC_TRCBLOCK, EVENTGROUP, eg, bitsToWaitFor); + +#undef traceEVENT_GROUP_SYNC_END +#define traceEVENT_GROUP_SYNC_END(eg, bitsToSet, bitsToWaitFor, wasTimeout) \ + if (wasTimeout) \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SYNC_END_TRCFAILED, EVENTGROUP, eg, bitsToWaitFor); \ + } \ + else \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SYNC_END, EVENTGROUP, eg, bitsToWaitFor); \ + } + +#undef traceEVENT_GROUP_WAIT_BITS_BLOCK +#define traceEVENT_GROUP_WAIT_BITS_BLOCK(eg, bitsToWaitFor) \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_WAIT_BITS_TRCBLOCK, EVENTGROUP, eg, bitsToWaitFor); \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); + +#undef traceEVENT_GROUP_WAIT_BITS_END +#define traceEVENT_GROUP_WAIT_BITS_END(eg, bitsToWaitFor, wasTimeout) \ + if (wasTimeout) \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_WAIT_BITS_END_TRCFAILED, EVENTGROUP, eg, bitsToWaitFor); \ + } \ + else \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_WAIT_BITS_END, EVENTGROUP, eg, bitsToWaitFor); \ + } + +#undef traceEVENT_GROUP_CLEAR_BITS +#define traceEVENT_GROUP_CLEAR_BITS(eg, bitsToClear) \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_CLEAR_BITS, EVENTGROUP, eg, bitsToClear); + +#undef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR +#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(eg, bitsToClear) \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(EVENT_GROUP_CLEAR_BITS_FROM_ISR, EVENTGROUP, eg, bitsToClear); + +#undef traceEVENT_GROUP_SET_BITS +#define traceEVENT_GROUP_SET_BITS(eg, bitsToSet) \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(EVENT_GROUP_SET_BITS, EVENTGROUP, eg, bitsToSet); + +#undef traceEVENT_GROUP_SET_BITS_FROM_ISR +#define traceEVENT_GROUP_SET_BITS_FROM_ISR(eg, bitsToSet) \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(EVENT_GROUP_SET_BITS_FROM_ISR, EVENTGROUP, eg, bitsToSet); \ + uiInEventGroupSetBitsFromISR = 1; + +#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */ + +#undef traceTASK_NOTIFY_TAKE +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) +#define traceTASK_NOTIFY_TAKE() \ + if (pxCurrentTCB->eNotifyState == eNotified){ \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE, TASK, pxCurrentTCB, xTicksToWait); \ + } \ + else{ \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCFAILED, TASK, pxCurrentTCB, xTicksToWait); \ + } +#elif (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_TAKE() \ + if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED){ \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE, TASK, pxCurrentTCB, xTicksToWait); \ + }else{ \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCFAILED, TASK, pxCurrentTCB, xTicksToWait);} +#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */ +#define traceTASK_NOTIFY_TAKE(index) \ + if (pxCurrentTCB->ucNotifyState[index] == taskNOTIFICATION_RECEIVED){ \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE, TASK, pxCurrentTCB, xTicksToWait); \ + }else{ \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCFAILED, TASK, pxCurrentTCB, xTicksToWait);} +#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */ + +#undef traceTASK_NOTIFY_TAKE_BLOCK +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_TAKE_BLOCK() \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCBLOCK, TASK, pxCurrentTCB, xTicksToWait); \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); +#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY_TAKE_BLOCK(index) \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(TRACE_TASK_NOTIFY_TAKE_TRCBLOCK, TASK, pxCurrentTCB, xTicksToWait); \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); +#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceTASK_NOTIFY_WAIT +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) +#define traceTASK_NOTIFY_WAIT() \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \ + { \ + if (pxCurrentTCB->eNotifyState == eNotified) \ + prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ + else \ + prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCFAILED, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ + } +#elif (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_WAIT() \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \ + { \ + if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \ + prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ + else \ + prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCFAILED, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ + } +#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */ +#define traceTASK_NOTIFY_WAIT(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \ + { \ + if (pxCurrentTCB->ucNotifyState[index] == taskNOTIFICATION_RECEIVED) \ + prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ + else \ + prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCFAILED, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ + } +#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0 */ + +#undef traceTASK_NOTIFY_WAIT_BLOCK +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_WAIT_BLOCK() \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \ + prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCBLOCK, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); +#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY_WAIT_BLOCK(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxCurrentTCB) & CurrentFilterMask) \ + prvTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_TRCBLOCK, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxCurrentTCB), xTicksToWait); \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); +#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceTASK_NOTIFY +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreKernelCall(TRACE_TASK_NOTIFY, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify)); +#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreKernelCall(TRACE_TASK_NOTIFY, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify)); +#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceTASK_NOTIFY_FROM_ISR +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_FROM_ISR() \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreKernelCall(TRACE_TASK_NOTIFY_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify)); +#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY_FROM_ISR(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreKernelCall(TRACE_TASK_NOTIFY_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify)); +#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceTASK_NOTIFY_GIVE_FROM_ISR +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_GIVE_FROM_ISR() \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreKernelCall(TRACE_TASK_NOTIFY_GIVE_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify)); +#else /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY_GIVE_FROM_ISR(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreKernelCall(TRACE_TASK_NOTIFY_GIVE_FROM_ISR, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(xTaskToNotify)); +#endif /* TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_10_4_0 */ + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) + +#undef traceSTREAM_BUFFER_CREATE +#define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) \ + trcKERNEL_HOOKS_OBJECT_CREATE(TRACE_GET_OBJECT_EVENT_CODE(CREATE_OBJ, TRCSUCCESS, STREAMBUFFER, pxStreamBuffer), STREAMBUFFER, pxStreamBuffer); + +#undef traceSTREAM_BUFFER_CREATE_FAILED +#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, STREAMBUFFER, xIsMessageBuffer), 0); + +#undef traceSTREAM_BUFFER_CREATE_STATIC_FAILED +#define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ) \ + traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) + +#undef traceSTREAM_BUFFER_DELETE +#define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) \ + trcKERNEL_HOOKS_OBJECT_DELETE(TRACE_GET_OBJECT_EVENT_CODE(DELETE_OBJ, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_NAME, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), TRACE_GET_OBJECT_EVENT_CODE(OBJCLOSE_PROP, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); + +#undef traceSTREAM_BUFFER_RESET +#define traceSTREAM_BUFFER_RESET( xStreamBuffer ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(prvGetStreamBufferType(xStreamBuffer) > 0 ? TRACE_MESSAGEBUFFER_RESET : TRACE_STREAMBUFFER_RESET, STREAMBUFFER, xStreamBuffer); \ + trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, 0); + +#undef traceSTREAM_BUFFER_SEND +#define traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ + trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); + +#undef traceBLOCKING_ON_STREAM_BUFFER_SEND +#define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCBLOCK, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); + +#undef traceSTREAM_BUFFER_SEND_FAILED +#define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(SEND, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); + +#undef traceSTREAM_BUFFER_RECEIVE +#define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ + trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); + + +#undef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE +#define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCBLOCK, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); + +#undef traceSTREAM_BUFFER_RECEIVE_FAILED +#define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) \ + trcKERNEL_HOOKS_KERNEL_SERVICE(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); + +#undef traceSTREAM_BUFFER_SEND_FROM_ISR +#define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ) \ + if( xReturn > ( size_t ) 0 ) \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ + trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \ + } \ + else \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(SEND_FROM_ISR, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ + } + +#undef traceSTREAM_BUFFER_RECEIVE_FROM_ISR +#define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) \ + if( xReceivedLength > ( size_t ) 0 ) \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCSUCCESS, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ + trcKERNEL_HOOKS_SET_OBJECT_STATE(STREAMBUFFER, xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \ + } \ + else \ + { \ + trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(TRACE_GET_OBJECT_EVENT_CODE(RECEIVE_FROM_ISR, TRCFAILED, STREAMBUFFER, xStreamBuffer), STREAMBUFFER, xStreamBuffer); \ + } + +#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ + +#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */ + +#endif /*#if TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT */ + +/******************************************************************************/ +/*** Definitions for Streaming mode *******************************************/ +/******************************************************************************/ +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +/******************************************************************************* +* vTraceStoreKernelObjectName +* +* Set the name for a kernel object (defined by its address). +******************************************************************************/ +void vTraceStoreKernelObjectName(void* object, const char* name); + +/******************************************************************************* +* prvIsNewTCB +* +* Tells if this task is already executing, or if there has been a task-switch. +* Assumed to be called within a trace hook in kernel context. +*******************************************************************************/ +uint32_t prvIsNewTCB(void* pNewTCB); + +#define TRACE_GET_CURRENT_TASK() prvTraceGetCurrentTaskHandle() + +/*************************************************************************/ +/* KERNEL SPECIFIC OBJECT CONFIGURATION */ +/*************************************************************************/ + +/******************************************************************************* + * The event codes - should match the offline config file. + ******************************************************************************/ + +/*** Event codes for streaming - should match the Tracealyzer config file *****/ +#define PSF_EVENT_NULL_EVENT 0x00 + +#define PSF_EVENT_TRACE_START 0x01 +#define PSF_EVENT_TS_CONFIG 0x02 +#define PSF_EVENT_OBJ_NAME 0x03 +#define PSF_EVENT_TASK_PRIORITY 0x04 +#define PSF_EVENT_TASK_PRIO_INHERIT 0x05 +#define PSF_EVENT_TASK_PRIO_DISINHERIT 0x06 +#define PSF_EVENT_DEFINE_ISR 0x07 + +#define PSF_EVENT_TASK_CREATE 0x10 +#define PSF_EVENT_QUEUE_CREATE 0x11 +#define PSF_EVENT_SEMAPHORE_BINARY_CREATE 0x12 +#define PSF_EVENT_MUTEX_CREATE 0x13 +#define PSF_EVENT_TIMER_CREATE 0x14 +#define PSF_EVENT_EVENTGROUP_CREATE 0x15 +#define PSF_EVENT_SEMAPHORE_COUNTING_CREATE 0x16 +#define PSF_EVENT_MUTEX_RECURSIVE_CREATE 0x17 +#define PSF_EVENT_STREAMBUFFER_CREATE 0x18 +#define PSF_EVENT_MESSAGEBUFFER_CREATE 0x19 + +#define PSF_EVENT_TASK_DELETE 0x20 +#define PSF_EVENT_QUEUE_DELETE 0x21 +#define PSF_EVENT_SEMAPHORE_DELETE 0x22 +#define PSF_EVENT_MUTEX_DELETE 0x23 +#define PSF_EVENT_TIMER_DELETE 0x24 +#define PSF_EVENT_EVENTGROUP_DELETE 0x25 +#define PSF_EVENT_STREAMBUFFER_DELETE 0x28 +#define PSF_EVENT_MESSAGEBUFFER_DELETE 0x29 + +#define PSF_EVENT_TASK_READY 0x30 +#define PSF_EVENT_NEW_TIME 0x31 +#define PSF_EVENT_NEW_TIME_SCHEDULER_SUSPENDED 0x32 +#define PSF_EVENT_ISR_BEGIN 0x33 +#define PSF_EVENT_ISR_RESUME 0x34 +#define PSF_EVENT_TS_BEGIN 0x35 +#define PSF_EVENT_TS_RESUME 0x36 +#define PSF_EVENT_TASK_ACTIVATE 0x37 + +#define PSF_EVENT_MALLOC 0x38 +#define PSF_EVENT_FREE 0x39 + +#define PSF_EVENT_LOWPOWER_BEGIN 0x3A +#define PSF_EVENT_LOWPOWER_END 0x3B + +#define PSF_EVENT_IFE_NEXT 0x3C +#define PSF_EVENT_IFE_DIRECT 0x3D + +#define PSF_EVENT_TASK_CREATE_FAILED 0x40 +#define PSF_EVENT_QUEUE_CREATE_FAILED 0x41 +#define PSF_EVENT_SEMAPHORE_BINARY_CREATE_FAILED 0x42 +#define PSF_EVENT_MUTEX_CREATE_FAILED 0x43 +#define PSF_EVENT_TIMER_CREATE_FAILED 0x44 +#define PSF_EVENT_EVENTGROUP_CREATE_FAILED 0x45 +#define PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED 0x46 +#define PSF_EVENT_MUTEX_RECURSIVE_CREATE_FAILED 0x47 +#define PSF_EVENT_STREAMBUFFER_CREATE_FAILED 0x49 +#define PSF_EVENT_MESSAGEBUFFER_CREATE_FAILED 0x4A + +#define PSF_EVENT_TIMER_DELETE_FAILED 0x48 + +#define PSF_EVENT_QUEUE_SEND 0x50 +#define PSF_EVENT_SEMAPHORE_GIVE 0x51 +#define PSF_EVENT_MUTEX_GIVE 0x52 + +#define PSF_EVENT_QUEUE_SEND_FAILED 0x53 +#define PSF_EVENT_SEMAPHORE_GIVE_FAILED 0x54 +#define PSF_EVENT_MUTEX_GIVE_FAILED 0x55 + +#define PSF_EVENT_QUEUE_SEND_BLOCK 0x56 +#define PSF_EVENT_SEMAPHORE_GIVE_BLOCK 0x57 +#define PSF_EVENT_MUTEX_GIVE_BLOCK 0x58 + +#define PSF_EVENT_QUEUE_SEND_FROMISR 0x59 +#define PSF_EVENT_SEMAPHORE_GIVE_FROMISR 0x5A + +#define PSF_EVENT_QUEUE_SEND_FROMISR_FAILED 0x5C +#define PSF_EVENT_SEMAPHORE_GIVE_FROMISR_FAILED 0x5D + +#define PSF_EVENT_QUEUE_RECEIVE 0x60 +#define PSF_EVENT_SEMAPHORE_TAKE 0x61 +#define PSF_EVENT_MUTEX_TAKE 0x62 + +#define PSF_EVENT_QUEUE_RECEIVE_FAILED 0x63 +#define PSF_EVENT_SEMAPHORE_TAKE_FAILED 0x64 +#define PSF_EVENT_MUTEX_TAKE_FAILED 0x65 + +#define PSF_EVENT_QUEUE_RECEIVE_BLOCK 0x66 +#define PSF_EVENT_SEMAPHORE_TAKE_BLOCK 0x67 +#define PSF_EVENT_MUTEX_TAKE_BLOCK 0x68 + +#define PSF_EVENT_QUEUE_RECEIVE_FROMISR 0x69 +#define PSF_EVENT_SEMAPHORE_TAKE_FROMISR 0x6A + +#define PSF_EVENT_QUEUE_RECEIVE_FROMISR_FAILED 0x6C +#define PSF_EVENT_SEMAPHORE_TAKE_FROMISR_FAILED 0x6D + +#define PSF_EVENT_QUEUE_PEEK 0x70 +#define PSF_EVENT_SEMAPHORE_PEEK 0x71 +#define PSF_EVENT_MUTEX_PEEK 0x72 + +#define PSF_EVENT_QUEUE_PEEK_FAILED 0x73 +#define PSF_EVENT_SEMAPHORE_PEEK_FAILED 0x74 +#define PSF_EVENT_MUTEX_PEEK_FAILED 0x75 + +#define PSF_EVENT_QUEUE_PEEK_BLOCK 0x76 +#define PSF_EVENT_SEMAPHORE_PEEK_BLOCK 0x77 +#define PSF_EVENT_MUTEX_PEEK_BLOCK 0x78 + +#define PSF_EVENT_TASK_DELAY_UNTIL 0x79 +#define PSF_EVENT_TASK_DELAY 0x7A +#define PSF_EVENT_TASK_SUSPEND 0x7B +#define PSF_EVENT_TASK_RESUME 0x7C +#define PSF_EVENT_TASK_RESUME_FROMISR 0x7D + +#define PSF_EVENT_TIMER_PENDFUNCCALL 0x80 +#define PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR 0x81 +#define PSF_EVENT_TIMER_PENDFUNCCALL_FAILED 0x82 +#define PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR_FAILED 0x83 + +#define PSF_EVENT_USER_EVENT 0x90 + +#define PSF_EVENT_TIMER_START 0xA0 +#define PSF_EVENT_TIMER_RESET 0xA1 +#define PSF_EVENT_TIMER_STOP 0xA2 +#define PSF_EVENT_TIMER_CHANGEPERIOD 0xA3 +#define PSF_EVENT_TIMER_START_FROMISR 0xA4 +#define PSF_EVENT_TIMER_RESET_FROMISR 0xA5 +#define PSF_EVENT_TIMER_STOP_FROMISR 0xA6 +#define PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR 0xA7 +#define PSF_EVENT_TIMER_START_FAILED 0xA8 +#define PSF_EVENT_TIMER_RESET_FAILED 0xA9 +#define PSF_EVENT_TIMER_STOP_FAILED 0xAA +#define PSF_EVENT_TIMER_CHANGEPERIOD_FAILED 0xAB +#define PSF_EVENT_TIMER_START_FROMISR_FAILED 0xAC +#define PSF_EVENT_TIMER_RESET_FROMISR_FAILED 0xAD +#define PSF_EVENT_TIMER_STOP_FROMISR_FAILED 0xAE +#define PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR_FAILED 0xAF + +#define PSF_EVENT_EVENTGROUP_SYNC 0xB0 +#define PSF_EVENT_EVENTGROUP_WAITBITS 0xB1 +#define PSF_EVENT_EVENTGROUP_CLEARBITS 0xB2 +#define PSF_EVENT_EVENTGROUP_CLEARBITS_FROMISR 0xB3 +#define PSF_EVENT_EVENTGROUP_SETBITS 0xB4 +#define PSF_EVENT_EVENTGROUP_SETBITS_FROMISR 0xB5 +#define PSF_EVENT_EVENTGROUP_SYNC_BLOCK 0xB6 +#define PSF_EVENT_EVENTGROUP_WAITBITS_BLOCK 0xB7 +#define PSF_EVENT_EVENTGROUP_SYNC_FAILED 0xB8 +#define PSF_EVENT_EVENTGROUP_WAITBITS_FAILED 0xB9 + +#define PSF_EVENT_QUEUE_SEND_FRONT 0xC0 +#define PSF_EVENT_QUEUE_SEND_FRONT_FAILED 0xC1 +#define PSF_EVENT_QUEUE_SEND_FRONT_BLOCK 0xC2 +#define PSF_EVENT_QUEUE_SEND_FRONT_FROMISR 0xC3 +#define PSF_EVENT_QUEUE_SEND_FRONT_FROMISR_FAILED 0xC4 +#define PSF_EVENT_MUTEX_GIVE_RECURSIVE 0xC5 +#define PSF_EVENT_MUTEX_GIVE_RECURSIVE_FAILED 0xC6 +#define PSF_EVENT_MUTEX_TAKE_RECURSIVE 0xC7 +#define PSF_EVENT_MUTEX_TAKE_RECURSIVE_FAILED 0xC8 + +#define PSF_EVENT_TASK_NOTIFY 0xC9 +#define PSF_EVENT_TASK_NOTIFY_TAKE 0xCA +#define PSF_EVENT_TASK_NOTIFY_TAKE_BLOCK 0xCB +#define PSF_EVENT_TASK_NOTIFY_TAKE_FAILED 0xCC +#define PSF_EVENT_TASK_NOTIFY_WAIT 0xCD +#define PSF_EVENT_TASK_NOTIFY_WAIT_BLOCK 0xCE +#define PSF_EVENT_TASK_NOTIFY_WAIT_FAILED 0xCF +#define PSF_EVENT_TASK_NOTIFY_FROM_ISR 0xD0 +#define PSF_EVENT_TASK_NOTIFY_GIVE_FROM_ISR 0xD1 + +#define PSF_EVENT_TIMER_EXPIRED 0xD2 + +#define PSF_EVENT_STREAMBUFFER_SEND 0xD3 +#define PSF_EVENT_STREAMBUFFER_SEND_BLOCK 0xD4 +#define PSF_EVENT_STREAMBUFFER_SEND_FAILED 0xD5 +#define PSF_EVENT_STREAMBUFFER_RECEIVE 0xD6 +#define PSF_EVENT_STREAMBUFFER_RECEIVE_BLOCK 0xD7 +#define PSF_EVENT_STREAMBUFFER_RECEIVE_FAILED 0xD8 +#define PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR 0xD9 +#define PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR_FAILED 0xDA +#define PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR 0xDB +#define PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR_FAILED 0xDC +#define PSF_EVENT_STREAMBUFFER_RESET 0xDD + +#define PSF_EVENT_MESSAGEBUFFER_SEND 0xDE +#define PSF_EVENT_MESSAGEBUFFER_SEND_BLOCK 0xDF +#define PSF_EVENT_MESSAGEBUFFER_SEND_FAILED 0xE0 +#define PSF_EVENT_MESSAGEBUFFER_RECEIVE 0xE1 +#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_BLOCK 0xE2 +#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_FAILED 0xE3 +#define PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR 0xE4 +#define PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR_FAILED 0xE5 +#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR 0xE6 +#define PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR_FAILED 0xE7 +#define PSF_EVENT_MESSAGEBUFFER_RESET 0xE8 + +#define PSF_EVENT_MALLOC_FAILED 0xE9 + +#define PSF_EVENT_UNUSED_STACK 0xEA + +/*** The trace macros for streaming ******************************************/ + +/* A macro that will update the tick count when returning from tickless idle */ +#undef traceINCREASE_TICK_COUNT +/* Note: This can handle time adjustments of max 2^32 ticks, i.e., 35 seconds at 120 MHz. Thus, tick-less idle periods longer than 2^32 ticks will appear "compressed" on the time line.*/ +#define traceINCREASE_TICK_COUNT( xCount ) { extern uint32_t uiTraceTickCount; uiTraceTickCount += xCount; } + +#if (TRC_CFG_INCLUDE_OSTICK_EVENTS == 1) +#define OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) if (uxSchedulerSuspended == (unsigned portBASE_TYPE) pdFALSE) { prvTraceStoreEvent1(PSF_EVENT_NEW_TIME, (uint32_t)(xTickCount + 1)); } +#else +#define OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) +#endif + +/* Called on each OS tick. Will call uiPortGetTimestamp to make sure it is called at least once every OS tick. */ +#undef traceTASK_INCREMENT_TICK +#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_3_0 + +#define traceTASK_INCREMENT_TICK( xTickCount ) \ + if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || xPendedTicks == 0) { extern uint32_t uiTraceTickCount; uiTraceTickCount++; } \ + OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) + +#elif TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_5_X + +#define traceTASK_INCREMENT_TICK( xTickCount ) \ + if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxPendedTicks == 0) { extern uint32_t uiTraceTickCount; uiTraceTickCount++; } \ + OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) + +#else + +#define traceTASK_INCREMENT_TICK( xTickCount ) \ + if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxMissedTicks == 0) { extern uint32_t uiTraceTickCount; uiTraceTickCount++; } \ + OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) + +#endif + +extern volatile uint32_t uiTraceSystemState; + +/* Called on each task-switch */ +#undef traceTASK_SWITCHED_IN +#define traceTASK_SWITCHED_IN() \ + uiTraceSystemState = TRC_STATE_IN_TASKSWITCH; \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + { \ + if (prvIsNewTCB(pxCurrentTCB)) \ + { \ + prvTraceStoreEvent2(PSF_EVENT_TASK_ACTIVATE, (uint32_t)pxCurrentTCB, pxCurrentTCB->uxPriority); \ + } \ + } \ + uiTraceSystemState = TRC_STATE_IN_APPLICATION; + +/* Called for each task that becomes ready */ +#if (TRC_CFG_INCLUDE_READY_EVENTS == 1) +#undef traceMOVED_TASK_TO_READY_STATE +#define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_READY, (uint32_t)pxTCB); +#endif + +#undef traceTASK_CREATE +#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 +#define traceTASK_CREATE(pxNewTCB) \ + if (pxNewTCB != NULL) \ + { \ + prvAddTaskToStackMonitor(pxNewTCB); \ + prvTraceSaveObjectSymbol(pxNewTCB, pxNewTCB->pcTaskName); \ + prvTraceSaveObjectData(pxNewTCB, pxNewTCB->uxPriority); \ + prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, pxNewTCB->pcTaskName, pxNewTCB); \ + TRACE_SET_OBJECT_FILTER(TASK, pxNewTCB, CurrentFilterGroup); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxNewTCB) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_CREATE, (uint32_t)pxNewTCB, pxNewTCB->uxPriority); \ + } +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ +#define traceTASK_CREATE(pxNewTCB) \ + if (pxNewTCB != NULL) \ + { \ + prvAddTaskToStackMonitor(pxNewTCB); \ + prvTraceSaveObjectSymbol(pxNewTCB, (const char*)pcName); \ + prvTraceSaveObjectData(pxNewTCB, uxPriority); \ + prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, (const char*)pcName, pxNewTCB); \ + TRACE_SET_OBJECT_FILTER(TASK, pxNewTCB, CurrentFilterGroup); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxNewTCB) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_CREATE, (uint32_t)pxNewTCB, uxPriority); \ + } +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ + +/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */ +#undef traceTASK_CREATE_FAILED +#define traceTASK_CREATE_FAILED() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent0(PSF_EVENT_TASK_CREATE_FAILED); + +/* Called on vTaskDelete */ +#undef traceTASK_DELETE // We don't allow for filtering out "delete" events. They are important and not very frequent. Moreover, we can't exclude create events, so this should be symmetrical. +#define traceTASK_DELETE( pxTaskToDelete ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToDelete) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_DELETE, (uint32_t)pxTaskToDelete, (pxTaskToDelete != NULL) ? (pxTaskToDelete->uxPriority) : 0); \ + prvTraceDeleteSymbol(pxTaskToDelete); \ + prvTraceDeleteObjectData(pxTaskToDelete); \ + prvRemoveTaskFromStackMonitor(pxTaskToDelete); + +#if (TRC_CFG_SCHEDULING_ONLY == 0) + +#if (defined(configUSE_TICKLESS_IDLE) && configUSE_TICKLESS_IDLE != 0) + +#undef traceLOW_POWER_IDLE_BEGIN +#define traceLOW_POWER_IDLE_BEGIN() \ + { \ + prvTraceStoreEvent1(PSF_EVENT_LOWPOWER_BEGIN, xExpectedIdleTime); \ + } + +#undef traceLOW_POWER_IDLE_END +#define traceLOW_POWER_IDLE_END() \ + { \ + prvTraceStoreEvent0(PSF_EVENT_LOWPOWER_END); \ + } + +#endif /* (defined(configUSE_TICKLESS_IDLE) && configUSE_TICKLESS_IDLE != 0) */ + +/* Called on vTaskSuspend */ +#undef traceTASK_SUSPEND +#define traceTASK_SUSPEND( pxTaskToSuspend ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToSuspend) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_SUSPEND, (uint32_t)pxTaskToSuspend); + +/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */ +#undef traceTASK_DELAY +#define traceTASK_DELAY() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_DELAY, xTicksToDelay); + +/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */ +#undef traceTASK_DELAY_UNTIL +#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 +#define traceTASK_DELAY_UNTIL(xTimeToWake) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_DELAY_UNTIL, (uint32_t)xTimeToWake); +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ +#define traceTASK_DELAY_UNTIL() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_DELAY_UNTIL, (uint32_t)xTimeToWake); +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 */ + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) +#define traceQUEUE_CREATE_HELPER() \ + case queueQUEUE_TYPE_MUTEX: \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE, (uint32_t)pxNewQueue); \ + break; \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_RECURSIVE_CREATE, (uint32_t)pxNewQueue); \ + break; +#else +#define traceQUEUE_CREATE_HELPER() +#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */ + +/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */ +#undef traceQUEUE_CREATE +#define traceQUEUE_CREATE( pxNewQueue )\ + TRACE_SET_OBJECT_FILTER(QUEUE, pxNewQueue, CurrentFilterGroup); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + { \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxNewQueue) & CurrentFilterMask) \ + { \ + switch (pxNewQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent2(PSF_EVENT_QUEUE_CREATE, (uint32_t)pxNewQueue, uxQueueLength); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + prvTraceStoreEvent1(PSF_EVENT_SEMAPHORE_BINARY_CREATE, (uint32_t)pxNewQueue); \ + break; \ + traceQUEUE_CREATE_HELPER() \ + } \ + } \ + } + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) +#define traceQUEUE_CREATE_FAILED_HELPER() \ + case queueQUEUE_TYPE_MUTEX: \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE_FAILED, 0); \ + break; \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_RECURSIVE_CREATE_FAILED, 0); \ + break; +#else +#define traceQUEUE_CREATE_FAILED_HELPER() +#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */ + +/* Called in xQueueCreate, if the queue creation fails */ +#undef traceQUEUE_CREATE_FAILED +#define traceQUEUE_CREATE_FAILED( queueType ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + { \ + switch (queueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent2(PSF_EVENT_QUEUE_CREATE_FAILED, 0, uxQueueLength); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + prvTraceStoreEvent1(PSF_EVENT_SEMAPHORE_BINARY_CREATE_FAILED, 0); \ + break; \ + traceQUEUE_CREATE_FAILED_HELPER() \ + } \ + } + +#undef traceQUEUE_DELETE // We don't allow for filtering out "delete" events. They are important and not very frequent. Moreover, we can't exclude create events, so this should be symmetrical. +#define traceQUEUE_DELETE( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + { \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + { \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent2(PSF_EVENT_QUEUE_DELETE, (uint32_t)pxQueue, (pxQueue != NULL) ? (pxQueue->uxMessagesWaiting) : 0); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent2(PSF_EVENT_MUTEX_DELETE, (uint32_t)pxQueue, (pxQueue != NULL) ? (pxQueue->uxMessagesWaiting) : 0); \ + break; \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_DELETE, (uint32_t)pxQueue, (pxQueue != NULL) ? (pxQueue->uxMessagesWaiting) : 0); \ + break; \ + } \ + } \ + } \ + prvTraceDeleteSymbol(pxQueue); + +/* Called in xQueueCreateCountingSemaphore, if the queue creation fails */ +#undef traceCREATE_COUNTING_SEMAPHORE +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) +#define traceCREATE_COUNTING_SEMAPHORE() \ + TRACE_SET_OBJECT_FILTER(QUEUE, xHandle, CurrentFilterGroup); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, xHandle) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)xHandle, uxMaxCount) +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_5_X) +#define traceCREATE_COUNTING_SEMAPHORE() \ + TRACE_SET_OBJECT_FILTER(QUEUE, xHandle, CurrentFilterGroup); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, xHandle) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)xHandle, uxInitialCount); +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4_X) +#define traceCREATE_COUNTING_SEMAPHORE() \ + TRACE_SET_OBJECT_FILTER(QUEUE, xHandle, CurrentFilterGroup); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, xHandle) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)xHandle, uxCountValue); +#else +#define traceCREATE_COUNTING_SEMAPHORE() \ + TRACE_SET_OBJECT_FILTER(QUEUE, pxHandle, CurrentFilterGroup); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxHandle) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (uint32_t)pxHandle, uxCountValue); +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X */ + +#undef traceCREATE_COUNTING_SEMAPHORE_FAILED +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) +#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxMaxCount); +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_5_X) +#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxInitialCount); +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4_X) +#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxCountValue); +#else +#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxCountValue); +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X */ + + +/* This macro is not necessary as of FreeRTOS v9.0.0 */ +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) +/* Called in xQueueCreateMutex, and thereby also from xSemaphoreCreateMutex and xSemaphoreCreateRecursiveMutex */ +#undef traceCREATE_MUTEX +#define traceCREATE_MUTEX( pxNewQueue ) \ + TRACE_SET_OBJECT_FILTER(QUEUE, pxNewQueue, CurrentFilterGroup); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + { \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxNewQueue) & CurrentFilterMask) \ + { \ + switch (pxNewQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_MUTEX: \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE, (uint32_t)pxNewQueue); \ + break; \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_RECURSIVE_CREATE, (uint32_t)pxNewQueue); \ + break; \ + } \ + }\ + } + +/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */ +#undef traceCREATE_MUTEX_FAILED +#define traceCREATE_MUTEX_FAILED() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_CREATE_FAILED, 0); +#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_9_0_0) */ + +/* Called when a message is sent to a queue */ /* CS IS NEW ! */ +#undef traceQUEUE_SEND +#define traceQUEUE_SEND( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND : PSF_EVENT_QUEUE_SEND_FRONT, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_GIVE, (uint32_t)pxQueue); \ + break; \ + } + +#undef traceQUEUE_SET_SEND +#define traceQUEUE_SET_SEND( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_QUEUE_SEND, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); + +/* Called when a message failed to be sent to a queue (timeout) */ +#undef traceQUEUE_SEND_FAILED +#define traceQUEUE_SEND_FAILED( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FAILED : PSF_EVENT_QUEUE_SEND_FRONT_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_GIVE_FAILED, (uint32_t)pxQueue); \ + break; \ + } + +/* 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 ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_BLOCK : PSF_EVENT_QUEUE_SEND_FRONT_BLOCK, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_BLOCK, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_GIVE_BLOCK, (uint32_t)pxQueue); \ + break; \ + } + +/* Called when a message is sent from interrupt context, e.g., using xQueueSendFromISR */ +#undef traceQUEUE_SEND_FROM_ISR +#define traceQUEUE_SEND_FROM_ISR( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FROMISR : PSF_EVENT_QUEUE_SEND_FRONT_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting + 1); \ + break; \ + } + +/* 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 ) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent2(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FROMISR_FAILED : PSF_EVENT_QUEUE_SEND_FRONT_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_GIVE_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ + break; \ + } + +/* Called when a message is received from a queue */ +#undef traceQUEUE_RECEIVE +#define traceQUEUE_RECEIVE( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + if (isQueueReceiveHookActuallyPeek) \ + prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \ + else\ + prvTraceStoreEvent3(PSF_EVENT_QUEUE_RECEIVE, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + if (isQueueReceiveHookActuallyPeek) \ + prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \ + else \ + prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_TAKE, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting - 1); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + if (isQueueReceiveHookActuallyPeek) \ + prvTraceStoreEvent2(PSF_EVENT_MUTEX_PEEK, (uint32_t)pxQueue, xTicksToWait); \ + else \ + prvTraceStoreEvent2(PSF_EVENT_MUTEX_TAKE, (uint32_t)pxQueue, xTicksToWait); \ + break; \ + } + +/* Called when a receive operation on a queue fails (timeout) */ +#undef traceQUEUE_RECEIVE_FAILED +#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_QUEUE_PEEK_FAILED : PSF_EVENT_QUEUE_RECEIVE_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_SEMAPHORE_PEEK_FAILED : PSF_EVENT_SEMAPHORE_TAKE_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent2(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK_FAILED : PSF_EVENT_MUTEX_TAKE_FAILED, (uint32_t)pxQueue, xTicksToWait); \ + break; \ + } + +/* 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 ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_QUEUE_PEEK_BLOCK : PSF_EVENT_QUEUE_RECEIVE_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent3(isQueueReceiveHookActuallyPeek ? PSF_EVENT_SEMAPHORE_PEEK_BLOCK : PSF_EVENT_SEMAPHORE_TAKE_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent2(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK_BLOCK : PSF_EVENT_MUTEX_TAKE_BLOCK, (uint32_t)pxQueue, xTicksToWait); \ + break; \ + } + +#if (TRC_CFG_FREERTOS_VERSION > TRC_FREERTOS_VERSION_9_0_1) +/* Called when a peek operation on a queue fails (timeout) */ +#undef traceQUEUE_PEEK_FAILED +#define traceQUEUE_PEEK_FAILED( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK_FAILED, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent2(PSF_EVENT_MUTEX_PEEK_FAILED, (uint32_t)pxQueue, xTicksToWait); \ + break; \ + } + +/* Called when the task is blocked due to a peek operation on an empty queue */ +#undef traceBLOCKING_ON_QUEUE_PEEK +#define traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK_BLOCK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent2(PSF_EVENT_MUTEX_PEEK_BLOCK, (uint32_t)pxQueue, xTicksToWait); \ + break; \ + } + +#endif /* (TRC_CFG_FREERTOS_VERSION > TRC_FREERTOS_VERSION_9_0_1) */ + +/* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */ +#undef traceQUEUE_RECEIVE_FROM_ISR +#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent2(PSF_EVENT_QUEUE_RECEIVE_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting - 1); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_TAKE_FROMISR, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting - 1); \ + break; \ + } + +/* 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 ) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent2(PSF_EVENT_QUEUE_RECEIVE_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent2(PSF_EVENT_SEMAPHORE_TAKE_FROMISR_FAILED, (uint32_t)pxQueue, pxQueue->uxMessagesWaiting); \ + break; \ + } + +/* Called on xQueuePeek */ +#undef traceQUEUE_PEEK +#define traceQUEUE_PEEK( pxQueue ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(QUEUE, pxQueue) & CurrentFilterMask) \ + switch (pxQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent3(PSF_EVENT_QUEUE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent3(PSF_EVENT_SEMAPHORE_PEEK, (uint32_t)pxQueue, xTicksToWait, pxQueue->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent1(PSF_EVENT_MUTEX_PEEK, (uint32_t)pxQueue); \ + break; \ + } + +/* Called in vTaskPrioritySet */ +#undef traceTASK_PRIORITY_SET +#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \ + prvTraceSaveObjectData(pxTask, uxNewPriority); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTask) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_PRIORITY, (uint32_t)pxTask, uxNewPriority); + +/* Called in vTaskPriorityInherit, which is called by Mutex operations */ +#undef traceTASK_PRIORITY_INHERIT +#define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTask) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_PRIO_INHERIT, (uint32_t)pxTask, uxNewPriority); + +/* Called in vTaskPriorityDisinherit, which is called by Mutex operations */ +#undef traceTASK_PRIORITY_DISINHERIT +#define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTask) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_PRIO_DISINHERIT, (uint32_t)pxTask, uxNewPriority); + +/* Called in vTaskResume */ +#undef traceTASK_RESUME +#define traceTASK_RESUME( pxTaskToResume ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToResume) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_RESUME, (uint32_t)pxTaskToResume); + +/* Called in vTaskResumeFromISR */ +#undef traceTASK_RESUME_FROM_ISR +#define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTaskToResume) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_RESUME_FROMISR, (uint32_t)pxTaskToResume); + +#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) + +extern uint32_t trcHeapCounter; + +#undef traceMALLOC +#define traceMALLOC( pvAddress, uiSize ) \ + if (pvAddress != 0) \ + { \ + trcHeapCounter += uiSize; \ + } \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + { \ + if (pvAddress != 0) \ + { \ + prvTraceStoreEvent2(PSF_EVENT_MALLOC, (uint32_t)pvAddress, uiSize); \ + } \ + else \ + { \ + prvTraceStoreEvent2(PSF_EVENT_MALLOC_FAILED, (uint32_t)pvAddress, uiSize); \ + } \ + } + +#undef traceFREE +#define traceFREE( pvAddress, uiSize ) \ + trcHeapCounter -= uiSize; \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_FREE, (uint32_t)pvAddress, (uint32_t)(0 - uiSize)); /* "0 -" instead of just "-" to get rid of a warning... */ + +#endif /* (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) */ + +#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) + +/* Called in timer.c - xTimerCreate */ +#undef traceTIMER_CREATE +#define traceTIMER_CREATE(tmr) \ + TRACE_SET_OBJECT_FILTER(TIMER, tmr, CurrentFilterGroup); \ + prvTraceSaveObjectSymbol(tmr, (const char*)tmr->pcTimerName); \ + prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, (const char*)tmr->pcTimerName, tmr); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TIMER, tmr) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TIMER_CREATE, (uint32_t)tmr, tmr->xTimerPeriodInTicks); + +#undef traceTIMER_CREATE_FAILED +#define traceTIMER_CREATE_FAILED() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent0(PSF_EVENT_TIMER_CREATE_FAILED); + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) +#define traceTIMER_COMMAND_SEND_8_0_CASES(tmr) \ + case tmrCOMMAND_RESET: \ + prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_RESET : PSF_EVENT_TIMER_RESET_FAILED, (uint32_t)tmr, xOptionalValue); \ + break; \ + case tmrCOMMAND_START_FROM_ISR: \ + prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_START_FROMISR : PSF_EVENT_TIMER_START_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \ + break; \ + case tmrCOMMAND_RESET_FROM_ISR: \ + prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_RESET_FROMISR : PSF_EVENT_TIMER_RESET_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \ + break; \ + case tmrCOMMAND_STOP_FROM_ISR: \ + prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_STOP_FROMISR : PSF_EVENT_TIMER_STOP_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \ + break; \ + case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR: \ + prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR : PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR_FAILED, (uint32_t)tmr, xOptionalValue); \ + break; +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X */ +#define traceTIMER_COMMAND_SEND_8_0_CASES(tmr) +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X */ + +/* Note that xCommandID can never be tmrCOMMAND_EXECUTE_CALLBACK (-1) since the trace macro is not called in that case */ +#undef traceTIMER_COMMAND_SEND +#define traceTIMER_COMMAND_SEND(tmr, xCommandID, xOptionalValue, xReturn) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TIMER, tmr) & CurrentFilterMask) \ + switch(xCommandID) \ + { \ + case tmrCOMMAND_START: \ + prvTraceStoreEvent1((xReturn == pdPASS) ? PSF_EVENT_TIMER_START : PSF_EVENT_TIMER_START_FAILED, (uint32_t)tmr); \ + break; \ + case tmrCOMMAND_STOP: \ + prvTraceStoreEvent1((xReturn == pdPASS) ? PSF_EVENT_TIMER_STOP : PSF_EVENT_TIMER_STOP_FAILED, (uint32_t)tmr); \ + break; \ + case tmrCOMMAND_CHANGE_PERIOD: \ + prvTraceStoreEvent2((xReturn == pdPASS) ? PSF_EVENT_TIMER_CHANGEPERIOD : PSF_EVENT_TIMER_CHANGEPERIOD_FAILED, (uint32_t)tmr, xOptionalValue); \ + break; \ + case tmrCOMMAND_DELETE: \ + prvTraceStoreEvent1((xReturn == pdPASS) ? PSF_EVENT_TIMER_DELETE : PSF_EVENT_TIMER_DELETE_FAILED, (uint32_t)tmr); \ + break; \ + traceTIMER_COMMAND_SEND_8_0_CASES(tmr) \ + } + +#undef traceTIMER_EXPIRED +#define traceTIMER_EXPIRED(tmr) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TIMER, tmr) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TIMER_EXPIRED, (uint32_t)tmr->pxCallbackFunction, (uint32_t)tmr->pvTimerID); + +#endif /* #if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) */ + + +#if (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) + +#undef tracePEND_FUNC_CALL +#define tracePEND_FUNC_CALL(func, arg1, arg2, ret) \ + prvTraceStoreEvent1((ret == pdPASS) ? PSF_EVENT_TIMER_PENDFUNCCALL : PSF_EVENT_TIMER_PENDFUNCCALL_FAILED, (uint32_t)func); + +#undef tracePEND_FUNC_CALL_FROM_ISR +#define tracePEND_FUNC_CALL_FROM_ISR(func, arg1, arg2, ret) \ + prvTraceStoreEvent1((ret == pdPASS) ? PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR : PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR_FAILED, (uint32_t)func); + +#endif /* (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) */ + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) + +#undef traceEVENT_GROUP_CREATE +#define traceEVENT_GROUP_CREATE(eg) \ + TRACE_SET_OBJECT_FILTER(EVENTGROUP, eg, CurrentFilterGroup); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_EVENTGROUP_CREATE, (uint32_t)eg); + +#undef traceEVENT_GROUP_DELETE +#define traceEVENT_GROUP_DELETE(eg) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_EVENTGROUP_DELETE, (uint32_t)eg); \ + prvTraceDeleteSymbol(eg); + +#undef traceEVENT_GROUP_CREATE_FAILED +#define traceEVENT_GROUP_CREATE_FAILED() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent0(PSF_EVENT_EVENTGROUP_CREATE_FAILED); + +#undef traceEVENT_GROUP_SYNC_BLOCK +#define traceEVENT_GROUP_SYNC_BLOCK(eg, bitsToSet, bitsToWaitFor) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_SYNC_BLOCK, (uint32_t)eg, bitsToWaitFor); + +#undef traceEVENT_GROUP_SYNC_END +#define traceEVENT_GROUP_SYNC_END(eg, bitsToSet, bitsToWaitFor, wasTimeout) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ + prvTraceStoreEvent2((wasTimeout != pdTRUE) ? PSF_EVENT_EVENTGROUP_SYNC : PSF_EVENT_EVENTGROUP_SYNC_FAILED, (uint32_t)eg, bitsToWaitFor); + +#undef traceEVENT_GROUP_WAIT_BITS_BLOCK +#define traceEVENT_GROUP_WAIT_BITS_BLOCK(eg, bitsToWaitFor) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_WAITBITS_BLOCK, (uint32_t)eg, bitsToWaitFor); + +#undef traceEVENT_GROUP_WAIT_BITS_END +#define traceEVENT_GROUP_WAIT_BITS_END(eg, bitsToWaitFor, wasTimeout) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ + prvTraceStoreEvent2((wasTimeout != pdTRUE) ? PSF_EVENT_EVENTGROUP_WAITBITS : PSF_EVENT_EVENTGROUP_WAITBITS_FAILED, (uint32_t)eg, bitsToWaitFor); + +#undef traceEVENT_GROUP_CLEAR_BITS +#define traceEVENT_GROUP_CLEAR_BITS(eg, bitsToClear) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_CLEARBITS, (uint32_t)eg, bitsToClear); + +#undef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR +#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(eg, bitsToClear) \ + if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_CLEARBITS_FROMISR, (uint32_t)eg, bitsToClear); + +#undef traceEVENT_GROUP_SET_BITS +#define traceEVENT_GROUP_SET_BITS(eg, bitsToSet) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_SETBITS, (uint32_t)eg, bitsToSet); + +#undef traceEVENT_GROUP_SET_BITS_FROM_ISR +#define traceEVENT_GROUP_SET_BITS_FROM_ISR(eg, bitsToSet) \ + if (TRACE_GET_OBJECT_FILTER(EVENTGROUP, eg) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_EVENTGROUP_SETBITS_FROMISR, (uint32_t)eg, bitsToSet); + +#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) */ + +#undef traceTASK_NOTIFY_TAKE +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_TAKE(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \ + if (pxCurrentTCB->ucNotifyState[index] == taskNOTIFICATION_RECEIVED) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE, (uint32_t)pxCurrentTCB, xTicksToWait); \ + else \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);} +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) +#define traceTASK_NOTIFY_TAKE() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \ + if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE, (uint32_t)pxCurrentTCB, xTicksToWait); \ + else \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);} +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY_TAKE() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \ + if (pxCurrentTCB->eNotifyState == eNotified) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE, (uint32_t)pxCurrentTCB, xTicksToWait); \ + else \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);} +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceTASK_NOTIFY_TAKE_BLOCK +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_TAKE_BLOCK(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_BLOCK, (uint32_t)pxCurrentTCB, xTicksToWait); +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY_TAKE_BLOCK() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_TAKE_BLOCK, (uint32_t)pxCurrentTCB, xTicksToWait); +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceTASK_NOTIFY_WAIT +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_WAIT(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \ + if (pxCurrentTCB->ucNotifyState[index] == taskNOTIFICATION_RECEIVED) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT, (uint32_t)pxCurrentTCB, xTicksToWait); \ + else \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);} +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) +#define traceTASK_NOTIFY_WAIT() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \ + if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT, (uint32_t)pxCurrentTCB, xTicksToWait); \ + else \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);} +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY_WAIT() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask){ \ + if (pxCurrentTCB->eNotifyState == eNotified) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT, (uint32_t)pxCurrentTCB, xTicksToWait); \ + else \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_FAILED, (uint32_t)pxCurrentTCB, xTicksToWait);} +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceTASK_NOTIFY_WAIT_BLOCK +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_WAIT_BLOCK(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_BLOCK, (uint32_t)pxCurrentTCB, xTicksToWait); +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY_WAIT_BLOCK() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent2(PSF_EVENT_TASK_NOTIFY_WAIT_BLOCK, (uint32_t)pxCurrentTCB, xTicksToWait); +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceTASK_NOTIFY +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY, (uint32_t)xTaskToNotify); +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY, (uint32_t)xTaskToNotify); +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceTASK_NOTIFY_FROM_ISR +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_FROM_ISR(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY_FROM_ISR, (uint32_t)xTaskToNotify); +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY_FROM_ISR() \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY_FROM_ISR, (uint32_t)xTaskToNotify); +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceTASK_NOTIFY_GIVE_FROM_ISR +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) +#define traceTASK_NOTIFY_GIVE_FROM_ISR(index) \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY_GIVE_FROM_ISR, (uint32_t)xTaskToNotify); +#else /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ +#define traceTASK_NOTIFY_GIVE_FROM_ISR() \ + if (TRACE_GET_OBJECT_FILTER(TASK, xTaskToNotify) & CurrentFilterMask) \ + prvTraceStoreEvent1(PSF_EVENT_TASK_NOTIFY_GIVE_FROM_ISR, (uint32_t)xTaskToNotify); +#endif /* TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0 */ + +#undef traceQUEUE_REGISTRY_ADD +#define traceQUEUE_REGISTRY_ADD(object, name) \ + prvTraceSaveObjectSymbol(object, (const char*)name); \ + prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, name, object); + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) + +#undef traceSTREAM_BUFFER_CREATE +#define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) \ + TRACE_SET_OBJECT_FILTER(STREAMBUFFER, pxStreamBuffer, CurrentFilterGroup); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, pxStreamBuffer) & CurrentFilterMask) \ + prvTraceStoreEvent2(xIsMessageBuffer == 1 ? PSF_EVENT_MESSAGEBUFFER_CREATE : PSF_EVENT_STREAMBUFFER_CREATE, (uint32_t)pxStreamBuffer, xBufferSizeBytes); + +#undef traceSTREAM_BUFFER_CREATE_FAILED +#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreEvent2(xIsMessageBuffer == 1 ? PSF_EVENT_MESSAGEBUFFER_CREATE_FAILED : PSF_EVENT_STREAMBUFFER_CREATE_FAILED, 0 , xBufferSizeBytes); + +#undef traceSTREAM_BUFFER_CREATE_STATIC_FAILED +#define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ) \ + traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) + +#undef traceSTREAM_BUFFER_DELETE +#define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, pxStreamBuffer) & CurrentFilterMask) \ + prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_DELETE : PSF_EVENT_STREAMBUFFER_DELETE, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \ + prvTraceDeleteSymbol(xStreamBuffer); + +#undef traceSTREAM_BUFFER_RESET +#define traceSTREAM_BUFFER_RESET( xStreamBuffer ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ + prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RESET : PSF_EVENT_STREAMBUFFER_RESET, (uint32_t)xStreamBuffer, 0); + +#undef traceSTREAM_BUFFER_SEND +#define traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ + prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND : PSF_EVENT_STREAMBUFFER_SEND, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); + +#undef traceBLOCKING_ON_STREAM_BUFFER_SEND +#define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ + prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_BLOCK : PSF_EVENT_STREAMBUFFER_SEND_BLOCK, (uint32_t)xStreamBuffer); + +#undef traceSTREAM_BUFFER_SEND_FAILED +#define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ + prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FAILED : PSF_EVENT_STREAMBUFFER_SEND_FAILED, (uint32_t)xStreamBuffer); + +#undef traceSTREAM_BUFFER_RECEIVE +#define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ + prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE: PSF_EVENT_STREAMBUFFER_RECEIVE, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); + +#undef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE +#define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ + prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_BLOCK: PSF_EVENT_STREAMBUFFER_RECEIVE_BLOCK, (uint32_t)xStreamBuffer); + +#undef traceSTREAM_BUFFER_RECEIVE_FAILED +#define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ + prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FAILED: PSF_EVENT_STREAMBUFFER_RECEIVE_FAILED, (uint32_t)xStreamBuffer); + +#undef traceSTREAM_BUFFER_SEND_FROM_ISR +#define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ) \ + if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ + { \ + if ( xReturn > ( size_t ) 0 ) \ + { \ + prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR : PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \ + } \ + else \ + { \ + prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR_FAILED : PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR_FAILED, (uint32_t)xStreamBuffer); \ + } \ + } + +#undef traceSTREAM_BUFFER_RECEIVE_FROM_ISR +#define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) \ +if (TRACE_GET_OBJECT_FILTER(STREAMBUFFER, xStreamBuffer) & CurrentFilterMask) \ + { \ + if ( xReceivedLength > ( size_t ) 0 ) \ + { \ + prvTraceStoreEvent2(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR : PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR, (uint32_t)xStreamBuffer, prvBytesInBuffer(xStreamBuffer)); \ + } \ + else \ + { \ + prvTraceStoreEvent1(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR_FAILED : PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR_FAILED, (uint32_t)xStreamBuffer); \ + } \ + } + +#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) */ + +#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#else /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +/* When recorder is disabled */ +#define vTraceSetQueueName(object, name) +#define vTraceSetSemaphoreName(object, name) +#define vTraceSetMutexName(object, name) +#define vTraceSetEventGroupName(object, name) +#define vTraceSetStreamBufferName(object, name) +#define vTraceSetMessageBufferName(object, name) + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_KERNEL_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcPortDefines.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcPortDefines.h index 258bf220a..99a2fbf50 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcPortDefines.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcPortDefines.h @@ -1,137 +1,138 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcPortDefines.h
- *
- * Some common defines for the trace recorder.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_PORTDEFINES_H
-#define TRC_PORTDEFINES_H
-
-#define TRC_FREE_RUNNING_32BIT_INCR 1
-#define TRC_FREE_RUNNING_32BIT_DECR 2
-#define TRC_OS_TIMER_INCR 3
-#define TRC_OS_TIMER_DECR 4
-#define TRC_CUSTOM_TIMER_INCR 5
-#define TRC_CUSTOM_TIMER_DECR 6
-
-/* Start options for vTraceEnable. */
-#define TRC_INIT 0
-#define TRC_START 1
-#define TRC_START_AWAIT_HOST 2
-
-/* Command codes for TzCtrl task */
-#define CMD_SET_ACTIVE 1 /* Start (param1 = 1) or Stop (param1 = 0) */
-
-/* The final command code, used to validate commands. */
-#define CMD_LAST_COMMAND 1
-
-#define TRC_RECORDER_MODE_SNAPSHOT 0
-#define TRC_RECORDER_MODE_STREAMING 1
-
-#define TRC_RECORDER_BUFFER_ALLOCATION_STATIC (0x00)
-#define TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC (0x01)
-#define TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM (0x02)
-
-/* Filter Groups */
-#define FilterGroup0 (uint16_t)0x0001
-#define FilterGroup1 (uint16_t)0x0002
-#define FilterGroup2 (uint16_t)0x0004
-#define FilterGroup3 (uint16_t)0x0008
-#define FilterGroup4 (uint16_t)0x0010
-#define FilterGroup5 (uint16_t)0x0020
-#define FilterGroup6 (uint16_t)0x0040
-#define FilterGroup7 (uint16_t)0x0080
-#define FilterGroup8 (uint16_t)0x0100
-#define FilterGroup9 (uint16_t)0x0200
-#define FilterGroup10 (uint16_t)0x0400
-#define FilterGroup11 (uint16_t)0x0800
-#define FilterGroup12 (uint16_t)0x1000
-#define FilterGroup13 (uint16_t)0x2000
-#define FilterGroup14 (uint16_t)0x4000
-#define FilterGroup15 (uint16_t)0x8000
-
-/******************************************************************************
- * Supported ports
- *
- * TRC_HARDWARE_PORT_HWIndependent
- * A hardware independent fallback option for event timestamping. Provides low
- * resolution timestamps based on the OS tick.
- * This may be used on the Win32 port, but may also be used on embedded hardware
- * platforms. All time durations will be truncated to the OS tick frequency,
- * typically 1 KHz. This means that a task or ISR that executes in less than
- * 1 ms get an execution time of zero.
- *
- * TRC_HARDWARE_PORT_APPLICATION_DEFINED
- * Allows for defining the port macros in other source code files.
- *
- * TRC_HARDWARE_PORT_Win32
- * "Accurate" timestamping based on the Windows performance counter for Win32
- * builds. Note that this gives the host machine time, not the kernel time.
- *
- * Hardware specific ports
- * To get accurate timestamping, a hardware timer is necessary. Below are the
- * available ports. Some of these are "unofficial", meaning that
- * they have not yet been verified by Percepio but have been contributed by
- * external developers. They should work, otherwise let us know by emailing
- * support@percepio.com. Some work on any OS platform, while other are specific
- * to a certain operating system.
- *****************************************************************************/
-
-/****** Port Name ************************************* Code ** Official ** OS Platform *********/
-#define TRC_HARDWARE_PORT_APPLICATION_DEFINED 98 /* - - */
-#define TRC_HARDWARE_PORT_NOT_SET 99 /* - - */
-#define TRC_HARDWARE_PORT_HWIndependent 0 /* Yes Any */
-#define TRC_HARDWARE_PORT_Win32 1 /* Yes FreeRTOS on Win32 */
-#define TRC_HARDWARE_PORT_Atmel_AT91SAM7 2 /* No Any */
-#define TRC_HARDWARE_PORT_Atmel_UC3A0 3 /* No Any */
-#define TRC_HARDWARE_PORT_ARM_Cortex_M 4 /* Yes Any */
-#define TRC_HARDWARE_PORT_Renesas_RX600 6 /* Yes Any */
-#define TRC_HARDWARE_PORT_MICROCHIP_PIC24_PIC32 7 /* Yes Any */
-#define TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_TMS570_RM48 8 /* Yes Any */
-#define TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_MSP430 9 /* No Any */
-#define TRC_HARDWARE_PORT_XILINX_PPC405 11 /* No FreeRTOS */
-#define TRC_HARDWARE_PORT_XILINX_PPC440 12 /* No FreeRTOS */
-#define TRC_HARDWARE_PORT_XILINX_MICROBLAZE 13 /* No Any */
-#define TRC_HARDWARE_PORT_NXP_LPC210X 14 /* No Any */
-#define TRC_HARDWARE_PORT_ARM_CORTEX_A9 15 /* Yes Any */
-#define TRC_HARDWARE_PORT_POWERPC_Z4 16 /* No FreeRTOS */
-#define TRC_HARDWARE_PORT_Altera_NiosII 17 /* No Any */
-#endif /*TRC_PORTDEFINES_H*/
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcPortDefines.h + * + * Some common defines for the trace recorder. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_PORTDEFINES_H +#define TRC_PORTDEFINES_H + +#define TRC_FREE_RUNNING_32BIT_INCR 1 +#define TRC_FREE_RUNNING_32BIT_DECR 2 +#define TRC_OS_TIMER_INCR 3 +#define TRC_OS_TIMER_DECR 4 +#define TRC_CUSTOM_TIMER_INCR 5 +#define TRC_CUSTOM_TIMER_DECR 6 + +/* Start options for vTraceEnable. */ +#define TRC_INIT 0 +#define TRC_START 1 +#define TRC_START_AWAIT_HOST 2 + +/* Command codes for TzCtrl task */ +#define CMD_SET_ACTIVE 1 /* Start (param1 = 1) or Stop (param1 = 0) */ + +/* The final command code, used to validate commands. */ +#define CMD_LAST_COMMAND 1 + +#define TRC_RECORDER_MODE_SNAPSHOT 0 +#define TRC_RECORDER_MODE_STREAMING 1 + +#define TRC_RECORDER_BUFFER_ALLOCATION_STATIC (0x00) +#define TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC (0x01) +#define TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM (0x02) + +/* Filter Groups */ +#define FilterGroup0 (uint16_t)0x0001 +#define FilterGroup1 (uint16_t)0x0002 +#define FilterGroup2 (uint16_t)0x0004 +#define FilterGroup3 (uint16_t)0x0008 +#define FilterGroup4 (uint16_t)0x0010 +#define FilterGroup5 (uint16_t)0x0020 +#define FilterGroup6 (uint16_t)0x0040 +#define FilterGroup7 (uint16_t)0x0080 +#define FilterGroup8 (uint16_t)0x0100 +#define FilterGroup9 (uint16_t)0x0200 +#define FilterGroup10 (uint16_t)0x0400 +#define FilterGroup11 (uint16_t)0x0800 +#define FilterGroup12 (uint16_t)0x1000 +#define FilterGroup13 (uint16_t)0x2000 +#define FilterGroup14 (uint16_t)0x4000 +#define FilterGroup15 (uint16_t)0x8000 + +/****************************************************************************** + * Supported ports + * + * TRC_HARDWARE_PORT_HWIndependent + * A hardware independent fallback option for event timestamping. Provides low + * resolution timestamps based on the OS tick. + * This may be used on the Win32 port, but may also be used on embedded hardware + * platforms. All time durations will be truncated to the OS tick frequency, + * typically 1 KHz. This means that a task or ISR that executes in less than + * 1 ms get an execution time of zero. + * + * TRC_HARDWARE_PORT_APPLICATION_DEFINED + * Allows for defining the port macros in other source code files. + * + * TRC_HARDWARE_PORT_Win32 + * "Accurate" timestamping based on the Windows performance counter for Win32 + * builds. Note that this gives the host machine time, not the kernel time. + * + * Hardware specific ports + * To get accurate timestamping, a hardware timer is necessary. Below are the + * available ports. Some of these are "unofficial", meaning that + * they have not yet been verified by Percepio but have been contributed by + * external developers. They should work, otherwise let us know by emailing + * support@percepio.com. Some work on any OS platform, while other are specific + * to a certain operating system. + *****************************************************************************/ + +/****** Port Name ************************************* Code ** Official ** OS Platform *********/ +#define TRC_HARDWARE_PORT_APPLICATION_DEFINED 98 /* - - */ +#define TRC_HARDWARE_PORT_NOT_SET 99 /* - - */ +#define TRC_HARDWARE_PORT_HWIndependent 0 /* Yes Any */ +#define TRC_HARDWARE_PORT_Win32 1 /* Yes FreeRTOS on Win32 */ +#define TRC_HARDWARE_PORT_Atmel_AT91SAM7 2 /* No Any */ +#define TRC_HARDWARE_PORT_Atmel_UC3A0 3 /* No Any */ +#define TRC_HARDWARE_PORT_ARM_Cortex_M 4 /* Yes Any */ +#define TRC_HARDWARE_PORT_Renesas_RX600 6 /* Yes Any */ +#define TRC_HARDWARE_PORT_MICROCHIP_PIC24_PIC32 7 /* Yes Any */ +#define TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_TMS570_RM48 8 /* Yes Any */ +#define TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_MSP430 9 /* No Any */ +#define TRC_HARDWARE_PORT_XILINX_PPC405 11 /* No FreeRTOS */ +#define TRC_HARDWARE_PORT_XILINX_PPC440 12 /* No FreeRTOS */ +#define TRC_HARDWARE_PORT_XILINX_MICROBLAZE 13 /* No Any */ +#define TRC_HARDWARE_PORT_XILINX_ZyncUltraScaleR5 14 /* No FreeRTOS */ +#define TRC_HARDWARE_PORT_NXP_LPC210X 15 /* No Any */ +#define TRC_HARDWARE_PORT_ARM_CORTEX_A9 16 /* Yes Any */ +#define TRC_HARDWARE_PORT_POWERPC_Z4 17 /* No FreeRTOS */ +#define TRC_HARDWARE_PORT_Altera_NiosII 18 /* Yes Any (Tested with FreeRTOS) */ +#endif /*TRC_PORTDEFINES_H*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcRecorder.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcRecorder.h index edcd5f0ae..3d4f3d635 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcRecorder.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcRecorder.h @@ -1,1789 +1,1905 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcRecorder.h
- *
- * The public API of the trace recorder.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_RECORDER_H
-#define TRC_RECORDER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-#include <stddef.h>
-
-#include "trcConfig.h"
-#include "trcPortDefines.h"
-
-
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
-typedef uint16_t traceString;
-typedef uint8_t traceUBChannel;
-typedef uint8_t traceObjectClass;
-
-#if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1)
-typedef uint16_t traceHandle;
-#else
-typedef uint8_t traceHandle;
-#endif
-
-#include "trcHardwarePort.h"
-#include "trcKernelPort.h"
-
-// Not available in snapshot mode
-#define vTraceConsoleChannelPrintF(fmt, ...)
-
-#endif
-
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-
-typedef const char* traceString;
-typedef const void* traceHandle;
-
-#include "trcHardwarePort.h"
-#include "trcStreamingPort.h"
-#include "trcKernelPort.h"
-
-#endif
-
-#if (TRC_USE_TRACEALYZER_RECORDER == 1)
-
-/* The user event channel for recorder warnings, must be defined in trcKernelPort.c */
-extern traceString trcWarningChannel;
-
-#define TRACE_GET_LOW16(value) ((uint16_t)((value) & 0x0000FFFF))
-#define TRACE_GET_HIGH16(value) ((uint16_t)(((value) >> 16) & 0x0000FFFF))
-#define TRACE_SET_LOW16(current, value) (((current) & 0xFFFF0000) | (value))
-#define TRACE_SET_HIGH16(current, value) (((current) & 0x0000FFFF) | (((uint32_t)(value)) << 16))
-
-/******************************************************************************/
-/*** Common API - both Snapshot and Streaming mode ****************************/
-/******************************************************************************/
-
-/******************************************************************************
-* vTraceEnable(int startOption);
-*
-* Initializes and optionally starts the trace, depending on the start option.
-* To use the trace recorder, the startup must call vTraceEnable before any RTOS
-* calls are made (including "create" calls). Three start options are provided:
-*
-* TRC_START: Starts the tracing directly. In snapshot mode this allows for
-* starting the trace at any point in your code, assuming vTraceEnable(TRC_INIT)
-* has been called in the startup.
-* Can also be used for streaming without Tracealyzer control, e.g. to a local
-* flash file system (assuming such a "stream port", see trcStreamingPort.h).
-*
-* TRC_START_AWAIT_HOST: For streaming mode only. Initializes the trace recorder
-* if necessary and waits for a Start command from Tracealyzer ("Start Recording"
-* button). This call is intentionally blocking! By calling vTraceEnable with
-* this option from the startup code, you start tracing at this point and capture
-* the early events.
-*
-* TRC_INIT: Initializes the trace recorder, but does not start the tracing.
-* In snapshot mode, this must be followed by a vTraceEnable(TRC_START) sometime
-* later.
-*
-* Usage examples:
-*
-* Snapshot trace, from startup:
-* <board init>
-* vTraceEnable(TRC_START);
-* <RTOS init>
-*
-* Snapshot trace, from a later point:
-* <board init>
-* vTraceEnable(TRC_INIT);
-* <RTOS init>
-* ...
-* vTraceEnable(TRC_START); // e.g., in task context, at some relevant event
-*
-* Streaming trace, from startup:
-* <board init>
-* vTraceEnable(TRC_START_AWAIT_HOST); // Blocks!
-* <RTOS init>
-*
-* Streaming trace, from a later point:
-* <board startup>
-* vTraceEnable(TRC_INIT);
-* <RTOS startup>
-*
-******************************************************************************/
-void vTraceEnable(int startOption);
-
-/******************************************************************************
- * vTracePrintF
- *
- * Generates "User Events", with formatted text and data, similar to a "printf".
- * User Events can be used for very efficient logging from your application code.
- * It is very fast since the actual string formatting is done on the host side,
- * when the trace is displayed. The execution time is just some microseconds on
- * a 32-bit MCU.
- *
- * User Events are shown as yellow labels in the main trace view of $PNAME.
- *
- * An advantage of User Events is that data can be plotted in the "User Event
- * Signal Plot" view, visualizing any data you log as User Events, discrete
- * states or control system signals (e.g. system inputs or outputs).
- *
- * You may group User Events into User Event Channels. The yellow User Event
- * labels show the logged string, preceded by the channel name within brackets.
- *
- * Example:
- *
- * "[MyChannel] Hello World!"
- *
- * The User Event Channels are shown in the View Filter, which makes it easy to
- * select what User Events you wish to display. User Event Channels are created
- * using xTraceRegisterString().
- *
- * Example:
- *
- * traceString adc_uechannel = xTraceRegisterString("ADC User Events");
- * ...
- * vTracePrintF(adc_uechannel,
- * "ADC channel %d: %d volts",
- * ch, adc_reading);
- *
- * The following format specifiers are supported in both modes:
- * %d - signed integer.
- * %u - unsigned integer.
- * %X - hexadecimal, uppercase.
- * %x - hexadecimal, lowercase.
- * %s - string (see comment below)
- *
- * For integer formats (%d, %u, %x, %X) you may also use width and padding.
- * If using -42 as data argument, two examples are:
- * "%05d" -> "-0042"
- * "%5d" -> " -42".
- *
- * String arguments are supported in both snapshot and streaming, but in streaming
- * mode you need to use xTraceRegisterString and use the returned traceString as
- * the argument. In snapshot you simply provide a char* as argument.
- *
- * Snapshot: vTracePrintF(myChn, "my string: %s", str);
- * Streaming: vTracePrintF(myChn, "my string: %s", xTraceRegisterString(str));
- *
- * In snapshot mode you can specify 8-bit or 16-bit arguments to reduce RAM usage:
- * %hd -> 16 bit (h) signed integer (d).
- * %bu -> 8 bit (b) unsigned integer (u).
- *
- * However, in streaming mode all data arguments are assumed to be 32 bit wide.
- * Width specifiers (e.g. %hd) are accepted but ignored (%hd treated like %d).
- *
- * The maximum event size also differs between the modes. In streaming this is
- * limited by a maximum payload size of 52 bytes, including format string and
- * data arguments. So if using one data argument, the format string is limited
- * to 48 byte, etc. If this is exceeded, the format string is truncated and you
- * get a warning in Tracealyzer.
- *
- * In snapshot mode you are limited to maximum 15 arguments, that must not exceed
- * 32 bytes in total (not counting the format string). If exceeded, the recorder
- * logs an internal error (displayed when opening the trace) and stops recording.
- ******************************************************************************/
-#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
-void vTracePrintF(traceString chn, const char* fmt, ...);
-#else
-#define vTracePrintF(chn, ...) (void)chn
-#endif
-
- /******************************************************************************
-* vTracePrint
-*
-* A faster version of vTracePrintF, that only allows for logging a string.
-*
-* Example:
-*
-* traceString chn = xTraceRegisterString("MyChannel");
-* ...
-* vTracePrint(chn, "Hello World!");
-******************************************************************************/
-#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
-void vTracePrint(traceString chn, const char* str);
-#else
-#define vTracePrint(chn, ...) (void)chn
-#endif
-
-
-/*******************************************************************************
-* vTraceConsoleChannelPrintF
-*
-* Wrapper for vTracePrint, using the default channel. Can be used as a drop-in
-* replacement for printf and similar functions, e.g. in a debug logging macro.
-*
-* Example:
-*
-* // Old: #define LogString debug_console_printf
-*
-* // New, log to Tracealyzer instead:
-* #define LogString vTraceConsoleChannelPrintF
-* ...
-* LogString("My value is: %d", myValue);
-******************************************************************************/
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-void vTraceConsoleChannelPrintF(const char* fmt, ...);
-#endif
-
-/*******************************************************************************
-* xTraceRegisterString
-*
-* Register strings in the recorder, e.g. for names of user event channels.
-*
-* Example:
-* myEventHandle = xTraceRegisterString("MyUserEvent");
-* ...
-* vTracePrintF(myEventHandle, "My value is: %d", myValue);
-******************************************************************************/
-#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
-traceString xTraceRegisterString(const char* name);
-#else
-#define xTraceRegisterString(x) (x)
-#endif
-
-/*******************************************************************************
- * vTraceSet...Name(void* object, const char* name)
- *
- * Parameter object: pointer to the kernel object that shall be named
- * Parameter name: the name to set
- *
- * Kernel-specific functions for setting names of kernel objects, for display in
- * Tracealyzer.
- ******************************************************************************/
-/* See trcKernelPort.h for details (kernel-specific) */
-
-/*******************************************************************************
- * xTraceSetISRProperties
- *
- * Stores a name and priority level for an Interrupt Service Routine, to allow
- * for better visualization. Returns a traceHandle used by vTraceStoreISRBegin.
- *
- * Example:
- * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt
- * ...
- * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1);
- * ...
- * void ISR_handler()
- * {
- * vTraceStoreISRBegin(Timer1Handle);
- * ...
- * vTraceStoreISREnd(0);
- * }
- ******************************************************************************/
-traceHandle xTraceSetISRProperties(const char* name, uint8_t priority);
-
-/*******************************************************************************
- * vTraceStoreISRBegin
- *
- * Registers the beginning of an Interrupt Service Routine, using a traceHandle
- * provided by xTraceSetISRProperties.
- *
- * Example:
- * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt
- * ...
- * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1);
- * ...
- * void ISR_handler()
- * {
- * vTraceStoreISRBegin(Timer1Handle);
- * ...
- * vTraceStoreISREnd(0);
- * }
- ******************************************************************************/
-void vTraceStoreISRBegin(traceHandle handle);
-
-/*******************************************************************************
- * vTraceStoreISREnd
- *
- * Registers the end of an Interrupt Service Routine.
- *
- * The parameter pendingISR indicates if the interrupt has requested a
- * task-switch (= 1), e.g., by signaling a semaphore. Otherwise (= 0) the
- * interrupt is assumed to return to the previous context.
- *
- * Example:
- * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
- * traceHandle traceHandleIsrTimer1 = 0; // The ID set by the recorder
- * ...
- * traceHandleIsrTimer1 = xTraceSetISRProperties("ISRTimer1", PRIO_OF_ISR_TIMER1);
- * ...
- * void ISR_handler()
- * {
- * vTraceStoreISRBegin(traceHandleIsrTimer1);
- * ...
- * vTraceStoreISREnd(0);
- * }
- ******************************************************************************/
-void vTraceStoreISREnd(int isTaskSwitchRequired);
-
-/*******************************************************************************
- * vTraceInstanceFinishNow
- *
- * Creates an event that ends the current task instance at this very instant.
- * This makes the viewer to splits the current fragment at this point and begin
- * a new actor instance, even if no task-switch has occurred.
- *****************************************************************************/
-void vTraceInstanceFinishedNow(void);
-
-/*******************************************************************************
- * vTraceInstanceFinishedNext
- *
- * Marks the current "task instance" as finished on the next kernel call.
- *
- * If that kernel call is blocking, the instance ends after the blocking event
- * and the corresponding return event is then the start of the next instance.
- * If the kernel call is not blocking, the viewer instead splits the current
- * fragment right before the kernel call, which makes this call the first event
- * of the next instance.
- *****************************************************************************/
-void vTraceInstanceFinishedNext(void);
-
-/*******************************************************************************
- * xTraceGetLastError
- *
- * Returns the last error or warning as a string, or NULL if none.
- *****************************************************************************/
-const char* xTraceGetLastError(void);
-
-/*******************************************************************************
- * vTraceClearError
- *
- * Clears any errors.
- *****************************************************************************/
-void vTraceClearError(void);
-
-/*******************************************************************************
-* vTraceStop
-*
-* Stops the recording. Intended for snapshot mode or if streaming without
-* Tracealyzer control (e.g., to a device file system).
-******************************************************************************/
-void vTraceStop(void);
-
-/******************************************************************************
-* vTraceSetFrequency
-*
-* Registers the clock rate of the time source for the event timestamping.
-* This is normally not required, but if the default value (TRC_HWTC_FREQ_HZ)
-* should be incorrect for your setup, you can override it using this function.
-*
-* Must be called prior to vTraceEnable, and the time source is assumed to
-* have a fixed clock frequency after the startup.
-*
-* Note that, in snapshot mode, the value is divided by the TRC_HWTC_DIVISOR.
-* This is a software "prescaler" that is also applied on the timestamps.
-*****************************************************************************/
-void vTraceSetFrequency(uint32_t frequency);
-
-/*******************************************************************************
-* vTraceSetRecorderDataBuffer
-*
-* The trcConfig.h setting TRC_CFG_RECORDER_BUFFER_ALLOCATION allows for selecting
-* custom allocation (TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM), which allows you to
-* control where the recorder trace buffer is allocated.
-*
-* When custom allocation is selected, use TRC_ALLOC_CUSTOM_BUFFER to make the
-* allocation (in global context) and then call vTraceSetRecorderDataBuffer to
-* register the allocated buffer. This supports both snapshot and streaming,
-* and has no effect if using other allocation modes than CUSTOM.
-*
-* NOTE: vTraceSetRecorderDataBuffer must be called before vTraceEnable.
-******************************************************************************/
-#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM)
-void vTraceSetRecorderDataBuffer(void* pRecorderData);
-#else
-#define vTraceSetRecorderDataBuffer(pRecorderData)
-#endif
-
-
-/*******************************************************************************
-* TRC_ALLOC_CUSTOM_BUFFER
-*
-* If using custom allocation of the trace buffer (i.e., your trcConfig.h has the
-* setting TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM), this macro allows you to declare
-* the trace buffer in a portable way that works both in snapshot and streaming.
-*
-* This macro has no effect if using another allocation mode, so you can easily
-* switch between different recording modes and configurations, using the same
-* initialization code.
-*
-* This translates to a single static allocation, on which you can apply linker
-* directives to place it in a particular memory region.
-*
-* - Snapshot mode: "RecorderDataType <name>"
-*
-* - Streaming mode: "char <name> [<size>]",
-* where <size> is defined in trcStreamingConfig.h.
-*
-* Example:
-*
-* // GCC example: place myTraceBuffer in section .tz, defined in the .ld file.
-* TRC_ALLOC_CUSTOM_BUFFER(myTraceBuffer) __attribute__((section(".tz")));
-*
-* int main(void)
-* {
-* ...
-* vTraceSetRecorderDataBuffer(&myTraceBuffer); // Note the "&"
-* ...
-* vTraceEnable(TRC_INIT); // Initialize the data structure
-******************************************************************************/
-#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM)
- #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
- #define TRC_ALLOC_CUSTOM_BUFFER(bufname) RecorderDataType bufname;
- #elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
- #ifdef TRC_CFG_RTT_BUFFER_SIZE_UP /* J-Link RTT */
- #define TRC_ALLOC_CUSTOM_BUFFER(bufname) char bufname [TRC_CFG_RTT_BUFFER_SIZE_UP]; /* Not static in this case, since declared in user code */
- #else
- #define TRC_ALLOC_CUSTOM_BUFFER(bufname) char bufname [(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];
- #endif
- #endif
-#else
- #define TRC_ALLOC_CUSTOM_BUFFER(bufname)
-#endif
-
-/******************************************************************************
-* xTraceIsRecordingEnabled
-*
-* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0.
-******************************************************************************/
-int xTraceIsRecordingEnabled(void);
-
-/*******************************************************************************
-* vTraceSetFilterGroup
-*
-* Sets the "filter group" to assign when creating RTOS objects, such as tasks,
-* queues, semaphores and mutexes. This together with vTraceSetFilterMask
-* allows you to control what events that are recorded, based on the
-* objects they refer to.
-*
-* There are 16 filter groups named FilterGroup0 .. FilterGroup15.
-*
-* Note: We don't recommend filtering out the Idle task, so make sure to call
-* vTraceSetFilterGroup just before initializing the RTOS, in order to assign
-* such "default" objects to the right Filter Group (typically group 0).
-*
-* Example:
-*
-* // Assign tasks T1 to FilterGroup0 (default)
-* <Create Task T1>
-*
-* // Assign Q1 and Q2 to FilterGroup1
-* vTraceSetFilterGroup(FilterGroup1);
-* <Create Queue Q1>
-* <Create Queue Q2>
-*
-* // Assigns Q3 to FilterGroup2
-* vTraceSetFilterGroup(FilterGroup2);
-* <Create Queue Q3>
-*
-* // Only include FilterGroup0 and FilterGroup2, exclude FilterGroup1 (Q1 and Q2) from the trace
-* vTraceSetFilterMask( FilterGroup0 | FilterGroup2 );
-*
-* // Assign the default RTOS objects (e.g. Idle task) to FilterGroup0
-* vTraceSetFilterGroup(FilterGroup0);
-* <Start the RTOS scheduler>
-*
-* Note that you may define your own names for the filter groups using
-* preprocessor definitions, to make the code easier to understand.
-*
-* Example:
-*
-* #define BASE FilterGroup0
-* #define USB_EVENTS FilterGroup1
-* #define CAN_EVENTS FilterGroup2
-*
-* Note that filtering per event type (regardless of object) is also available
-* in trcConfig.h.
-******************************************************************************/
-void vTraceSetFilterGroup(uint16_t filterGroup);
-
-/******************************************************************************
-* vTraceSetFilterMask
-*
-* Sets the "filter mask" that is used to filter the events by object. This can
-* be used to reduce the trace data rate, i.e., if your streaming interface is
-* a bottleneck or if you want longer snapshot traces without increasing the
-* buffer size.
-*
-* Note: There are two kinds of filters in the recorder. The other filter type
-* excludes all events of certain kinds (e.g., OS ticks). See trcConfig.h.
-*
-* The filtering is based on bitwise AND with the Filter Group ID, assigned
-* to RTOS objects such as tasks, queues, semaphores and mutexes.
-* This together with vTraceSetFilterGroup allows you to control what
-* events that are recorded, based on the objects they refer to.
-*
-* See example for vTraceSetFilterGroup.
-******************************************************************************/
-void vTraceSetFilterMask(uint16_t filterMask);
-
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
-
-/******************************************************************************/
-/*** Extended API for Snapshot mode *******************************************/
-/******************************************************************************/
-
-/******************************************************************************
-* 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.
-*
-* Snapshot mode only!
-******************************************************************************/
-typedef void(*TRACE_STOP_HOOK)(void);
-
-/*******************************************************************************
-* vTraceStopHookPtr
-*
-* Points to a call back function that is called from vTraceStop().
-*
-* Snapshot mode only!
-******************************************************************************/
-extern TRACE_STOP_HOOK vTraceStopHookPtr;
-
-/*******************************************************************************
-* vTraceSetStopHook
-*
-* Sets a function to be called when the recorder is stopped.
-*
-* Snapshot mode only!
-******************************************************************************/
-void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction);
-
-/*******************************************************************************
-* uiTraceStart
-*
-* [DEPRECATED] Use vTraceEnable instead.
-*
-* Starts the recorder. The recorder will not be started if an error has been
-* indicated using prvTraceError, e.g. if any of the Nx constants in
-* trcSnapshotConfig.h has a too small value (TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc).
-*
-* Returns 1 if the recorder was started successfully.
-* Returns 0 if the recorder start was prevented due to a previous internal
-* error. In that case, check xTraceGetLastError to get the error message.
-* Any error message is also presented when opening a trace file.
-*
-* Snapshot mode only!
-******************************************************************************/
-uint32_t uiTraceStart(void);
-
-/*******************************************************************************
-* vTraceStart
-*
-* [DEPRECATED] Use vTraceEnable instead.
-*
-* Starts the recorder. The recorder will not be started if an error has been
-* indicated using prvTraceError, e.g. if any of the Nx constants in
-* trcSnapshotConfig.h has a too small value (TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc).
-*
-* Snapshot mode only!
-******************************************************************************/
-void vTraceStart(void);
-
-/*******************************************************************************
-* vTraceClear
-*
-* Resets the recorder. Only necessary if a restart is desired - this is not
-* needed in the startup initialization.
-*
-* Snapshot mode only!
-******************************************************************************/
-void vTraceClear(void);
-
-
-/*****************************************************************************/
-/*** INTERNAL SNAPSHOT FUNCTIONS *********************************************/
-/*****************************************************************************/
-
-#define TRC_UNUSED
-
-#ifndef TRC_CFG_INCLUDE_OBJECT_DELETE
-#define TRC_CFG_INCLUDE_OBJECT_DELETE 0
-#endif
-
-#ifndef TRC_CFG_INCLUDE_READY_EVENTS
-#define TRC_CFG_INCLUDE_READY_EVENTS 1
-#endif
-
-#ifndef TRC_CFG_INCLUDE_OSTICK_EVENTS
-#define TRC_CFG_INCLUDE_OSTICK_EVENTS 0
-#endif
-
-/* This macro will create a task in the object table */
-#undef trcKERNEL_HOOKS_TASK_CREATE
-#define trcKERNEL_HOOKS_TASK_CREATE(SERVICE, CLASS, pxTCB) \
- TRACE_SET_OBJECT_NUMBER(TASK, pxTCB); \
- TRACE_SET_OBJECT_FILTER(TASK, pxTCB, CurrentFilterGroup); \
- prvTraceSetObjectName(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_NAME(pxTCB)); \
- prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
- prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
-
-/* This macro will remove the task and store it in the event buffer */
-#undef trcKERNEL_HOOKS_TASK_DELETE
-#define trcKERNEL_HOOKS_TASK_DELETE(SERVICE, SERVICE_NAME, SERVICE_PROP, pxTCB) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
- prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \
- prvTraceStoreObjectNameOnCloseEvent(SERVICE_NAME, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \
- prvTraceStoreObjectPropertiesOnCloseEvent(SERVICE_PROP, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \
- prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \
- prvTraceSetObjectState(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TASK_STATE_INSTANCE_NOT_ACTIVE); \
- prvTraceFreeObjectHandle(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
-
-
-/* This macro will setup a task in the object table */
-#undef trcKERNEL_HOOKS_OBJECT_CREATE
-#define trcKERNEL_HOOKS_OBJECT_CREATE(SERVICE, CLASS, pxObject)\
- TRACE_SET_OBJECT_NUMBER(CLASS, pxObject);\
- TRACE_SET_OBJECT_FILTER(CLASS, pxObject, CurrentFilterGroup); \
- prvMarkObjectAsUsed(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));\
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
- prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \
- prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), 0);
-
-/* This macro will remove the object and store it in the event buffer */
-#undef trcKERNEL_HOOKS_OBJECT_DELETE
-#define trcKERNEL_HOOKS_OBJECT_DELETE(SERVICE, SERVICE_NAME, SERVICE_PROP, CLASS, pxObject) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
- prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \
- prvTraceStoreObjectNameOnCloseEvent(SERVICE_NAME, TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \
- prvTraceStoreObjectPropertiesOnCloseEvent(SERVICE_PROP, TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \
- prvTraceFreeObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
-
-/* 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, CLASS, pxObject) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
- prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
-
-/* This macro will create a call to a kernel service with a certain result, with a null object as parameter */
-#undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT
-#define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT(SERVICE, TRACECLASS) \
- if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreKernelCall(SERVICE, TRACECLASS, 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_WITH_PARAM
-#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(SERVICE, CLASS, pxObject, param) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
- prvTraceStoreKernelCallWithParam(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint32_t)param);
-
-/* This macro will create a call to a kernel service with a certain result, with a null object and other value as parameter */
-#undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM
-#define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM(SERVICE, TRACECLASS, param) \
- if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreKernelCallWithParam(SERVICE, TRACECLASS, 0, param);
-
-/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
-#undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY
-#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(SERVICE, param) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, (uint32_t)param);
-
-/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
-#undef trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR
-#define trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(SERVICE, CLASS, pxObject) \
- if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
- prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));
-
-/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
-#undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR
-#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(SERVICE, CLASS, pxObject, param) \
- if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \
- prvTraceStoreKernelCallWithParam(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint32_t)param);
-
-/* This macro will create a call to a kernel service with a certain result, with an object as parameter */
-#undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR
-#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR(SERVICE, param) \
- prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, (uint32_t)param);
-
-/* This macro will set the state for an object */
-#undef trcKERNEL_HOOKS_SET_OBJECT_STATE
-#define trcKERNEL_HOOKS_SET_OBJECT_STATE(CLASS, pxObject, STATE) \
- prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint8_t)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() \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- prvTraceSetTaskInstanceFinished(TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()));
-
-#if (TRC_CFG_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) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
- prvTraceStoreTaskReady(TRACE_GET_TASK_NUMBER(pxTCB));
-#else /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/
-#undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE
-#define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB)
-#endif /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/
-
-/* This macro will update the internal tick counter and call prvTracePortGetTimeStamp(0) to update the internal counters */
-#undef trcKERNEL_HOOKS_INCREMENT_TICK
-#define trcKERNEL_HOOKS_INCREMENT_TICK() \
- { \
- extern uint32_t uiTraceTickCount; \
- uiTraceTickCount++; \
- prvTracePortGetTimeStamp(0); \
- }
-
-#if (TRC_CFG_INCLUDE_OSTICK_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) \
- prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue);
-#else /*(TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)*/
-#undef trcKERNEL_HOOKS_NEW_TIME
-#define trcKERNEL_HOOKS_NEW_TIME(SERVICE, xValue)
-#endif /*(TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)*/
-
-/* This macro will create a task switch event to the currently executing task */
-#undef trcKERNEL_HOOKS_TASK_SWITCH
-#define trcKERNEL_HOOKS_TASK_SWITCH( pxTCB ) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
- prvTraceStoreTaskswitch(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) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
- prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \
- prvTraceSetTaskInstanceFinished((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) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
- { \
- prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue); \
- prvTraceSetTaskInstanceFinished((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) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
- { \
- prvTraceStoreKernelCallWithParam(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), prvTraceGetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)));\
- prvTraceSetPriorityProperty(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) \
- if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
- prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
-
-#undef trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR
-#define trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR(SERVICE, pxTCB) \
- if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \
- prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB));
-
-#if !defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1
- void prvTraceSetReadyEventsEnabled(int status);
- void prvTraceStoreTaskReady(traceHandle handle);
-#else
- #define prvTraceSetReadyEventsEnabled(status)
-#endif
-
-void prvTraceStoreLowPower(uint32_t flag);
-
-void prvTraceStoreTaskswitch(traceHandle task_handle);
-
-
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-
-void prvTraceStoreKernelCall(uint32_t eventcode, traceObjectClass objectClass, uint32_t byteParam);
-
-void prvTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param);
-
-void prvTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass,
- uint32_t objectNumber, uint32_t param);
-#else
-
-#define prvTraceStoreKernelCall(eventcode, objectClass, byteParam) {}
-#define prvTraceStoreKernelCallWithNumericParamOnly(evtcode, param) {}
-#define prvTraceStoreKernelCallWithParam(evtcode, objectClass, objectNumber, param) {}
-
-#endif
-
-void prvTraceSetTaskInstanceFinished(traceHandle handle);
-
-void prvTraceSetPriorityProperty(uint8_t objectclass, traceHandle id, uint8_t value);
-
-uint8_t prvTraceGetPriorityProperty(uint8_t objectclass, traceHandle id);
-
-void prvTraceSetObjectState(uint8_t objectclass, traceHandle id, uint8_t value);
-
-void prvMarkObjectAsUsed(traceObjectClass objectclass, traceHandle handle);
-
-void prvTraceStoreObjectNameOnCloseEvent(uint8_t evtcode, traceHandle handle,
- traceObjectClass objectclass);
-
-void prvTraceStoreObjectPropertiesOnCloseEvent(uint8_t evtcode, traceHandle handle,
- traceObjectClass objectclass);
-
-/* Internal constants for task state */
-#define TASK_STATE_INSTANCE_NOT_ACTIVE 0
-#define TASK_STATE_INSTANCE_ACTIVE 1
-
-
-#if (TRC_CFG_INCLUDE_ISR_TRACING == 0)
-
-#undef vTraceSetISRProperties
-#define vTraceSetISRProperties(handle, name, priority)
-
-#undef vTraceStoreISRBegin
-#define vTraceStoreISRBegin(x) (void)x
-
-#undef vTraceStoreISREnd
-#define vTraceStoreISREnd(x) (void)x
-
-#undef xTraceSetISRProperties
-#define xTraceSetISRProperties(name, priority) 0
-
-#endif /*(TRC_CFG_INCLUDE_ISR_TRACING == 0)*/
-
-/*******************************************************************************
- * xTraceGetTraceBuffer
- *
- * Returns a pointer to the recorder data structure. Use this together with
- * uiTraceGetTraceBufferSize if you wish to implement an own store/upload
- * solution, e.g., in case a debugger connection is not available for uploading
- * the data.
- ******************************************************************************/
-void* xTraceGetTraceBuffer(void);
-
-/*******************************************************************************
- * uiTraceGetTraceBufferSize
- *
- * Gets the size of the recorder data structure. For use together with
- * vTraceGetTraceBuffer if you wish to implement an own store/upload solution,
- * e.g., in case a debugger connection is not available for uploading the data.
- ******************************************************************************/
-uint32_t uiTraceGetTraceBufferSize(void);
-
-#if (TRC_CFG_SCHEDULING_ONLY == 1)
-#undef TRC_CFG_INCLUDE_USER_EVENTS
-#define TRC_CFG_INCLUDE_USER_EVENTS 0
-#endif /*(TRC_CFG_SCHEDULING_ONLY == 1)*/
-
-#if ((TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_SCHEDULING_ONLY == 0))
-
-#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)
-traceUBChannel xTraceRegisterUBChannel(traceString channel, traceString formatStr);
-void vTraceUBData(traceUBChannel channel, ...);
-void vTraceUBEvent(traceUBChannel channel);
-#endif /*(TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)*/
-
-#else /*((TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_SCHEDULING_ONLY == 0))*/
-
-#undef vTracePrint
-#define vTracePrint(chn, ...) (void)chn
-#undef vTracePrintF
-#define vTracePrintF(chn, ...) (void)chn
-#undef xTraceRegisterString
-#define xTraceRegisterString(x) 0; (void)x;
-#undef xTraceRegisterChannelFormat
-#define xTraceRegisterChannelFormat(eventLabel, formatStr) 0
-#undef vTraceUBData
-#define vTraceUBData(label, ...) {}
-#undef vTraceChannelPrint
-#define vTraceChannelPrint(label) {}
-
-#endif /*(TRC_CFG_INCLUDE_USER_EVENTS == 1)*/
-
-#define NEventCodes 0x100
-
-/* Our local critical sections for the recorder */
-#define trcCRITICAL_SECTION_BEGIN() {TRACE_ENTER_CRITICAL_SECTION(); recorder_busy++;}
-#define trcCRITICAL_SECTION_END() {recorder_busy--; TRACE_EXIT_CRITICAL_SECTION();}
-
-#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M)
- #define trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY TRACE_ALLOC_CRITICAL_SECTION
- #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_BEGIN
- #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_END
-#else
- #define trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY() {}
- #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY() recorder_busy++;
- #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--;
-#endif
-
-/******************************************************************************
- * 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 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 */
- uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ];
-
- /* The lowest index of this class (constant) */
- uint16_t lowestIndexOfClass[ TRACE_NCLASSES ];
-
- /* The highest index of this class (constant) */
- uint16_t highestIndexOfClass[ TRACE_NCLASSES ];
-
- /* The highest use count for this class (for statistics) */
- uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ];
-
- /* The free object handles - a set of stacks within this array */
- traceHandle objectHandles[ TRACE_KERNEL_OBJECT_COUNT ];
-
-} objectHandleStackType;
-
-extern objectHandleStackType objectHandleStacks;
-
-/******************************************************************************
- * Object Property Table
- * The Object Table contains name and other properties of the objects (tasks,
- * queues, mutexes, etc). The below data structures defines the properties of
- * each object class and are used to cast the byte buffer into a cleaner format.
- *
- * The values in the object table are continuously overwritten and always
- * represent the current state. If a property is changed during runtime, the OLD
- * value should be stored in the trace buffer, not the new value (since the new
- * value is found in the Object Property Table).
- *
- * For close events this mechanism is the old names are stored in the symbol
- * table), for "priority set" (the old priority is stored in the event data)
- * and for "isActive", where the value decides if the task switch event type
- * should be "new" or "resume".
- ******************************************************************************/
-
-typedef struct
-{
- /* = NCLASSES */
- uint32_t NumberOfObjectClasses;
-
- uint32_t ObjectPropertyTableSizeInBytes;
-
- /* This is used to calculate the index in the dynamic object table
- (handle - 1 - nofStaticObjects = index)*/
-#if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1)
- traceHandle NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)];
-#else
- traceHandle NumberOfObjectsPerClass[4*((TRACE_NCLASSES+3)/4)];
-#endif
-
- /* Allocation size rounded up to the closest multiple of 4 */
- uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/4) ];
-
- uint8_t TotalPropertyBytesPerClass[ 4*((TRACE_NCLASSES+3)/4) ];
-
- /* Allocation size rounded up to the closest multiple of 2 */
- uint16_t StartIndexOfClass[ 2*((TRACE_NCLASSES+1)/2) ];
-
- /* The actual handles issued, should be Initiated to all zeros */
- uint8_t objbytes[ 4*((TRACE_OBJECT_TABLE_SIZE+3)/4) ];
-} ObjectPropertyTableType;
-
-/* Symbol table data structure */
-typedef struct
-{
- /* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */
- uint32_t symTableSize;
-
- /* Entry 0 is reserved. Any reference to entry 0 implies NULL*/
- uint32_t nextFreeSymbolIndex;
-
- /* Size rounded up to closest multiple of 4, to avoid alignment issues*/
- uint8_t symbytes[4*(((TRC_CFG_SYMBOL_TABLE_SIZE)+3)/4)];
-
- /* Used for lookups - Up to 64 linked lists within the symbol table
- connecting all entries with the same 6 bit checksum.
- This field holds the current list heads. Should be initiated to zeros */
- uint16_t latestEntryOfChecksum[64];
-} symbolTableType;
-
-
-/*******************************************************************************
- * The data structures of the different events, all 4 bytes long
- ******************************************************************************/
-
-typedef struct
-{
- uint8_t type;
- uint8_t objHandle;
- uint16_t dts; /* differential timestamp - time since last event */
-} TSEvent, TREvent;
-
-typedef struct
-{
- uint8_t type;
- uint8_t dummy;
- uint16_t dts; /* differential timestamp - time since last event */
-} LPEvent;
-
-typedef struct
-{
- uint8_t type;
- uint8_t objHandle;
- uint16_t dts; /* differential timestamp - time since last event */
-} KernelCall;
-
-typedef struct
-{
- uint8_t type;
- uint8_t objHandle;
- uint8_t param;
- uint8_t dts; /* differential timestamp - time since last event */
-} KernelCallWithParamAndHandle;
-
-typedef struct
-{
- uint8_t type;
- uint8_t dts; /* differential timestamp - time since last event */
- uint16_t param;
-} KernelCallWithParam16;
-
-typedef struct
-{
- uint8_t type;
- uint8_t objHandle; /* the handle of the closed object */
- uint16_t symbolIndex; /* the name of the closed object */
-} ObjCloseNameEvent;
-
-typedef struct
-{
- uint8_t type;
- uint8_t arg1;
- uint8_t arg2;
- uint8_t arg3;
-} ObjClosePropEvent;
-
-typedef struct
-{
- uint8_t type;
- uint8_t unused1;
- uint8_t unused2;
- uint8_t dts;
-} TaskInstanceStatusEvent;
-
-typedef struct
-{
- uint8_t type;
- uint8_t dts;
- uint16_t payload; /* the name of the user event */
-} UserEvent;
-
-typedef struct
-{
- uint8_t type;
-
- /* 8 bits extra for storing DTS, if it does not fit in ordinary event
- (this one is always MSB if used) */
- uint8_t xts_8;
-
- /* 16 bits extra for storing DTS, if it does not fit in ordinary event. */
- uint16_t xts_16;
-} XTSEvent;
-
-typedef struct
-{
- uint8_t type;
-
- uint8_t xps_8;
- uint16_t xps_16;
-} XPSEvent;
-
-typedef struct{
- uint8_t type;
- uint8_t dts;
- uint16_t size;
-} MemEventSize;
-
-typedef struct{
- uint8_t type;
- uint8_t addr_high;
- uint16_t addr_low;
-} MemEventAddr;
-
-/*******************************************************************************
- * The separate user event buffer structure. Can be enabled in trcConfig.h.
- ******************************************************************************/
-
-#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)
-typedef struct
-{
- traceString name;
- traceString 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[(TRC_CFG_UB_CHANNELS)+1];
- uint8_t channelBuffer[((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) + 3) & 0xFFFFFFFC]; /* 1 byte per slot, with padding for 4 byte alignment */
- uint8_t dataBuffer[(TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) * 4]; /* 4 bytes per slot */
-
-} UserEventBuffer;
-#endif
-
-/*******************************************************************************
- * The main data structure, read by Tracealyzer from the RAM dump
- ******************************************************************************/
-
-typedef struct
-{
- volatile uint8_t startmarker0; /* Volatile is important, see init code. */
- volatile uint8_t startmarker1;
- volatile uint8_t startmarker2;
- volatile uint8_t startmarker3;
- volatile uint8_t startmarker4;
- volatile uint8_t startmarker5;
- volatile uint8_t startmarker6;
- volatile uint8_t startmarker7;
- volatile uint8_t startmarker8;
- volatile uint8_t startmarker9;
- volatile uint8_t startmarker10;
- volatile uint8_t startmarker11;
-
- /* Used to determine Kernel and Endianess */
- uint16_t version;
-
- /* Currently 5 */
- uint8_t minor_version;
-
- /* This should be 0 if lower IRQ priority values implies higher priority
- levels, such as on ARM Cortex M. If the opposite scheme is used, i.e.,
- if higher IRQ priority values means higher priority, this should be 1. */
- uint8_t irq_priority_order;
-
- /* sizeof(RecorderDataType) - just for control */
- uint32_t filesize;
-
- /* Current number of events recorded */
- uint32_t numEvents;
-
- /* The buffer size, in number of event records */
- uint32_t maxEvents;
-
- /* The event buffer index, where to write the next event */
- uint32_t nextFreeIndex;
-
- /* 1 if the buffer is full, 0 otherwise */
- uint32_t bufferIsFull;
-
- /* The frequency of the clock/timer/counter used as time base */
- uint32_t frequency;
-
- /* The absolute timestamp of the last stored event, in the native
- timebase, modulo frequency! */
- uint32_t absTimeLastEvent;
-
- /* The number of seconds in total - lasts for 136 years */
- uint32_t absTimeLastEventSecond;
-
- /* 1 if the recorder has been started, 0 if not yet started or stopped.
- This is a 32 bit variable due to alignment issues. */
- uint32_t recorderActive;
-
- /* If > 0, tells the maximum time between two traced ISRs that execute
- back-to-back. If the time between vTraceStoreISREnd and a directly
- following vTraceISRBegin is above isrTailchainingThreshold, we assume a
- return to the previous context in between the ISRs, otherwise we assume
- the have executed back-to-back and don't show any fragment of the previous
- context in between. */
- uint32_t isrTailchainingThreshold;
-
- /* Not used, remains for compatibility and future use */
- uint8_t notused[24];
-
- /* The amount of heap memory remaining at the last malloc or free event */
- uint32_t heapMemUsage;
-
- /* 0xF0F0F0F0 - for control only */
- int32_t debugMarker0;
-
- /* Set to value of TRC_CFG_USE_16BIT_OBJECT_HANDLES */
- uint32_t isUsing16bitHandles;
-
- /* The Object Property Table holds information about currently active
- tasks, queues, and other recorded objects. This is updated on each
- create call and includes object name and other properties. */
- ObjectPropertyTableType ObjectPropertyTable;
-
- /* 0xF1F1F1F1 - for control only */
- int32_t debugMarker1;
-
- /* The Symbol Table stores strings for User Events and is also used to
- store names of deleted objects, which still may be in the trace but no
- longer are available. */
- symbolTableType SymbolTable;
-
- /* For inclusion of float support, and for endian detection of floats.
- The value should be (float)1 or (uint32_t)0 */
-#if (TRC_CFG_INCLUDE_FLOAT_SUPPORT == 1)
- float exampleFloatEncoding;
-#else
- uint32_t exampleFloatEncoding;
-#endif
- /* This is non-zero if an internal error occurred in the recorder, e.g., if
- one of the Nxxx constants was too small. The systemInfo string will then
- contain an error message that is displayed when attempting to view the
- trace file. */
- uint32_t internalErrorOccured;
-
- /* 0xF2F2F2F2 - for control only */
- int32_t debugMarker2;
-
- /* Error messages from the recorder. */
- char systemInfo[80];
-
- /* 0xF3F3F3F3 - for control only */
- int32_t debugMarker3;
-
- /* The event data, in 4-byte records */
- uint8_t eventData[ (TRC_CFG_EVENT_BUFFER_SIZE) * 4 ];
-
-#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)
- UserEventBuffer userEventBuffer;
-#endif
-
- /* This should always be 0 */
- uint32_t endOfSecondaryBlocks;
-
- uint8_t endmarker0;
- uint8_t endmarker1;
- uint8_t endmarker2;
- uint8_t endmarker3;
- uint8_t endmarker4;
- uint8_t endmarker5;
- uint8_t endmarker6;
- uint8_t endmarker7;
- uint8_t endmarker8;
- uint8_t endmarker9;
- uint8_t endmarker10;
- uint8_t endmarker11;
-} RecorderDataType;
-
-extern RecorderDataType* RecorderDataPtr;
-
-/* Internal functions */
-
-/* Signal an error. */
-void prvTraceError(const char* msg);
-
-/*******************************************************************************
- * prvTracePortGetTimeStamp
- *
- * Returns the current time based on the HWTC macros which provide a hardware
- * isolation layer towards the hardware timer/counter.
- *
- * The HWTC macros and prvTracePortGetTimeStamp is the main porting issue
- * or the trace recorder library. Typically you should not need to change
- * the code of prvTracePortGetTimeStamp if using the HWTC macros.
- *
- ******************************************************************************/
-void prvTracePortGetTimeStamp(uint32_t *puiTimestamp);
-
-traceHandle prvTraceGetObjectHandle(traceObjectClass objectclass);
-
-void prvTraceFreeObjectHandle(traceObjectClass objectclass,
- traceHandle handle);
-
-/* Private function. Use the public functions in trcKernelPort.h */
-void prvTraceSetObjectName(traceObjectClass objectclass,
- traceHandle handle,
- const char* name);
-
-/* Internal macros */
-
-#define TRACE_PROPERTY_NAME_GET(objectclass, objecthandle) \
-(const char*)(& RecorderDataPtr->ObjectPropertyTable.objbytes \
-[uiIndexOfObject(objecthandle, objectclass)])
-
-#define TRACE_PROPERTY_OBJECT_STATE(objectclass, handle) \
-RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
-+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass]]
-
-#define TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle) \
-RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \
-+ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass] + 1]
-
-/* DEBUG ASSERTS */
-#if defined TRC_CFG_USE_TRACE_ASSERT && TRC_CFG_USE_TRACE_ASSERT != 0
-#define TRACE_ASSERT(eval, msg, defRetVal) \
-if (!(eval)) \
-{ \
- prvTraceError("TRACE_ASSERT: " msg); \
- return defRetVal; \
-}
-#else
-#define TRACE_ASSERT(eval, msg, defRetVal)
-#endif
-
-#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)*/
-
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-
-/******************************************************************************
- * Default values for STREAM PORT macros
- *
- * As a normal user, this is nothing you don't need to bother about. This is
- * only important if you want to define your own custom streaming interface.
- *
- * You may override these in your own trcStreamingPort.h to create a custom
- * stream port, and thereby stream the trace on any host-target interface.
- * These default values are suitable for most cases, except the J-Link port.
- ******************************************************************************/
-
-/******************************************************************************
- * TRC_STREAM_PORT_USE_INTERNAL_BUFFER
- *
- * There are two kinds of stream ports, those that store the event to the
- * internal buffer (with periodic flushing by the TzCtrl task) and those that
- * write directly to the streaming interface. Most stream ports use the
- * recorder's internal buffer, except for the SEGGER J-Link port (also uses a
- * RAM buffer, but one defined in the SEGGER code).
- *
- * If the stream port (trcStreamingPort.h) defines this as zero (0), it is
- * expected to transmit the data directly using TRC_STREAM_PORT_COMMIT_EVENT.
- * Otherwise it is expected that the trace data is stored in the internal buffer
- * and the TzCtrl task will then send the buffer pages when they become full.
- ******************************************************************************/
-#ifndef TRC_STREAM_PORT_USE_INTERNAL_BUFFER
-#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 1
-#endif
-
- /******************************************************************************
- * TRC_STREAM_PORT_ON_TRACE_BEGIN
- *
- * Defining any actions needed in the stream port when the recording is activated.
- *******************************************************************************/
-#ifndef TRC_STREAM_PORT_ON_TRACE_BEGIN
- #define TRC_STREAM_PORT_ON_TRACE_BEGIN() /* Do nothing */
-#endif
-
- /******************************************************************************
- * TRC_STREAM_PORT_ON_TRACE_BEGIN
- *
- * Defining any actions needed in the stream port when the tracing stops.
- * Empty by default.
- *******************************************************************************/
-#ifndef TRC_STREAM_PORT_ON_TRACE_END
-#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */
-#endif
-
- /******************************************************************************
- * TRC_STREAM_PORT_ALLOCATE_EVENT
- *
- * This macro is used to allocate memory for each event record, just before
- * assigning the record fields.
- * Depending on "TRC_STREAM_PORT_USE_INTERNAL_BUFFER", this either allocates
- * space in the paged event buffer, or on the local stack. In the latter case,
- * the COMMIT event is used to write the data to the streaming interface.
- ******************************************************************************/
-#ifndef TRC_STREAM_PORT_ALLOCATE_EVENT
-#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
- #define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type* _ptrData; _ptrData = (_type*)prvPagedEventBufferGetWritePointer(_size);
-#else
- #define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type _tmpArray[_size / sizeof(_type)]; _type* _ptrData = _tmpArray;
-#endif
-#endif
-
- /******************************************************************************
- * TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT
- *
- * This macro is used to allocate memory for each event record, just before
- * assigning the record fields.
- * This has the same purpose as TRC_STREAM_PORT_ALLOCATE_EVENT and by default
- * it has the same definition as TRC_STREAM_PORT_ALLOCATE_EVENT. This is used
- * for events carrying variable-sized payload, such as strings.
- * In the SEGGER RTT port, we need this in order to make a worst-case
- * allocation on the stack.
- ******************************************************************************/
-#ifndef TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT
-#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
- #define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) /* We do the same thing as for non-dynamic event sizes */
-#else
- #define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) _type _tmpArray[sizeof(largestEventType) / sizeof(_type)]; _type* _ptrData = _tmpArray;
-#endif
-#endif
-
- /******************************************************************************
- * TRC_STREAM_PORT_COMMIT_EVENT
- *
- * The COMMIT macro is used to write a single event record directly to the
- * streaming inteface, without first storing the event in the internal buffer.
- * This is currently only used in the SEGGER J-Link RTT port.
- *
- * This relies on the TRC_STREAM_PORT_WRITE_DATA macro, defined in by the
- * stream port in trcStreamingPort.h. The COMMIT macro calls
- * prvTraceWarning(TRC_STREAM_PORT_WRITE_DATA) if a non-zero value is returned
- * from TRC_STREAM_PORT_WRITE_DATA. If zero (0) is returned, it is assumed
- * that all data was successfully written.
- *
- * In ports using the internal buffer, this macro has no purpose as the events
- * are written to the internal buffer instead. They are then flushed to the
- * streaming interface in the TzCtrl task using TRC_STREAM_PORT_WRITE_DATA.
- ******************************************************************************/
-#ifndef TRC_STREAM_PORT_COMMIT_EVENT
-#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
- #define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) /* Not used */
-#else
- #define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) \
- { \
- if (TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, 0) != 0)\
- prvTraceWarning(PSF_WARNING_STREAM_PORT_WRITE); \
- }
-#endif
-#endif
-
-/******************************************************************************
- * TRC_STREAM_PORT_READ_DATA (defined in trcStreamingPort.h)
- *
- * Defining how to read data from host (commands from Tracealyzer).
- *
- * If there is no direct interface to host (e.g., if streaming to a file
- * system) this should be defined as 0. Instead use vTraceEnable(TRC_START) and
- * vTraceStop() to control the recording from target.
- *
- * Parameters:
- *
- * - _ptrData: a pointer to a data buffer, where the received data shall be
- * stored (TracealyzerCommandType*).
- *
- * - _size: the number of bytes to read (int).
- *
- * - _ptrBytesRead: a pointer to an integer (int), that should be assigned
- * with the number of bytes that was received.
- *
- * Example:
- *
- * int32_t myRead(void* ptrData, uint32_t size, int32_t* ptrBytesRead);
- *
- * #define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) \
- * myRead(_ptrData, _size, _ptrBytesRead)
- *
- * Your "myRead" function should return 0 if successful, i.e. if at least some
- * bytes were received. A non-zero value should be returned if the streaming
- * interface returned an error (e.g. a closed socket), which results in the
- * recorder calling prvTraceWarning with the error code
- * PSF_WARNING_STREAM_PORT_WRITE.
- *
- * If developing your own custom stream port and using the default internal
- * buffer, it is important that the _ptrBytesRead parameter is assigned
- * correctly by "myRead", i.e. with the number of bytes actually written.
- * Otherwise the data stream may get out of sync in case the streaming interface
- * can't swallow all data at once.
- ******************************************************************************/
-#ifndef TRC_STREAM_PORT_READ_DATA
-#error "No definition for TRC_STREAM_PORT_READ_DATA (should be in trcStreamingPort.h)"
-#endif
-
-/******************************************************************************
- * TRC_STREAM_PORT_WRITE_DATA (defined in trcStreamingPort.h)
- *
- * Defining how to write trace data to the streaming interface.
- *
- * Parameters:
- *
- * - _ptrData: a pointer (void*) to the data to write.
- *
- * - _size: the number of bytes to write (uint32_t).
- *
- * - _ptrBytesWritten: a pointer to an integer (int32_t), that should be
- * assigned with the number of bytes actually written.
- *
- * Example:
- *
- * int32_t myWrite(void* ptrData, uint32_t size, int32_t* ptrBytesWritten);
- *
- * #define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) \
- * myWrite(_ptrData, _size, _ptrBytesWritten)
- *
- * Your "myWrite" function should return 0 if successful, i.e. if at least some
- * bytes were sent. A non-zero value should be returned if the streaming interface
- * returned an error (e.g. a closed socket), which results in the recorder calling
- * prvTraceWarning with the error code PSF_WARNING_STREAM_PORT_WRITE.
- *
- * If developing your own custom stream port and using the default internal
- * buffer, it is important that the _ptrBytesWritten parameter is assigned
- * correctly by "myWrite", i.e. with the number of bytes actually written.
- * Otherwise the data stream may get out of sync in case the streaming interface
- * can't swallow all data at once.
- *
- * Assuming TRC_STREAM_PORT_USE_INTERNAL_BUFFER is 1 (default), the TzCtrl task
- * will use this macro to send one buffer page at a time. In case all data can't
- * be written at once (if _ptrBytesWritten is less than _size), the TzCtrl task
- * is smart enough to make repeated calls (with updated parameters) in order to
- * send the remaining data.
- *
- * However, if TRC_STREAM_PORT_USE_INTERNAL_BUFFER is 0, this is used from the
- * COMMIT macro, directly in the "event functions". In that case, the
- * _ptrBytesWritten parameter will be NULL and should be ignored by the write
- * function. In this case, it is assumed that all data can be sent in a single
- * call, otherwise the write function should return a non-zero error code.
- ******************************************************************************/
-#ifndef TRC_STREAM_PORT_WRITE_DATA
-#error "No definition for TRC_STREAM_PORT_WRITE_DATA (should be in trcStreamingPort.h)"
-#endif
-
-/******************************************************************************
-* Data structure declaration, depending on TRC_CFG_RECORDER_BUFFER_ALLOCATION
-*******************************************************************************/
-#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC)
-
- /* Static allocation. */
-
- /* If not defined in trcStreamingPort.h */
- #ifndef TRC_STREAM_PORT_ALLOCATE_FIELDS
- #define TRC_STREAM_PORT_ALLOCATE_FIELDS() \
- char _TzTraceData[(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];
- extern char _TzTraceData[(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];
- #endif
-
- /* If not defined in trcStreamingPort.h */
- #ifndef TRC_STREAM_PORT_MALLOC
- #define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
- #endif
-#else
- /* For Dynamic or Custom Allocation mode */
-
- /* If not defined in trcStreamingPort.h */
- #ifndef TRC_STREAM_PORT_ALLOCATE_FIELDS
- #define TRC_STREAM_PORT_ALLOCATE_FIELDS() char* _TzTraceData = NULL;
- extern char* _TzTraceData;
- #endif
-
- /* If not defined in trcStreamingPort.h */
- #ifndef TRC_STREAM_PORT_MALLOC
- #if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC)
- #define TRC_STREAM_PORT_MALLOC() \
- _TzTraceData = TRC_PORT_MALLOC((TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE));
- extern char* _TzTraceData;
- #else
- #define TRC_STREAM_PORT_MALLOC() /* Custom allocation. Not used. */
- #endif
- #endif
-#endif
-
-#ifndef TRC_STREAM_PORT_INIT
- #define TRC_STREAM_PORT_INIT() \
- TRC_STREAM_PORT_MALLOC(); /* Empty if static allocation mode */ \
- prvPagedEventBufferInit(_TzTraceData);
-#endif
-
-
-/* Signal an error. */
-void prvTraceError(int errCode);
-
-/* Signal an warning (does not stop the recorder). */
-void prvTraceWarning(int errCode);
-
-/******************************************************************************/
-/*** ERROR AND WARNING CODES (check using xTraceGetLastError) *****************/
-/******************************************************************************/
-
-#define PSF_ERROR_NONE 0
-#define PSF_ERROR_EVENT_CODE_TOO_LARGE 1
-#define PSF_ERROR_ISR_NESTING_OVERFLOW 2
-#define PSF_ERROR_DWT_NOT_SUPPORTED 3
-#define PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED 4
-#define PSF_ERROR_TZCTRLTASK_NOT_CREATED 5
-
-#define PSF_WARNING_SYMBOL_TABLE_SLOTS 101
-#define PSF_WARNING_SYMBOL_MAX_LENGTH 102
-#define PSF_WARNING_OBJECT_DATA_SLOTS 103
-#define PSF_WARNING_STRING_TOO_LONG 104
-#define PSF_WARNING_STREAM_PORT_READ 105
-#define PSF_WARNING_STREAM_PORT_WRITE 106
-
-/******************************************************************************/
-/*** INTERNAL STREAMING FUNCTIONS *********************************************/
-/******************************************************************************/
-
-/* Saves a symbol name (task name etc.) in symbol table */
-void prvTraceSaveSymbol(const void *address, const char *name);
-
-/* Deletes a symbol name (task name etc.) from symbol table */
-void prvTraceDeleteSymbol(void *address);
-
-/* Saves an object data entry (task base priority) in object data table */
-void prvTraceSaveObjectData(const void *address, uint32_t data);
-
-/* Removes an object data entry (task base priority) from object data table */
-void prvTraceDeleteObjectData(void *address);
-
-/* Store an event with zero parameters (event ID only) */
-void prvTraceStoreEvent0(uint16_t eventID);
-
-/* Store an event with one 32-bit parameter (pointer address or an int) */
-void prvTraceStoreEvent1(uint16_t eventID,
- uint32_t param1);
-
-/* Store an event with two 32-bit parameters */
-void prvTraceStoreEvent2(uint16_t eventID,
- uint32_t param1,
- uint32_t param2);
-
-/* Store an event with three 32-bit parameters */
-void prvTraceStoreEvent3(uint16_t eventID,
- uint32_t param1,
- uint32_t param2,
- uint32_t param3);
-
-/* Stores an event with <nParam> 32-bit integer parameters */
-void prvTraceStoreEvent(int nParam, uint16_t EventID, ...);
-
-/* Stories an event with a string and <nParam> 32-bit integer parameters */
-void prvTraceStoreStringEvent(int nArgs, uint16_t eventID, const char* str, ...);
-
-/* Initializes the paged event buffer used by certain stream ports */
-void prvPagedEventBufferInit(char* buffer);
-
-/* Retrieve a pointer to the paged event buffer */
-void* prvPagedEventBufferGetWritePointer(int sizeOfEvent);
-
-/* Transfer a full buffer page */
-uint32_t prvPagedEventBufferTransfer(void);
-
-/* The data structure for commands (a bit overkill) */
-typedef struct
-{
- unsigned char cmdCode;
- unsigned char param1;
- unsigned char param2;
- unsigned char param3;
- unsigned char param4;
- unsigned char param5;
- unsigned char checksumLSB;
- unsigned char checksumMSB;
-} TracealyzerCommandType;
-
-/* Checks if the provided command is a valid command */
-int prvIsValidCommand(TracealyzerCommandType* cmd);
-
-/* Executed the received command (Start or Stop) */
-void prvProcessCommand(TracealyzerCommandType* cmd);
-
-#define vTraceSetStopHook(x)
-
-#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
-
-#else /* when TRC_USE_TRACEALYZER_RECORDER == 0 */
-
-#define vTraceEnable(x)
-#define xTraceRegisterString(x) 0; (void)x;
-#define vTracePrint(chn, ...) (void)chn
-#define vTracePrintF(chn, ...) (void)chn
-#define vTraceInstanceFinishedNow()
-#define vTraceInstanceFinishedNext()
-#define vTraceStoreISRBegin(x) (void)x
-#define vTraceStoreISREnd(x) (void)x
-#define xTraceSetISRProperties(a, b) 0
-#define vTraceStoreKernelObjectName(a, b)
-#define xTraceRegisterChannelFormat(eventLabel, formatStr) 0
-#define vTraceChannelPrint(label)
-#define vTraceUBData(label, ...)
-
-#define vTraceSetFilterGroup(x)
-#define vTraceSetFilterMask(x)
-
-#define prvTraceSetReadyEventsEnabled(status)
-
-#define vTraceExcludeTask(handle)
-
-#define uiTraceStart() (1)
-#define vTraceStart()
-#define vTraceStop()
-
-#ifndef vTraceSetRecorderDataBuffer
-#define vTraceSetRecorderDataBuffer(pRecorderData)
-#endif
-
-#define vTraceConsoleChannelPrintF(fmt, ...)
-
-#ifndef TRC_ALLOC_CUSTOM_BUFFER
-#define TRC_ALLOC_CUSTOM_BUFFER(bufname)
-#endif
-
-#define xTraceIsRecordingEnabled() (0)
-
-#define vTraceSetStopHook(x)
-
-#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TRC_RECORDER_H */
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcRecorder.h + * + * The public API of the trace recorder. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_RECORDER_H +#define TRC_RECORDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stddef.h> +#include <stdarg.h> + +#define TRC_ACKNOWLEDGED (0xABC99123) + +#include "trcConfig.h" +#include "trcPortDefines.h" + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + +typedef uint16_t traceString; +typedef uint8_t traceUBChannel; +typedef uint8_t traceObjectClass; + +#if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) +typedef uint16_t traceHandle; +#else /* (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) */ +typedef uint8_t traceHandle; +#endif /* (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) */ + +#include "trcHardwarePort.h" +#include "trcKernelPort.h" + +/* Not yet available in snapshot mode */ +#define vTraceConsoleChannelPrintF(fmt, ...) (void)(fmt) +#define prvTraceStoreEvent0(...) +#define prvTraceStoreEvent1(...) +#define prvTraceStoreEvent2(...) +#define prvTraceStoreEvent3(...) +#define prvTraceStoreEvent(...) +#define prvTraceStoreStringEvent(...) + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) */ + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +typedef const char* traceString; +typedef const void* traceHandle; + +#include "trcHardwarePort.h" +#include "trcStreamingPort.h" +#include "trcKernelPort.h" + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#define TRC_STATE_IN_STARTUP 0 +#define TRC_STATE_IN_TASKSWITCH 1 +#define TRC_STATE_IN_APPLICATION 2 + +/* The user event channel for recorder warnings, must be defined in trcKernelPort.c */ +extern traceString trcWarningChannel; + +#define TRACE_GET_LOW16(value) ((uint16_t)((value) & 0x0000FFFF)) +#define TRACE_GET_HIGH16(value) ((uint16_t)(((value) >> 16) & 0x0000FFFF)) +#define TRACE_SET_LOW16(current, value) (((current) & 0xFFFF0000) | (value)) +#define TRACE_SET_HIGH16(current, value) (((current) & 0x0000FFFF) | (((uint32_t)(value)) << 16)) + +/******************************************************************************/ +/*** Common API - both Snapshot and Streaming mode ****************************/ +/******************************************************************************/ + +/****************************************************************************** +* vTraceEnable(int startOption); +* +* Initializes and optionally starts the trace, depending on the start option. +* To use the trace recorder, the startup must call vTraceEnable before any RTOS +* calls are made (including "create" calls). Three start options are provided: +* +* TRC_START: Starts the tracing directly. In snapshot mode this allows for +* starting the trace at any point in your code, assuming vTraceEnable(TRC_INIT) +* has been called in the startup. +* Can also be used for streaming without Tracealyzer control, e.g. to a local +* flash file system (assuming such a "stream port", see trcStreamingPort.h). +* +* TRC_START_AWAIT_HOST: For streaming mode only. Initializes the trace recorder +* if necessary and waits for a Start command from Tracealyzer ("Start Recording" +* button). This call is intentionally blocking! By calling vTraceEnable with +* this option from the startup code, you start tracing at this point and capture +* the early events. +* +* TRC_INIT: Initializes the trace recorder, but does not start the tracing. +* In snapshot mode, this must be followed by a vTraceEnable(TRC_START) sometime +* later. +* +* Usage examples: +* +* Snapshot trace, from startup: +* <board init> +* vTraceEnable(TRC_START); +* <RTOS init> +* +* Snapshot trace, from a later point: +* <board init> +* vTraceEnable(TRC_INIT); +* <RTOS init> +* ... +* vTraceEnable(TRC_START); // e.g., in task context, at some relevant event +* +* Streaming trace, from startup: +* <board init> +* vTraceEnable(TRC_START_AWAIT_HOST); // Blocks! +* <RTOS init> +* +* Streaming trace, from a later point: +* <board startup> +* vTraceEnable(TRC_INIT); +* <RTOS startup> +* +******************************************************************************/ +void vTraceEnable(int startOption); + +/****************************************************************************** + * vTracePrintF + * + * Generates "User Events", with formatted text and data, similar to a "printf". + * User Events can be used for very efficient logging from your application code. + * It is very fast since the actual string formatting is done on the host side, + * when the trace is displayed. The execution time is just some microseconds on + * a 32-bit MCU. + * + * User Events are shown as yellow labels in the main trace view of $PNAME. + * + * An advantage of User Events is that data can be plotted in the "User Event + * Signal Plot" view, visualizing any data you log as User Events, discrete + * states or control system signals (e.g. system inputs or outputs). + * + * You may group User Events into User Event Channels. The yellow User Event + * labels show the logged string, preceded by the channel name within brackets. + * + * Example: + * + * "[MyChannel] Hello World!" + * + * The User Event Channels are shown in the View Filter, which makes it easy to + * select what User Events you wish to display. User Event Channels are created + * using xTraceRegisterString(). + * + * Example: + * + * traceString adc_uechannel = xTraceRegisterString("ADC User Events"); + * ... + * vTracePrintF(adc_uechannel, + * "ADC channel %d: %d volts", + * ch, adc_reading); + * + * The following format specifiers are supported in both modes: + * %d - signed integer. + * %u - unsigned integer. + * %X - hexadecimal, uppercase. + * %x - hexadecimal, lowercase. + * %s - string (see comment below) + * + * For integer formats (%d, %u, %x, %X) you may also use width and padding. + * If using -42 as data argument, two examples are: + * "%05d" -> "-0042" + * "%5d" -> " -42". + * + * String arguments are supported in both snapshot and streaming, but in streaming + * mode you need to use xTraceRegisterString and use the returned traceString as + * the argument. In snapshot you simply provide a char* as argument. + * + * Snapshot: vTracePrintF(myChn, "my string: %s", str); + * Streaming: vTracePrintF(myChn, "my string: %s", xTraceRegisterString(str)); + * + * In snapshot mode you can specify 8-bit or 16-bit arguments to reduce RAM usage: + * %hd -> 16 bit (h) signed integer (d). + * %bu -> 8 bit (b) unsigned integer (u). + * + * However, in streaming mode all data arguments are assumed to be 32 bit wide. + * Width specifiers (e.g. %hd) are accepted but ignored (%hd treated like %d). + * + * The maximum event size also differs between the modes. In streaming this is + * limited by a maximum payload size of 52 bytes, including format string and + * data arguments. So if using one data argument, the format string is limited + * to 48 byte, etc. If this is exceeded, the format string is truncated and you + * get a warning in Tracealyzer. + * + * In snapshot mode you are limited to maximum 15 arguments, that must not exceed + * 32 bytes in total (not counting the format string). If exceeded, the recorder + * logs an internal error (displayed when opening the trace) and stops recording. + ******************************************************************************/ +#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) +void vTracePrintF(traceString chn, const char* fmt, ...); +#else +#define vTracePrintF(chn, fmt, ...) (void)(chn), (void)(fmt) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#endif + +/****************************************************************************** + * vTraceVPrintF + * + * vTracePrintF variant that accepts a va_list. + * See vTracePrintF documentation for further details. + * + ******************************************************************************/ +#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) +void vTraceVPrintF(traceString eventLabel, const char* formatStr, va_list vl); +#else +#define vTraceVPrintF(chn, formatStr, vl) (void)(chn), (void)(formatStr), (void)(vl) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#endif + +/****************************************************************************** +* vTracePrint +* +* A faster version of vTracePrintF, that only allows for logging a string. +* +* Example: +* +* traceString chn = xTraceRegisterString("MyChannel"); +* ... +* vTracePrint(chn, "Hello World!"); +******************************************************************************/ +#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) +void vTracePrint(traceString chn, const char* str); +#else +#define vTracePrint(chn, str) (void)(chn), (void)(str) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#endif + + +/******************************************************************************* +* vTraceConsoleChannelPrintF +* +* Wrapper for vTracePrint, using the default channel. Can be used as a drop-in +* replacement for printf and similar functions, e.g. in a debug logging macro. +* +* Example: +* +* // Old: #define LogString debug_console_printf +* +* // New, log to Tracealyzer instead: +* #define LogString vTraceConsoleChannelPrintF +* ... +* LogString("My value is: %d", myValue); +******************************************************************************/ +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) +void vTraceConsoleChannelPrintF(const char* fmt, ...); +#endif + +/******************************************************************************* +* xTraceRegisterString +* +* Register strings in the recorder, e.g. for names of user event channels. +* +* Example: +* myEventHandle = xTraceRegisterString("MyUserEvent"); +* ... +* vTracePrintF(myEventHandle, "My value is: %d", myValue); +******************************************************************************/ +#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) +traceString xTraceRegisterString(const char* name); +#else +#define xTraceRegisterString(x) ((void)(x), (traceString)0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ +#endif + +/******************************************************************************* + * vTraceSet...Name(void* object, const char* name) + * + * Parameter object: pointer to the kernel object that shall be named + * Parameter name: the name to set + * + * Kernel-specific functions for setting names of kernel objects, for display in + * Tracealyzer. + ******************************************************************************/ +/* See trcKernelPort.h for details (kernel-specific) */ + +/******************************************************************************* + * xTraceSetISRProperties + * + * Stores a name and priority level for an Interrupt Service Routine, to allow + * for better visualization. Returns a traceHandle used by vTraceStoreISRBegin. + * + * Example: + * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt + * ... + * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1); + * ... + * void ISR_handler() + * { + * vTraceStoreISRBegin(Timer1Handle); + * ... + * vTraceStoreISREnd(0); + * } + ******************************************************************************/ +traceHandle xTraceSetISRProperties(const char* name, uint8_t priority); + +/******************************************************************************* + * vTraceStoreISRBegin + * + * Registers the beginning of an Interrupt Service Routine, using a traceHandle + * provided by xTraceSetISRProperties. + * + * Example: + * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt + * ... + * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1); + * ... + * void ISR_handler() + * { + * vTraceStoreISRBegin(Timer1Handle); + * ... + * vTraceStoreISREnd(0); + * } + ******************************************************************************/ +void vTraceStoreISRBegin(traceHandle handle); + +/******************************************************************************* + * vTraceStoreISREnd + * + * Registers the end of an Interrupt Service Routine. + * + * The parameter pendingISR indicates if the interrupt has requested a + * task-switch (= 1), e.g., by signaling a semaphore. Otherwise (= 0) the + * interrupt is assumed to return to the previous context. + * + * Example: + * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt + * traceHandle traceHandleIsrTimer1 = 0; // The ID set by the recorder + * ... + * traceHandleIsrTimer1 = xTraceSetISRProperties("ISRTimer1", PRIO_OF_ISR_TIMER1); + * ... + * void ISR_handler() + * { + * vTraceStoreISRBegin(traceHandleIsrTimer1); + * ... + * vTraceStoreISREnd(0); + * } + ******************************************************************************/ +void vTraceStoreISREnd(int isTaskSwitchRequired); + +/******************************************************************************* + * vTraceInstanceFinishNow + * + * Creates an event that ends the current task instance at this very instant. + * This makes the viewer to splits the current fragment at this point and begin + * a new actor instance, even if no task-switch has occurred. + *****************************************************************************/ +void vTraceInstanceFinishedNow(void); + +/******************************************************************************* + * vTraceInstanceFinishedNext + * + * Marks the current "task instance" as finished on the next kernel call. + * + * If that kernel call is blocking, the instance ends after the blocking event + * and the corresponding return event is then the start of the next instance. + * If the kernel call is not blocking, the viewer instead splits the current + * fragment right before the kernel call, which makes this call the first event + * of the next instance. + *****************************************************************************/ +void vTraceInstanceFinishedNext(void); + +/******************************************************************************* + * xTraceGetLastError + * + * Returns the last error or warning as a string, or NULL if none. + *****************************************************************************/ +const char* xTraceGetLastError(void); + +/******************************************************************************* + * vTraceClearError + * + * Clears any errors. + *****************************************************************************/ +void vTraceClearError(void); + +/******************************************************************************* +* vTraceStop +* +* Stops the recording. Intended for snapshot mode or if streaming without +* Tracealyzer control (e.g., to a device file system). +******************************************************************************/ +void vTraceStop(void); + +/****************************************************************************** +* vTraceSetFrequency +* +* Registers the clock rate of the time source for the event timestamping. +* This is normally not required, but if the default value (TRC_HWTC_FREQ_HZ) +* should be incorrect for your setup, you can override it using this function. +* +* Must be called prior to vTraceEnable, and the time source is assumed to +* have a fixed clock frequency after the startup. +* +* Note that, in snapshot mode, the value is divided by the TRC_HWTC_DIVISOR. +* This is a software "prescaler" that is also applied on the timestamps. +*****************************************************************************/ +void vTraceSetFrequency(uint32_t frequency); + +/******************************************************************************* +* vTraceSetRecorderDataBuffer +* +* The trcConfig.h setting TRC_CFG_RECORDER_BUFFER_ALLOCATION allows for selecting +* custom allocation (TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM), which allows you to +* control where the recorder trace buffer is allocated. +* +* When custom allocation is selected, use TRC_ALLOC_CUSTOM_BUFFER to make the +* allocation (in global context) and then call vTraceSetRecorderDataBuffer to +* register the allocated buffer. This supports both snapshot and streaming, +* and has no effect if using other allocation modes than CUSTOM. +* +* NOTE: vTraceSetRecorderDataBuffer must be called before vTraceEnable. +******************************************************************************/ +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) +void vTraceSetRecorderDataBuffer(void* pRecorderData); +#else +#define vTraceSetRecorderDataBuffer(pRecorderData) /* If not CUSTOM, pRecorderData will be an undefined symbol (same as in TRC_ALLOC_CUSTOM_BUFFER), so no (void) here */ +#endif + + +/******************************************************************************* +* TRC_ALLOC_CUSTOM_BUFFER +* +* If using custom allocation of the trace buffer (i.e., your trcConfig.h has the +* setting TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM), this macro allows you to declare +* the trace buffer in a portable way that works both in snapshot and streaming. +* +* This macro has no effect if using another allocation mode, so you can easily +* switch between different recording modes and configurations, using the same +* initialization code. +* +* This translates to a single static allocation, on which you can apply linker +* directives to place it in a particular memory region. +* +* - Snapshot mode: "RecorderDataType <name>" +* +* - Streaming mode: "char <name> [<size>]", +* where <size> is defined in trcStreamingConfig.h. +* +* Example: +* +* // GCC example: place myTraceBuffer in section .tz, defined in the .ld file. +* TRC_ALLOC_CUSTOM_BUFFER(myTraceBuffer) __attribute__((section(".tz"))); +* +* int main(void) +* { +* ... +* vTraceSetRecorderDataBuffer(&myTraceBuffer); // Note the "&" +* ... +* vTraceEnable(TRC_INIT); // Initialize the data structure +******************************************************************************/ +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) + #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + #define TRC_ALLOC_CUSTOM_BUFFER(bufname) RecorderDataType bufname; + #elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + #ifdef TRC_CFG_RTT_BUFFER_SIZE_UP /* J-Link RTT */ + #define TRC_ALLOC_CUSTOM_BUFFER(bufname) char bufname [TRC_CFG_RTT_BUFFER_SIZE_UP]; /* Not static in this case, since declared in user code */ + #else + #define TRC_ALLOC_CUSTOM_BUFFER(bufname) char bufname [(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)]; + #endif + #endif +#else + #define TRC_ALLOC_CUSTOM_BUFFER(bufname) /* If not CUSTOM, bufname will be an undefined symbol (same as in vTraceSetRecorderDataBuffer), so no (void) here */ +#endif + +/****************************************************************************** +* xTraceIsRecordingEnabled +* +* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0. +******************************************************************************/ +int xTraceIsRecordingEnabled(void); + +/******************************************************************************* +* vTraceSetFilterGroup +* +* Sets the "filter group" to assign when creating RTOS objects, such as tasks, +* queues, semaphores and mutexes. This together with vTraceSetFilterMask +* allows you to control what events that are recorded, based on the +* objects they refer to. +* +* There are 16 filter groups named FilterGroup0 .. FilterGroup15. +* +* Note: We don't recommend filtering out the Idle task, so make sure to call +* vTraceSetFilterGroup just before initializing the RTOS, in order to assign +* such "default" objects to the right Filter Group (typically group 0). +* +* Example: +* +* // Assign tasks T1 to FilterGroup0 (default) +* <Create Task T1> +* +* // Assign Q1 and Q2 to FilterGroup1 +* vTraceSetFilterGroup(FilterGroup1); +* <Create Queue Q1> +* <Create Queue Q2> +* +* // Assigns Q3 to FilterGroup2 +* vTraceSetFilterGroup(FilterGroup2); +* <Create Queue Q3> +* +* // Only include FilterGroup0 and FilterGroup2, exclude FilterGroup1 (Q1 and Q2) from the trace +* vTraceSetFilterMask( FilterGroup0 | FilterGroup2 ); +* +* // Assign the default RTOS objects (e.g. Idle task) to FilterGroup0 +* vTraceSetFilterGroup(FilterGroup0); +* <Start the RTOS scheduler> +* +* Note that you may define your own names for the filter groups using +* preprocessor definitions, to make the code easier to understand. +* +* Example: +* +* #define BASE FilterGroup0 +* #define USB_EVENTS FilterGroup1 +* #define CAN_EVENTS FilterGroup2 +* +* Note that filtering per event type (regardless of object) is also available +* in trcConfig.h. +******************************************************************************/ +void vTraceSetFilterGroup(uint16_t filterGroup); + +/****************************************************************************** +* vTraceSetFilterMask +* +* Sets the "filter mask" that is used to filter the events by object. This can +* be used to reduce the trace data rate, i.e., if your streaming interface is +* a bottleneck or if you want longer snapshot traces without increasing the +* buffer size. +* +* Note: There are two kinds of filters in the recorder. The other filter type +* excludes all events of certain kinds (e.g., OS ticks). See trcConfig.h. +* +* The filtering is based on bitwise AND with the Filter Group ID, assigned +* to RTOS objects such as tasks, queues, semaphores and mutexes. +* This together with vTraceSetFilterGroup allows you to control what +* events that are recorded, based on the objects they refer to. +* +* See example for vTraceSetFilterGroup. +******************************************************************************/ +void vTraceSetFilterMask(uint16_t filterMask); + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + +/******************************************************************************/ +/*** Extended API for Snapshot mode *******************************************/ +/******************************************************************************/ + +/****************************************************************************** +* 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. +* +* Snapshot mode only! +******************************************************************************/ +typedef void(*TRACE_STOP_HOOK)(void); + +/******************************************************************************* +* vTraceStopHookPtr +* +* Points to a call back function that is called from vTraceStop(). +* +* Snapshot mode only! +******************************************************************************/ +extern TRACE_STOP_HOOK vTraceStopHookPtr; + +/******************************************************************************* +* vTraceSetStopHook +* +* Sets a function to be called when the recorder is stopped. +* +* Snapshot mode only! +******************************************************************************/ +void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction); + +/******************************************************************************* +* uiTraceStart +* +* [DEPRECATED] Use vTraceEnable instead. +* +* Starts the recorder. The recorder will not be started if an error has been +* indicated using prvTraceError, e.g. if any of the Nx constants in +* trcSnapshotConfig.h has a too small value (TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc). +* +* Returns 1 if the recorder was started successfully. +* Returns 0 if the recorder start was prevented due to a previous internal +* error. In that case, check xTraceGetLastError to get the error message. +* Any error message is also presented when opening a trace file. +* +* Snapshot mode only! +******************************************************************************/ +uint32_t uiTraceStart(void); + +/******************************************************************************* +* vTraceStart +* +* [DEPRECATED] Use vTraceEnable instead. +* +* Starts the recorder. The recorder will not be started if an error has been +* indicated using prvTraceError, e.g. if any of the Nx constants in +* trcSnapshotConfig.h has a too small value (TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc). +* +* Snapshot mode only! +******************************************************************************/ +void vTraceStart(void); + +/******************************************************************************* +* vTraceClear +* +* Resets the recorder. Only necessary if a restart is desired - this is not +* needed in the startup initialization. +* +* Snapshot mode only! +******************************************************************************/ +void vTraceClear(void); + + +/*****************************************************************************/ +/*** INTERNAL SNAPSHOT FUNCTIONS *********************************************/ +/*****************************************************************************/ + +#define TRC_UNUSED + +#ifndef TRC_CFG_INCLUDE_OBJECT_DELETE +#define TRC_CFG_INCLUDE_OBJECT_DELETE 0 +#endif + +#ifndef TRC_CFG_INCLUDE_READY_EVENTS +#define TRC_CFG_INCLUDE_READY_EVENTS 1 +#endif + +#ifndef TRC_CFG_INCLUDE_OSTICK_EVENTS +#define TRC_CFG_INCLUDE_OSTICK_EVENTS 0 +#endif + +/* This macro will create a task in the object table */ +#undef trcKERNEL_HOOKS_TASK_CREATE +#define trcKERNEL_HOOKS_TASK_CREATE(SERVICE, CLASS, pxTCB) \ + TRACE_SET_OBJECT_NUMBER(TASK, pxTCB); \ + TRACE_SET_OBJECT_FILTER(TASK, pxTCB, CurrentFilterGroup); \ + prvTraceSetObjectName(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_NAME(pxTCB)); \ + prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ + prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); + +/* This macro will remove the task and store it in the event buffer */ +#undef trcKERNEL_HOOKS_TASK_DELETE +#define trcKERNEL_HOOKS_TASK_DELETE(SERVICE, SERVICE_NAME, SERVICE_PROP, pxTCB) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ + prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \ + prvTraceStoreObjectNameOnCloseEvent(SERVICE_NAME, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \ + prvTraceStoreObjectPropertiesOnCloseEvent(SERVICE_PROP, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_CLASS_TASK); \ + prvTraceSetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TRACE_GET_TASK_PRIORITY(pxTCB)); \ + prvTraceSetObjectState(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), TASK_STATE_INSTANCE_NOT_ACTIVE); \ + prvTraceFreeObjectHandle(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); + + +/* This macro will setup a task in the object table */ +#undef trcKERNEL_HOOKS_OBJECT_CREATE +#define trcKERNEL_HOOKS_OBJECT_CREATE(SERVICE, CLASS, pxObject)\ + TRACE_SET_OBJECT_NUMBER(CLASS, pxObject);\ + TRACE_SET_OBJECT_FILTER(CLASS, pxObject, CurrentFilterGroup); \ + prvMarkObjectAsUsed(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject));\ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ + prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \ + prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), 0); + +/* This macro will remove the object and store it in the event buffer */ +#undef trcKERNEL_HOOKS_OBJECT_DELETE +#define trcKERNEL_HOOKS_OBJECT_DELETE(SERVICE, SERVICE_NAME, SERVICE_PROP, CLASS, pxObject) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ + prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); \ + prvTraceStoreObjectNameOnCloseEvent(SERVICE_NAME, TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \ + prvTraceStoreObjectPropertiesOnCloseEvent(SERVICE_PROP, TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject)); \ + prvTraceFreeObjectHandle(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); + +/* 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, CLASS, pxObject) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ + prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); + +/* This macro will create a call to a kernel service with a certain result, with a null object as parameter */ +#undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT +#define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT(SERVICE, TRACECLASS) \ + if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreKernelCall(SERVICE, TRACECLASS, 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_WITH_PARAM +#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM(SERVICE, CLASS, pxObject, param) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ + prvTraceStoreKernelCallWithParam(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint32_t)param); + +/* This macro will create a call to a kernel service with a certain result, with a null object and other value as parameter */ +#undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM +#define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM(SERVICE, TRACECLASS, param) \ + if (TRACE_GET_TASK_FILTER(TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreKernelCallWithParam(SERVICE, TRACECLASS, 0, param); + +/* This macro will create a call to a kernel service with a certain result, with an object as parameter */ +#undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY +#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY(SERVICE, param) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, (uint32_t)param); + +/* This macro will create a call to a kernel service with a certain result, with an object as parameter */ +#undef trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR +#define trcKERNEL_HOOKS_KERNEL_SERVICE_FROM_ISR(SERVICE, CLASS, pxObject) \ + if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ + prvTraceStoreKernelCall(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject)); + +/* This macro will create a call to a kernel service with a certain result, with a null object as parameter */ +#undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_FROM_ISR +#define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_FROM_ISR(SERVICE, TRACECLASS) \ + prvTraceStoreKernelCall(SERVICE, TRACECLASS, 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_WITH_PARAM_FROM_ISR +#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_PARAM_FROM_ISR(SERVICE, CLASS, pxObject, param) \ + if (TRACE_GET_OBJECT_FILTER(CLASS, pxObject) & CurrentFilterMask) \ + prvTraceStoreKernelCallWithParam(SERVICE, TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint32_t)param); + +/* This macro will create a call to a kernel service with a certain result, with a null object and other value as parameter */ +#undef trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM_FROM_ISR +#define trcKERNEL_HOOKS_KERNEL_SERVICE_NULL_OBJECT_WITH_PARAM_FROM_ISR(SERVICE, TRACECLASS, param) \ + prvTraceStoreKernelCallWithParam(SERVICE, TRACECLASS, 0, param); + +/* This macro will create a call to a kernel service with a certain result, with an object as parameter */ +#undef trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR +#define trcKERNEL_HOOKS_KERNEL_SERVICE_WITH_NUMERIC_PARAM_ONLY_FROM_ISR(SERVICE, param) \ + prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, (uint32_t)param); + +/* This macro will set the state for an object */ +#undef trcKERNEL_HOOKS_SET_OBJECT_STATE +#define trcKERNEL_HOOKS_SET_OBJECT_STATE(CLASS, pxObject, STATE) \ + prvTraceSetObjectState(TRACE_GET_OBJECT_TRACE_CLASS(CLASS, pxObject), TRACE_GET_OBJECT_NUMBER(CLASS, pxObject), (uint8_t)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() \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + prvTraceSetTaskInstanceFinished(TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK())); + +#if (TRC_CFG_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) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ + prvTraceStoreTaskReady(TRACE_GET_TASK_NUMBER(pxTCB)); +#else /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/ +#undef trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE +#define trcKERNEL_HOOKS_MOVED_TASK_TO_READY_STATE(pxTCB) +#endif /*(TRC_CFG_INCLUDE_READY_EVENTS == 1)*/ + +/* This macro will update the internal tick counter and call prvTracePortGetTimeStamp(0) to update the internal counters */ +#undef trcKERNEL_HOOKS_INCREMENT_TICK +#define trcKERNEL_HOOKS_INCREMENT_TICK() \ + { \ + extern uint32_t uiTraceTickCount; \ + uiTraceTickCount++; \ + prvTracePortGetTimeStamp(0); \ + } + +#if (TRC_CFG_INCLUDE_OSTICK_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) \ + prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue); +#else /*(TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)*/ +#undef trcKERNEL_HOOKS_NEW_TIME +#define trcKERNEL_HOOKS_NEW_TIME(SERVICE, xValue) +#endif /*(TRC_CFG_INCLUDE_OSTICK_EVENTS == 1)*/ + +/* This macro will create a task switch event to the currently executing task */ +#undef trcKERNEL_HOOKS_TASK_SWITCH +#define trcKERNEL_HOOKS_TASK_SWITCH( pxTCB ) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ + prvTraceStoreTaskswitch(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) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ + prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); \ + prvTraceSetTaskInstanceFinished((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) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ + { \ + prvTraceStoreKernelCallWithNumericParamOnly(SERVICE, xValue); \ + prvTraceSetTaskInstanceFinished((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) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ + { \ + prvTraceStoreKernelCallWithParam(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB), prvTraceGetPriorityProperty(TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)));\ + prvTraceSetPriorityProperty(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) \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ + prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); + +#undef trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR +#define trcKERNEL_HOOKS_TASK_RESUME_FROM_ISR(SERVICE, pxTCB) \ + if (TRACE_GET_OBJECT_FILTER(TASK, pxTCB) & CurrentFilterMask) \ + prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(pxTCB)); + +#if !defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1 + void prvTraceSetReadyEventsEnabled(int status); + void prvTraceStoreTaskReady(traceHandle handle); +#else + #define prvTraceSetReadyEventsEnabled(status) +#endif + +void prvTraceStoreLowPower(uint32_t flag); + +void prvTraceStoreTaskswitch(traceHandle task_handle); + + +#if (TRC_CFG_SCHEDULING_ONLY == 0) + +void prvTraceStoreKernelCall(uint32_t eventcode, traceObjectClass objectClass, uint32_t byteParam); + +void prvTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param); + +void prvTraceStoreKernelCallWithParam(uint32_t evtcode, traceObjectClass objectClass, + uint32_t objectNumber, uint32_t param); +#else + +#define prvTraceStoreKernelCall(eventcode, objectClass, byteParam) {} +#define prvTraceStoreKernelCallWithNumericParamOnly(evtcode, param) {} +#define prvTraceStoreKernelCallWithParam(evtcode, objectClass, objectNumber, param) {} + +#endif + +/******************************************************************************* +* prvTraceInitTraceData +* +* 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 +* using a static declaration. +******************************************************************************/ +void prvTraceInitTraceData(void); + +void prvTraceSetTaskInstanceFinished(traceHandle handle); + +void prvTraceSetPriorityProperty(uint8_t objectclass, traceHandle id, uint8_t value); + +uint8_t prvTraceGetPriorityProperty(uint8_t objectclass, traceHandle id); + +void prvTraceSetObjectState(uint8_t objectclass, traceHandle id, uint8_t value); + +void prvMarkObjectAsUsed(traceObjectClass objectclass, traceHandle handle); + +void prvTraceStoreObjectNameOnCloseEvent(uint8_t evtcode, traceHandle handle, + traceObjectClass objectclass); + +void prvTraceStoreObjectPropertiesOnCloseEvent(uint8_t evtcode, traceHandle handle, + traceObjectClass objectclass); + +/* Internal constants for task state */ +#define TASK_STATE_INSTANCE_NOT_ACTIVE 0 +#define TASK_STATE_INSTANCE_ACTIVE 1 + + +#if (TRC_CFG_INCLUDE_ISR_TRACING == 0) + +#undef vTraceSetISRProperties +#define vTraceSetISRProperties(handle, name, priority) (void)(handle), (void)(name), (void)(priority) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ + +#undef vTraceStoreISRBegin +#define vTraceStoreISRBegin(x) (void)(x) + +#undef vTraceStoreISREnd +#define vTraceStoreISREnd(x) (void)(x) + +#undef xTraceSetISRProperties +#define xTraceSetISRProperties(name, priority) ((void)(name), (void)(priority), (traceHandle)0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ + +#endif /*(TRC_CFG_INCLUDE_ISR_TRACING == 0)*/ + +/******************************************************************************* + * xTraceGetTraceBuffer + * + * Returns a pointer to the recorder data structure. Use this together with + * uiTraceGetTraceBufferSize if you wish to implement an own store/upload + * solution, e.g., in case a debugger connection is not available for uploading + * the data. + ******************************************************************************/ +void* xTraceGetTraceBuffer(void); + +/******************************************************************************* + * uiTraceGetTraceBufferSize + * + * Gets the size of the recorder data structure. For use together with + * vTraceGetTraceBuffer if you wish to implement an own store/upload solution, + * e.g., in case a debugger connection is not available for uploading the data. + ******************************************************************************/ +uint32_t uiTraceGetTraceBufferSize(void); + +#if (TRC_CFG_SCHEDULING_ONLY == 1) +#undef TRC_CFG_INCLUDE_USER_EVENTS +#define TRC_CFG_INCLUDE_USER_EVENTS 0 +#endif /*(TRC_CFG_SCHEDULING_ONLY == 1)*/ + +#if ((TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)) + +#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) +traceUBChannel xTraceRegisterUBChannel(traceString channel, traceString formatStr); +void vTraceUBData(traceUBChannel channel, ...); +void vTraceUBEvent(traceUBChannel channel); +#endif /*(TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)*/ + +#else /*((TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_SCHEDULING_ONLY == 0))*/ + +#undef vTracePrint +#define vTracePrint(chn, ...) (void)(chn) +#undef vTracePrintF +#define vTracePrintF(chn, fmt, ...) (void)(chn), (void)(fmt) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#undef vTraceVPrintF +#define vTraceVPrintF(chn, formatStr, vl) (void)(chn), (void)(formatStr), (void)(vl) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#undef xTraceRegisterString +#define xTraceRegisterString(x) ((void)(x), (traceString)0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ +#undef xTraceRegisterChannelFormat +#define xTraceRegisterChannelFormat(eventLabel, formatStr) ((void)(eventLabel), (void)(formatStr), 0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ +#undef vTraceUBData +#define vTraceUBData(label, ...) (void)(label) +#undef vTraceChannelPrint +#define vTraceChannelPrint(label) (void)(label) + +#endif /*(TRC_CFG_INCLUDE_USER_EVENTS == 1)*/ + +#define NEventCodes 0x100 + +/* Our local critical sections for the recorder */ +#define trcCRITICAL_SECTION_BEGIN() {TRACE_ENTER_CRITICAL_SECTION(); recorder_busy++;} +#define trcCRITICAL_SECTION_END() {recorder_busy--; TRACE_EXIT_CRITICAL_SECTION();} + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) + #define trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY TRACE_ALLOC_CRITICAL_SECTION + #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_BEGIN + #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY trcCRITICAL_SECTION_END +#else + #define trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY() {} + #define trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY() recorder_busy++; + #define trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY() recorder_busy--; +#endif + +/****************************************************************************** + * 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 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 */ + uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ]; + + /* The lowest index of this class (constant) */ + uint16_t lowestIndexOfClass[ TRACE_NCLASSES ]; + + /* The highest index of this class (constant) */ + uint16_t highestIndexOfClass[ TRACE_NCLASSES ]; + + /* The highest use count for this class (for statistics) */ + uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ]; + + /* The free object handles - a set of stacks within this array */ + traceHandle objectHandles[ TRACE_KERNEL_OBJECT_COUNT ]; + +} objectHandleStackType; + +extern objectHandleStackType objectHandleStacks; + +/****************************************************************************** + * Object Property Table + * The Object Table contains name and other properties of the objects (tasks, + * queues, mutexes, etc). The below data structures defines the properties of + * each object class and are used to cast the byte buffer into a cleaner format. + * + * The values in the object table are continuously overwritten and always + * represent the current state. If a property is changed during runtime, the OLD + * value should be stored in the trace buffer, not the new value (since the new + * value is found in the Object Property Table). + * + * For close events this mechanism is the old names are stored in the symbol + * table), for "priority set" (the old priority is stored in the event data) + * and for "isActive", where the value decides if the task switch event type + * should be "new" or "resume". + ******************************************************************************/ + +typedef struct +{ + /* = NCLASSES */ + uint32_t NumberOfObjectClasses; + + uint32_t ObjectPropertyTableSizeInBytes; + + /* This is used to calculate the index in the dynamic object table + (handle - 1 - nofStaticObjects = index)*/ +#if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) + traceHandle NumberOfObjectsPerClass[2*((TRACE_NCLASSES+1)/2)]; +#else + traceHandle NumberOfObjectsPerClass[4*((TRACE_NCLASSES+3)/4)]; +#endif + + /* Allocation size rounded up to the closest multiple of 4 */ + uint8_t NameLengthPerClass[ 4*((TRACE_NCLASSES+3)/4) ]; + + uint8_t TotalPropertyBytesPerClass[ 4*((TRACE_NCLASSES+3)/4) ]; + + /* Allocation size rounded up to the closest multiple of 2 */ + uint16_t StartIndexOfClass[ 2*((TRACE_NCLASSES+1)/2) ]; + + /* The actual handles issued, should be Initiated to all zeros */ + uint8_t objbytes[ 4*((TRACE_OBJECT_TABLE_SIZE+3)/4) ]; +} ObjectPropertyTableType; + +/* Symbol table data structure */ +typedef struct +{ + /* = SYMBOL_HISTORY_TABLE_SIZE_IN_BYTES */ + uint32_t symTableSize; + + /* Entry 0 is reserved. Any reference to entry 0 implies NULL*/ + uint32_t nextFreeSymbolIndex; + + /* Size rounded up to closest multiple of 4, to avoid alignment issues*/ + uint8_t symbytes[4*(((TRC_CFG_SYMBOL_TABLE_SIZE)+3)/4)]; + + /* Used for lookups - Up to 64 linked lists within the symbol table + connecting all entries with the same 6 bit checksum. + This field holds the current list heads. Should be initiated to zeros */ + uint16_t latestEntryOfChecksum[64]; +} symbolTableType; + + +/******************************************************************************* + * The data structures of the different events, all 4 bytes long + ******************************************************************************/ + +typedef struct +{ + uint8_t type; + uint8_t objHandle; + uint16_t dts; /* differential timestamp - time since last event */ +} TSEvent, TREvent; + +typedef struct +{ + uint8_t type; + uint8_t dummy; + uint16_t dts; /* differential timestamp - time since last event */ +} LPEvent; + +typedef struct +{ + uint8_t type; + uint8_t objHandle; + uint16_t dts; /* differential timestamp - time since last event */ +} KernelCall; + +typedef struct +{ + uint8_t type; + uint8_t objHandle; + uint8_t param; + uint8_t dts; /* differential timestamp - time since last event */ +} KernelCallWithParamAndHandle; + +typedef struct +{ + uint8_t type; + uint8_t dts; /* differential timestamp - time since last event */ + uint16_t param; +} KernelCallWithParam16; + +typedef struct +{ + uint8_t type; + uint8_t objHandle; /* the handle of the closed object */ + uint16_t symbolIndex; /* the name of the closed object */ +} ObjCloseNameEvent; + +typedef struct +{ + uint8_t type; + uint8_t arg1; + uint8_t arg2; + uint8_t arg3; +} ObjClosePropEvent; + +typedef struct +{ + uint8_t type; + uint8_t unused1; + uint8_t unused2; + uint8_t dts; +} TaskInstanceStatusEvent; + +typedef struct +{ + uint8_t type; + uint8_t dts; + uint16_t payload; /* the name of the user event */ +} UserEvent; + +typedef struct +{ + uint8_t type; + + /* 8 bits extra for storing DTS, if it does not fit in ordinary event + (this one is always MSB if used) */ + uint8_t xts_8; + + /* 16 bits extra for storing DTS, if it does not fit in ordinary event. */ + uint16_t xts_16; +} XTSEvent; + +typedef struct +{ + uint8_t type; + + uint8_t xps_8; + uint16_t xps_16; +} XPSEvent; + +typedef struct{ + uint8_t type; + uint8_t dts; + uint16_t size; +} MemEventSize; + +typedef struct{ + uint8_t type; + uint8_t addr_high; + uint16_t addr_low; +} MemEventAddr; + +/******************************************************************************* + * The separate user event buffer structure. Can be enabled in trcConfig.h. + ******************************************************************************/ + +#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) +typedef struct +{ + traceString name; + traceString 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[(TRC_CFG_UB_CHANNELS)+1]; + uint8_t channelBuffer[((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) + 3) & 0xFFFFFFFC]; /* 1 byte per slot, with padding for 4 byte alignment */ + uint8_t dataBuffer[(TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) * 4]; /* 4 bytes per slot */ + +} UserEventBuffer; +#endif + +/******************************************************************************* + * The main data structure, read by Tracealyzer from the RAM dump + ******************************************************************************/ + +typedef struct +{ + volatile uint8_t startmarker0; /* Volatile is important, see init code. */ + volatile uint8_t startmarker1; + volatile uint8_t startmarker2; + volatile uint8_t startmarker3; + volatile uint8_t startmarker4; + volatile uint8_t startmarker5; + volatile uint8_t startmarker6; + volatile uint8_t startmarker7; + volatile uint8_t startmarker8; + volatile uint8_t startmarker9; + volatile uint8_t startmarker10; + volatile uint8_t startmarker11; + + /* Used to determine Kernel and Endianess */ + uint16_t version; + + /* Currently 5 */ + uint8_t minor_version; + + /* This should be 0 if lower IRQ priority values implies higher priority + levels, such as on ARM Cortex M. If the opposite scheme is used, i.e., + if higher IRQ priority values means higher priority, this should be 1. */ + uint8_t irq_priority_order; + + /* sizeof(RecorderDataType) - just for control */ + uint32_t filesize; + + /* Current number of events recorded */ + uint32_t numEvents; + + /* The buffer size, in number of event records */ + uint32_t maxEvents; + + /* The event buffer index, where to write the next event */ + uint32_t nextFreeIndex; + + /* 1 if the buffer is full, 0 otherwise */ + uint32_t bufferIsFull; + + /* The frequency of the clock/timer/counter used as time base */ + uint32_t frequency; + + /* The absolute timestamp of the last stored event, in the native + timebase, modulo frequency! */ + uint32_t absTimeLastEvent; + + /* The number of seconds in total - lasts for 136 years */ + uint32_t absTimeLastEventSecond; + + /* 1 if the recorder has been started, 0 if not yet started or stopped. + This is a 32 bit variable due to alignment issues. */ + uint32_t recorderActive; + + /* If > 0, tells the maximum time between two traced ISRs that execute + back-to-back. If the time between vTraceStoreISREnd and a directly + following vTraceISRBegin is above isrTailchainingThreshold, we assume a + return to the previous context in between the ISRs, otherwise we assume + the have executed back-to-back and don't show any fragment of the previous + context in between. */ + uint32_t isrTailchainingThreshold; + + /* Not used, remains for compatibility and future use */ + uint8_t notused[24]; + + /* The amount of heap memory remaining at the last malloc or free event */ + uint32_t heapMemUsage; + + /* 0xF0F0F0F0 - for control only */ + int32_t debugMarker0; + + /* Set to value of TRC_CFG_USE_16BIT_OBJECT_HANDLES */ + uint32_t isUsing16bitHandles; + + /* The Object Property Table holds information about currently active + tasks, queues, and other recorded objects. This is updated on each + create call and includes object name and other properties. */ + ObjectPropertyTableType ObjectPropertyTable; + + /* 0xF1F1F1F1 - for control only */ + int32_t debugMarker1; + + /* The Symbol Table stores strings for User Events and is also used to + store names of deleted objects, which still may be in the trace but no + longer are available. */ + symbolTableType SymbolTable; + + /* For inclusion of float support, and for endian detection of floats. + The value should be (float)1 or (uint32_t)0 */ +#if (TRC_CFG_INCLUDE_FLOAT_SUPPORT == 1) + float exampleFloatEncoding; +#else + uint32_t exampleFloatEncoding; +#endif + /* This is non-zero if an internal error occurred in the recorder, e.g., if + one of the Nxxx constants was too small. The systemInfo string will then + contain an error message that is displayed when attempting to view the + trace file. */ + uint32_t internalErrorOccured; + + /* 0xF2F2F2F2 - for control only */ + int32_t debugMarker2; + + /* Error messages from the recorder. */ + char systemInfo[80]; + + /* 0xF3F3F3F3 - for control only */ + int32_t debugMarker3; + + /* The event data, in 4-byte records */ + uint8_t eventData[ (TRC_CFG_EVENT_BUFFER_SIZE) * 4 ]; + +#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) + UserEventBuffer userEventBuffer; +#endif + + /* This should always be 0 */ + uint32_t endOfSecondaryBlocks; + + uint8_t endmarker0; + uint8_t endmarker1; + uint8_t endmarker2; + uint8_t endmarker3; + uint8_t endmarker4; + uint8_t endmarker5; + uint8_t endmarker6; + uint8_t endmarker7; + uint8_t endmarker8; + uint8_t endmarker9; + uint8_t endmarker10; + uint8_t endmarker11; +} RecorderDataType; + +extern RecorderDataType* RecorderDataPtr; + +/* Internal functions */ + +/* Signal an error. */ +void prvTraceError(const char* msg); + +/******************************************************************************* + * prvTracePortGetTimeStamp + * + * Returns the current time based on the HWTC macros which provide a hardware + * isolation layer towards the hardware timer/counter. + * + * The HWTC macros and prvTracePortGetTimeStamp is the main porting issue + * or the trace recorder library. Typically you should not need to change + * the code of prvTracePortGetTimeStamp if using the HWTC macros. + * + ******************************************************************************/ +void prvTracePortGetTimeStamp(uint32_t *puiTimestamp); + +traceHandle prvTraceGetObjectHandle(traceObjectClass objectclass); + +void prvTraceFreeObjectHandle(traceObjectClass objectclass, + traceHandle handle); + +/* Private function. Use the public functions in trcKernelPort.h */ +void prvTraceSetObjectName(traceObjectClass objectclass, + traceHandle handle, + const char* name); + +/* Internal macros */ + +#define TRACE_PROPERTY_NAME_GET(objectclass, objecthandle) \ +(const char*)(& RecorderDataPtr->ObjectPropertyTable.objbytes \ +[uiIndexOfObject(objecthandle, objectclass)]) + +#define TRACE_PROPERTY_OBJECT_STATE(objectclass, handle) \ +RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \ ++ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass]] + +#define TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle) \ +RecorderDataPtr->ObjectPropertyTable.objbytes[uiIndexOfObject(handle, objectclass) \ ++ RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[objectclass] + 1] + +/* DEBUG ASSERTS */ +#if defined TRC_CFG_USE_TRACE_ASSERT && TRC_CFG_USE_TRACE_ASSERT != 0 +#define TRACE_ASSERT(eval, msg, defRetVal) \ +if (!(eval)) \ +{ \ + prvTraceError("TRACE_ASSERT: " msg); \ + return defRetVal; \ +} +#else +#define TRACE_ASSERT(eval, msg, defRetVal) +#endif + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)*/ + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +/****************************************************************************** + * Default values for STREAM PORT macros + * + * As a normal user, this is nothing you don't need to bother about. This is + * only important if you want to define your own custom streaming interface. + * + * You may override these in your own trcStreamingPort.h to create a custom + * stream port, and thereby stream the trace on any host-target interface. + * These default values are suitable for most cases, except the J-Link port. + ******************************************************************************/ + +/****************************************************************************** + * TRC_STREAM_PORT_USE_INTERNAL_BUFFER + * + * There are two kinds of stream ports, those that store the event to the + * internal buffer (with periodic flushing by the TzCtrl task) and those that + * write directly to the streaming interface. Most stream ports use the + * recorder's internal buffer, except for the SEGGER J-Link port (also uses a + * RAM buffer, but one defined in the SEGGER code). + * + * If the stream port (trcStreamingPort.h) defines this as zero (0), it is + * expected to transmit the data directly using TRC_STREAM_PORT_COMMIT_EVENT. + * Otherwise it is expected that the trace data is stored in the internal buffer + * and the TzCtrl task will then send the buffer pages when they become full. + ******************************************************************************/ +#ifndef TRC_STREAM_PORT_USE_INTERNAL_BUFFER +#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 1 +#endif + + /****************************************************************************** + * TRC_STREAM_PORT_ON_TRACE_BEGIN + * + * Defining any actions needed in the stream port when the recording is activated. + *******************************************************************************/ +#ifndef TRC_STREAM_PORT_ON_TRACE_BEGIN + #define TRC_STREAM_PORT_ON_TRACE_BEGIN() /* Do nothing */ +#endif + + /****************************************************************************** + * TRC_STREAM_PORT_ON_TRACE_END + * + * Defining any actions needed in the stream port when the tracing stops. + * Empty by default. + *******************************************************************************/ +#ifndef TRC_STREAM_PORT_ON_TRACE_END +#define TRC_STREAM_PORT_ON_TRACE_END() /* Do nothing */ +#endif + + /****************************************************************************** + * TRC_STREAM_PORT_ALLOCATE_EVENT + * + * This macro is used to allocate memory for each event record, just before + * assigning the record fields. + * Depending on "TRC_STREAM_PORT_USE_INTERNAL_BUFFER", this either allocates + * space in the paged event buffer, or on the local stack. In the latter case, + * the COMMIT event is used to write the data to the streaming interface. + * + * The BLOCKING option is only used within vTraceEnable, to ensure the full + * header, object table and symbol table is transferred without data loss. + ******************************************************************************/ +#ifndef TRC_STREAM_PORT_ALLOCATE_EVENT +#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) + #define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) \ + _type* _ptrData; \ + _ptrData = (_type*)prvPagedEventBufferGetWritePointer(_size); + + /************************************************************************** + If your application gets stuck in TRC_STREAM_PORT_ALLOCATE_EVENT_BLOCKING, + it means it fails to transfer the header, object table or symbol table + during vTraceEnable. + This occurs if the trace buffer is too small to accomodate these in full, + i.e. before the streaming interface is started and begins to transfer. + + Note that this is intentionally blocking to avoid data loss, but only + used within vTraceEnable. + **************************************************************************/ + + #define TRC_STREAM_PORT_ALLOCATE_EVENT_BLOCKING(_type, _ptrData, _size) \ + _type* _ptrData; \ + do { _ptrData = (_type*)prvPagedEventBufferGetWritePointer(_size); } while (_ptrData == NULL); + +#else + #define TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) _type _tmpArray[_size / sizeof(_type)]; _type* _ptrData = _tmpArray; + #define TRC_STREAM_PORT_ALLOCATE_EVENT_BLOCKING(_type, _ptrData, _size) _type _tmpArray[_size / sizeof(_type)]; _type* _ptrData = _tmpArray; +#endif +#endif + + /****************************************************************************** + * TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT + * + * This macro is used to allocate memory for each event record, just before + * assigning the record fields. + * This has the same purpose as TRC_STREAM_PORT_ALLOCATE_EVENT and by default + * it has the same definition as TRC_STREAM_PORT_ALLOCATE_EVENT. This is used + * for events carrying variable-sized payload, such as strings. + * In the SEGGER RTT port, we need this in order to make a worst-case + * allocation on the stack. + ******************************************************************************/ +#ifndef TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT +#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) + #define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) TRC_STREAM_PORT_ALLOCATE_EVENT(_type, _ptrData, _size) /* We do the same thing as for non-dynamic event sizes */ +#else + #define TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(_type, _ptrData, _size) _type _tmpArray[sizeof(largestEventType) / sizeof(_type)]; _type* _ptrData = _tmpArray; +#endif +#endif + + /****************************************************************************** + * TRC_STREAM_PORT_COMMIT_EVENT + * TRC_STREAM_PORT_COMMIT_EVENT_BLOCKING + * + * The COMMIT macro is used to write a single event record directly to the + * streaming inteface, without first storing the event in the internal buffer. + * This is currently only used in the SEGGER J-Link RTT port. + * + * The BLOCKING version is used when sending the initial trace header, which is + * important to receive in full. Otherwise, when using non-blocking RTT transfer + * this may be corrupted if using an RTT buffer smaller than the combined size + * of the header, object table and symbol table. + * + * This relies on the TRC_STREAM_PORT_WRITE_DATA macro, defined in by the + * stream port in trcStreamingPort.h. The COMMIT macro calls + * prvTraceWarning(TRC_STREAM_PORT_WRITE_DATA) if a non-zero value is returned + * from TRC_STREAM_PORT_WRITE_DATA. If zero (0) is returned, it is assumed + * that all data was successfully written. + * + * In ports using the internal buffer, this macro has no purpose as the events + * are written to the internal buffer instead. They are then flushed to the + * streaming interface in the TzCtrl task using TRC_STREAM_PORT_WRITE_DATA. + ******************************************************************************/ +#ifndef TRC_STREAM_PORT_COMMIT_EVENT +#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) + #define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) /* Not used */ + #define TRC_STREAM_PORT_COMMIT_EVENT_BLOCKING(_ptrData, _size) /* Not used */ +#else + #define TRC_STREAM_PORT_COMMIT_EVENT(_ptrData, _size) \ + { \ + int32_t dummy = 0; \ + (void)dummy; \ + if (TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, &dummy) != 0) \ + { \ + vTraceStop(); \ + } \ + } + + /* Only used during vTraceEnable */ + #define TRC_STREAM_PORT_COMMIT_EVENT_BLOCKING(_ptrData, _size) \ + { \ + char* ptrWrite = (char*)_ptrData; \ + uint32_t writeSize = _size; \ + uint32_t attemptCounter = 0; \ + int32_t bytesWritten; \ + int32_t status; \ + do \ + { \ + bytesWritten = 0; \ + status = TRC_STREAM_PORT_WRITE_DATA(ptrWrite, writeSize, &bytesWritten); \ + if (status != 0) \ + { \ + prvTraceError(PSF_ERROR_STREAM_PORT_WRITE); \ + break; \ + } \ + ptrWrite += bytesWritten; \ + writeSize -= bytesWritten; \ + attemptCounter++; \ + } while (writeSize > 0); \ + \ + if (attemptCounter > 1) \ + { \ + prvTraceWarning(PSF_WARNING_STREAM_PORT_INITIAL_BLOCKING); \ + } \ + } + +#endif +#endif + +/****************************************************************************** + * TRC_STREAM_PORT_READ_DATA (defined in trcStreamingPort.h) + * + * Defining how to read data from host (commands from Tracealyzer). + * + * If there is no direct interface to host (e.g., if streaming to a file + * system) this should be defined as 0. Instead use vTraceEnable(TRC_START) and + * vTraceStop() to control the recording from target. + * + * Parameters: + * + * - _ptrData: a pointer to a data buffer, where the received data shall be + * stored (TracealyzerCommandType*). + * + * - _size: the number of bytes to read (int). + * + * - _ptrBytesRead: a pointer to an integer (int), that should be assigned + * with the number of bytes that was received. + * + * Example: + * + * int32_t myRead(void* ptrData, uint32_t size, int32_t* ptrBytesRead); + * + * #define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) \ + * myRead(_ptrData, _size, _ptrBytesRead) + * + * Your "myRead" function should return 0 if successful, i.e. if at least some + * bytes were received. A non-zero value should be returned if the streaming + * interface returned an error (e.g. a closed socket), which results in the + * recorder calling prvTraceWarning with the error code + * PSF_WARNING_STREAM_PORT_WRITE. + * + * If developing your own custom stream port and using the default internal + * buffer, it is important that the _ptrBytesRead parameter is assigned + * correctly by "myRead", i.e. with the number of bytes actually written. + * Otherwise the data stream may get out of sync in case the streaming interface + * can't swallow all data at once. + ******************************************************************************/ +#ifndef TRC_STREAM_PORT_READ_DATA +#error "No definition for TRC_STREAM_PORT_READ_DATA (should be in trcStreamingPort.h)" +#endif + +/****************************************************************************** + * TRC_STREAM_PORT_WRITE_DATA (defined in trcStreamingPort.h) + * + * Defining how to write trace data to the streaming interface. + * + * Parameters: + * + * - _ptrData: a pointer (void*) to the data to write. + * + * - _size: the number of bytes to write (uint32_t). + * + * - _ptrBytesWritten: a pointer to an integer (int32_t), that should be + * assigned with the number of bytes actually written. + * + * Example: + * + * int32_t myWrite(void* ptrData, uint32_t size, int32_t* ptrBytesWritten); + * + * #define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) \ + * myWrite(_ptrData, _size, _ptrBytesWritten) + * + * Your "myWrite" function should return 0 if successful, i.e. if at least some + * bytes were sent. A non-zero value should be returned if the streaming interface + * returned an error (e.g. a closed socket), which results in the recorder calling + * prvTraceWarning with the error code PSF_WARNING_STREAM_PORT_WRITE. + * + * If developing your own custom stream port and using the default internal + * buffer, it is important that the _ptrBytesWritten parameter is assigned + * correctly by "myWrite", i.e. with the number of bytes actually written. + * Otherwise the data stream may get out of sync in case the streaming interface + * can't swallow all data at once. + * + * Assuming TRC_STREAM_PORT_USE_INTERNAL_BUFFER is 1 (default), the TzCtrl task + * will use this macro to send one buffer page at a time. In case all data can't + * be written at once (if _ptrBytesWritten is less than _size), the TzCtrl task + * is smart enough to make repeated calls (with updated parameters) in order to + * send the remaining data. + * + * However, if TRC_STREAM_PORT_USE_INTERNAL_BUFFER is 0, this is used from the + * COMMIT macro, directly in the "event functions". In that case, the + * _ptrBytesWritten parameter will be NULL and should be ignored by the write + * function. In this case, it is assumed that all data can be sent in a single + * call, otherwise the write function should return a non-zero error code. + ******************************************************************************/ +#ifndef TRC_STREAM_PORT_WRITE_DATA +#error "No definition for TRC_STREAM_PORT_WRITE_DATA (should be in trcStreamingPort.h)" +#endif + +/****************************************************************************** +* Data structure declaration, depending on TRC_CFG_RECORDER_BUFFER_ALLOCATION +*******************************************************************************/ +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC) + + /* Static allocation. */ + + /* If not defined in trcStreamingPort.h */ + #ifndef TRC_STREAM_PORT_ALLOCATE_FIELDS + #define TRC_STREAM_PORT_ALLOCATE_FIELDS() \ + char _TzTraceData[(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)]; + extern char _TzTraceData[(TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)]; + #endif + + /* If not defined in trcStreamingPort.h */ + #ifndef TRC_STREAM_PORT_MALLOC + #define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */ + #endif +#else + /* For Dynamic or Custom Allocation mode */ + + /* If not defined in trcStreamingPort.h */ + #ifndef TRC_STREAM_PORT_ALLOCATE_FIELDS + #define TRC_STREAM_PORT_ALLOCATE_FIELDS() char* _TzTraceData = NULL; + extern char* _TzTraceData; + #endif + + /* If not defined in trcStreamingPort.h */ + #ifndef TRC_STREAM_PORT_MALLOC + #if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC) + #define TRC_STREAM_PORT_MALLOC() \ + _TzTraceData = TRC_PORT_MALLOC((TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)); + extern char* _TzTraceData; + #else + #define TRC_STREAM_PORT_MALLOC() /* Custom allocation. Not used. */ + #endif + #endif +#endif + +#ifndef TRC_STREAM_PORT_INIT + #define TRC_STREAM_PORT_INIT() \ + TRC_STREAM_PORT_MALLOC(); /* Empty if static allocation mode */ \ + prvPagedEventBufferInit(_TzTraceData); +#endif + + +/* Signal an error. */ +void prvTraceError(int errCode); + +/* Signal an warning (does not stop the recorder). */ +void prvTraceWarning(int errCode); + +/******************************************************************************/ +/*** ERROR AND WARNING CODES (check using xTraceGetLastError) *****************/ +/******************************************************************************/ + +#define PSF_ERROR_NONE 0 +#define PSF_ERROR_EVENT_CODE_TOO_LARGE 1 +#define PSF_ERROR_ISR_NESTING_OVERFLOW 2 +#define PSF_ERROR_DWT_NOT_SUPPORTED 3 +#define PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED 4 +#define PSF_ERROR_TZCTRLTASK_NOT_CREATED 5 +#define PSF_ERROR_STREAM_PORT_WRITE 6 + +#define PSF_WARNING_SYMBOL_TABLE_SLOTS 7 +#define PSF_WARNING_SYMBOL_MAX_LENGTH 8 +#define PSF_WARNING_OBJECT_DATA_SLOTS 9 +#define PSF_WARNING_STRING_TOO_LONG 10 +#define PSF_WARNING_STREAM_PORT_READ 11 +#define PSF_WARNING_STREAM_PORT_WRITE 12 +#define PSF_WARNING_STREAM_PORT_INITIAL_BLOCKING 13 +#define PSF_WARNING_STACKMON_NO_SLOTS 14 + +/******************************************************************************/ +/*** INTERNAL STREAMING FUNCTIONS *********************************************/ +/******************************************************************************/ + +/* Saves a symbol name in the symbol table and returns the slot address */ +void* prvTraceSaveSymbol(const char *name); + +/* Saves a string in the symbol table for an object (task name etc.) */ +void prvTraceSaveObjectSymbol(void* address, const char *name); + +/* Deletes a symbol name (task name etc.) from symbol table */ +void prvTraceDeleteSymbol(void *address); + +/* Saves an object data entry (task base priority) in object data table */ +void prvTraceSaveObjectData(const void *address, uint32_t data); + +/* Removes an object data entry (task base priority) from object data table */ +void prvTraceDeleteObjectData(void *address); + +/* Store an event with zero parameters (event ID only) */ +void prvTraceStoreEvent0(uint16_t eventID); + +/* Store an event with one 32-bit parameter (pointer address or an int) */ +void prvTraceStoreEvent1(uint16_t eventID, + uint32_t param1); + +/* Store an event with two 32-bit parameters */ +void prvTraceStoreEvent2(uint16_t eventID, + uint32_t param1, + uint32_t param2); + +/* Store an event with three 32-bit parameters */ +void prvTraceStoreEvent3(uint16_t eventID, + uint32_t param1, + uint32_t param2, + uint32_t param3); + +/* Stores an event with <nParam> 32-bit integer parameters */ +void prvTraceStoreEvent(int nParam, uint16_t EventID, ...); + +/* Stories an event with a string and <nParam> 32-bit integer parameters */ +void prvTraceStoreStringEvent(int nArgs, uint16_t eventID, const char* str, ...); + +/* Initializes the paged event buffer used by certain stream ports */ +void prvPagedEventBufferInit(char* buffer); + +/* Retrieve a pointer to the paged event buffer */ +void* prvPagedEventBufferGetWritePointer(int sizeOfEvent); + +/* Transfer a full buffer page */ +uint32_t prvPagedEventBufferTransfer(void); + +/* The data structure for commands (a bit overkill) */ +typedef struct +{ + unsigned char cmdCode; + unsigned char param1; + unsigned char param2; + unsigned char param3; + unsigned char param4; + unsigned char param5; + unsigned char checksumLSB; + unsigned char checksumMSB; +} TracealyzerCommandType; + +/* Checks if the provided command is a valid command */ +int prvIsValidCommand(TracealyzerCommandType* cmd); + +/* Executed the received command (Start or Stop) */ +void prvProcessCommand(TracealyzerCommandType* cmd); + +#define vTraceSetStopHook(x) (void)(x) + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#else /* when TRC_USE_TRACEALYZER_RECORDER == 0 */ + +#define vTraceEnable(x) (void)(x) +#define xTraceRegisterString(x) ((void)(x), (traceString)0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ +#define vTracePrint(chn, ...) (void)(chn) +#define vTracePrintF(chn, fmt, ...) (void)(chn), (void)(fmt) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#define vTraceVPrintF(chn, formatStr, vl) (void)(chn), (void)(formatStr), (void)(vl) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#define vTraceInstanceFinishedNow() +#define vTraceInstanceFinishedNext() +#define vTraceStoreISRBegin(x) (void)(x) +#define vTraceStoreISREnd(x) (void)(x) +#define xTraceSetISRProperties(a, b) ((void)(a), (void)(b), (traceHandle)0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ +#define vTraceStoreKernelObjectName(a, b) (void)(a), (void)(b) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#define xTraceRegisterChannelFormat(eventLabel, formatStr) ((void)(eventLabel), (void)(formatStr), 0) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ +#define vTraceChannelPrint(label) (void)(label) +#define vTraceUBData(label, ...) (void)(label) + +#define vTraceSetFilterGroup(x) (void)(x) +#define vTraceSetFilterMask(x) (void)(x) + +#define prvTraceSetReadyEventsEnabled(status) (void)(status) + +#define vTraceExcludeTask(handle) (void)(handle) + +#define uiTraceStart() (1) +#define vTraceStart() +#define vTraceStop() + +#ifndef vTraceSetRecorderDataBuffer +#define vTraceSetRecorderDataBuffer(pRecorderData) /* No (void) here - ignore parameter since undefined symbol if custom allocation is not used */ +#endif + +#define vTraceConsoleChannelPrintF(fmt, ...) (void)(fmt) + +#ifndef TRC_ALLOC_CUSTOM_BUFFER +#define TRC_ALLOC_CUSTOM_BUFFER(bufname) +#endif + +#define xTraceIsRecordingEnabled() (0) + +#define vTraceSetStopHook(x) (void)(x) + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_RECORDER_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcConfig.h index dceb6d85b..fa113949d 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcConfig.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcConfig.h @@ -1,301 +1,411 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.4
- * Percepio AB, www.percepio.com
- *
- * trcConfig.h
- *
- * Main configuration parameters for the trace recorder library.
- * More settings can be found in trcStreamingConfig.h and trcSnapshotConfig.h.
- *
- * Read more at http://percepio.com/2016/10/05/rtos-tracing/
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_CONFIG_H
-#define TRC_CONFIG_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "trcPortDefines.h"
-
-/******************************************************************************
- * Include of processor header file
- *
- * Here you may need to include the header file for your processor. This is
- * required at least for the ARM Cortex-M port, that uses the ARM CMSIS API.
- * Try that in case of build problems. Otherwise, remove the #error line below.
- *****************************************************************************/
-#error "Trace Recorder: Please include your processor's header file here and remove this line."
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_HARDWARE_PORT
- *
- * Specify what hardware port to use (i.e., the "timestamping driver").
- *
- * All ARM Cortex-M MCUs are supported by "TRC_HARDWARE_PORT_ARM_Cortex_M".
- * This port uses the DWT cycle counter for Cortex-M3/M4/M7 devices, which is
- * available on most such devices. In case your device don't have DWT support,
- * you will get an error message opening the trace. In that case, you may
- * force the recorder to use SysTick timestamping instead, using this define:
- *
- * #define TRC_CFG_ARM_CM_USE_SYSTICK
- *
- * For ARM Cortex-M0/M0+ devices, SysTick mode is used automatically.
- *
- * See trcHardwarePort.h for available ports and information on how to
- * define your own port, if not already present.
- ******************************************************************************/
-#define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_NOT_SET
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_RECORDER_MODE
- *
- * Specify what recording mode to use. Snapshot means that the data is saved in
- * an internal RAM buffer, for later upload. Streaming means that the data is
- * transferred continuously to the host PC.
- *
- * For more information, see http://percepio.com/2016/10/05/rtos-tracing/
- * and the Tracealyzer User Manual.
- *
- * Values:
- * TRC_RECORDER_MODE_SNAPSHOT
- * TRC_RECORDER_MODE_STREAMING
- ******************************************************************************/
-#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_SNAPSHOT
-
-/******************************************************************************
- * TRC_CFG_FREERTOS_VERSION
- *
- * Specify what version of FreeRTOS that is used (don't change unless using the
- * trace recorder library with an older version of FreeRTOS).
- *
- * TRC_FREERTOS_VERSION_7_3 If using FreeRTOS v7.3.x
- * TRC_FREERTOS_VERSION_7_4 If using FreeRTOS v7.4.x
- * TRC_FREERTOS_VERSION_7_5_OR_7_6 If using FreeRTOS v7.5.0 - v7.6.0
- * TRC_FREERTOS_VERSION_8_X If using FreeRTOS v8.X.X
- * TRC_FREERTOS_VERSION_9_0_0 If using FreeRTOS v9.0.0
- * TRC_FREERTOS_VERSION_9_0_1 If using FreeRTOS v9.0.1
- * TRC_FREERTOS_VERSION_9_0_2 If using FreeRTOS v9.0.2
- * TRC_FREERTOS_VERSION_10_0_0 If using FreeRTOS v10.0.0 or later
- *****************************************************************************/
-#define TRC_CFG_FREERTOS_VERSION TRC_FREERTOS_VERSION_10_0_0
-
-/*******************************************************************************
- * TRC_CFG_SCHEDULING_ONLY
- *
- * Macro which should be defined as an integer value.
- *
- * If this setting is enabled (= 1), only scheduling events are recorded.
- * If disabled (= 0), all events are recorded (unless filtered in other ways).
- *
- * Default value is 0 (= include additional events).
- ******************************************************************************/
-#define TRC_CFG_SCHEDULING_ONLY 0
-
- /******************************************************************************
- * TRC_CFG_INCLUDE_MEMMANG_EVENTS
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * This controls if malloc and free calls should be traced. Set this to zero (0)
- * to exclude malloc/free calls, or one (1) to include such events in the trace.
- *
- * Default value is 1.
- *****************************************************************************/
-#define TRC_CFG_INCLUDE_MEMMANG_EVENTS 1
-
- /******************************************************************************
- * TRC_CFG_INCLUDE_USER_EVENTS
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * If this is zero (0), all code related to User Events is excluded in order
- * to reduce code size. Any attempts of storing User Events are then silently
- * ignored.
- *
- * User Events are application-generated events, like "printf" but for the
- * trace log, generated using vTracePrint and vTracePrintF.
- * The formatting is done on host-side, by Tracealyzer. User Events are
- * therefore much faster than a console printf and can often be used
- * in timing critical code without problems.
- *
- * Note: In streaming mode, User Events are used to provide error messages
- * and warnings from the recorder (in case of incorrect configuration) for
- * display in Tracealyzer. Disabling user events will also disable these
- * warnings. You can however still catch them by calling xTraceGetLastError
- * or by putting breakpoints in prvTraceError and prvTraceWarning.
- *
- * Default value is 1.
- *****************************************************************************/
-#define TRC_CFG_INCLUDE_USER_EVENTS 1
-
- /*****************************************************************************
- * TRC_CFG_INCLUDE_ISR_TRACING
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * If this is zero (0), the code for recording Interrupt Service Routines is
- * excluded, in order to reduce code size.
- *
- * Default value is 1.
- *
- * Note: tracing ISRs requires that you insert calls to vTraceStoreISRBegin
- * and vTraceStoreISREnd in your interrupt handlers.
- *****************************************************************************/
-#define TRC_CFG_INCLUDE_ISR_TRACING 1
-
- /*****************************************************************************
- * TRC_CFG_INCLUDE_READY_EVENTS
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * If one (1), events are recorded when tasks enter scheduling state "ready".
- * This allows Tracealyzer to show the initial pending time before tasks enter
- * the execution state, and present accurate response times.
- * If zero (0), "ready events" are not created, which allows for recording
- * longer traces in the same amount of RAM.
- *
- * Default value is 1.
- *****************************************************************************/
-#define TRC_CFG_INCLUDE_READY_EVENTS 1
-
- /*****************************************************************************
- * TRC_CFG_INCLUDE_OSTICK_EVENTS
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * If this is one (1), events will be generated whenever the OS clock is
- * increased. If zero (0), OS tick events are not generated, which allows for
- * recording longer traces in the same amount of RAM.
- *
- * Default value is 1.
- *****************************************************************************/
-#define TRC_CFG_INCLUDE_OSTICK_EVENTS 1
-
- /*****************************************************************************
- * TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * If this is zero (0), the trace will exclude any "event group" events.
- *
- * Default value is 0 (excluded) since dependent on event_groups.c
- *****************************************************************************/
-#define TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS 0
-
- /*****************************************************************************
- * TRC_CFG_INCLUDE_TIMER_EVENTS
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * If this is zero (0), the trace will exclude any Timer events.
- *
- * Default value is 0 since dependent on timers.c
- *****************************************************************************/
-#define TRC_CFG_INCLUDE_TIMER_EVENTS 0
-
- /*****************************************************************************
- * TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * If this is zero (0), the trace will exclude any "pending function call"
- * events, such as xTimerPendFunctionCall().
- *
- * Default value is 0 since dependent on timers.c
- *****************************************************************************/
-#define TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS 0
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * If this is zero (0), the trace will exclude any stream buffer or message
- * buffer events.
- *
- * Default value is 0 since dependent on stream_buffer.c (new in FreeRTOS v10)
- ******************************************************************************/
-#define TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS 0
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_RECORDER_BUFFER_ALLOCATION
- *
- * Specifies how the recorder buffer is allocated (also in case of streaming, in
- * port using the recorder's internal temporary buffer)
- *
- * Values:
- * TRC_RECORDER_BUFFER_ALLOCATION_STATIC - Static allocation (internal)
- * TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC - Malloc in vTraceEnable
- * TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM - Use vTraceSetRecorderDataBuffer
- *
- * Static and dynamic mode does the allocation for you, either in compile time
- * (static) or in runtime (malloc).
- * The custom mode allows you to control how and where the allocation is made,
- * for details see TRC_ALLOC_CUSTOM_BUFFER and vTraceSetRecorderDataBuffer().
- ******************************************************************************/
-#define TRC_CFG_RECORDER_BUFFER_ALLOCATION TRC_RECORDER_BUFFER_ALLOCATION_STATIC
-
-/******************************************************************************
- * TRC_CFG_MAX_ISR_NESTING
- *
- * Defines how many levels of interrupt nesting the recorder can handle, in
- * case multiple ISRs are traced and ISR nesting is possible. If this
- * is exceeded, the particular ISR will not be traced and the recorder then
- * logs an error message. This setting is used to allocate an internal stack
- * for keeping track of the previous execution context (4 byte per entry).
- *
- * This value must be a non-zero positive constant, at least 1.
- *
- * Default value: 8
- *****************************************************************************/
-#define TRC_CFG_MAX_ISR_NESTING 8
-
-/* Specific configuration, depending on Streaming/Snapshot mode */
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
-#include "trcSnapshotConfig.h"
-#elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-#include "trcStreamingConfig.h"
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TRC_CONFIG_H */
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcConfig.h + * + * Main configuration parameters for the trace recorder library. + * More settings can be found in trcStreamingConfig.h and trcSnapshotConfig.h. + * + * Read more at http://percepio.com/2016/10/05/rtos-tracing/ + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_CONFIG_H +#define TRC_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "trcPortDefines.h" + +/****************************************************************************** + * Include of processor header file + * + * Here you may need to include the header file for your processor. This is + * required at least for the ARM Cortex-M port, that uses the ARM CMSIS API. + * Try that in case of build problems. Otherwise, remove the #error line below. + *****************************************************************************/ +#error "Trace Recorder: Please include your processor's header file here and remove this line." + +/******************************************************************************* + * Configuration Macro: TRC_CFG_HARDWARE_PORT + * + * Specify what hardware port to use (i.e., the "timestamping driver"). + * + * All ARM Cortex-M MCUs are supported by "TRC_HARDWARE_PORT_ARM_Cortex_M". + * This port uses the DWT cycle counter for Cortex-M3/M4/M7 devices, which is + * available on most such devices. In case your device don't have DWT support, + * you will get an error message opening the trace. In that case, you may + * force the recorder to use SysTick timestamping instead, using this define: + * + * #define TRC_CFG_ARM_CM_USE_SYSTICK + * + * For ARM Cortex-M0/M0+ devices, SysTick mode is used automatically. + * + * See trcHardwarePort.h for available ports and information on how to + * define your own port, if not already present. + ******************************************************************************/ +#define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_NOT_SET + +/******************************************************************************* + * Configuration Macro: TRC_CFG_RECORDER_MODE + * + * Specify what recording mode to use. Snapshot means that the data is saved in + * an internal RAM buffer, for later upload. Streaming means that the data is + * transferred continuously to the host PC. + * + * For more information, see http://percepio.com/2016/10/05/rtos-tracing/ + * and the Tracealyzer User Manual. + * + * Values: + * TRC_RECORDER_MODE_SNAPSHOT + * TRC_RECORDER_MODE_STREAMING + ******************************************************************************/ +#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_SNAPSHOT + +/****************************************************************************** + * TRC_CFG_FREERTOS_VERSION + * + * Specify what version of FreeRTOS that is used (don't change unless using the + * trace recorder library with an older version of FreeRTOS). + * + * TRC_FREERTOS_VERSION_7_3_X If using FreeRTOS v7.3.X + * TRC_FREERTOS_VERSION_7_4_X If using FreeRTOS v7.4.X + * TRC_FREERTOS_VERSION_7_5_X If using FreeRTOS v7.5.X + * TRC_FREERTOS_VERSION_7_6_X If using FreeRTOS v7.6.X + * TRC_FREERTOS_VERSION_8_X_X If using FreeRTOS v8.X.X + * TRC_FREERTOS_VERSION_9_0_0 If using FreeRTOS v9.0.0 + * TRC_FREERTOS_VERSION_9_0_1 If using FreeRTOS v9.0.1 + * TRC_FREERTOS_VERSION_9_0_2 If using FreeRTOS v9.0.2 + * TRC_FREERTOS_VERSION_10_0_0 If using FreeRTOS v10.0.0 + * TRC_FREERTOS_VERSION_10_0_1 If using FreeRTOS v10.0.1 + * TRC_FREERTOS_VERSION_10_1_0 If using FreeRTOS v10.1.0 + * TRC_FREERTOS_VERSION_10_1_1 If using FreeRTOS v10.1.1 + * TRC_FREERTOS_VERSION_10_2_0 If using FreeRTOS v10.2.0 + * TRC_FREERTOS_VERSION_10_2_1 If using FreeRTOS v10.2.1 + * TRC_FREERTOS_VERSION_10_3_0 If using FreeRTOS v10.3.0 + * TRC_FREERTOS_VERSION_10_3_1 If using FreeRTOS v10.3.1 + * TRC_FREERTOS_VERSION_10_4_0 If using FreeRTOS v10.4.0 or later + *****************************************************************************/ +#define TRC_CFG_FREERTOS_VERSION FREERTOS_VERSION_NOT_SET + +/******************************************************************************* + * TRC_CFG_SCHEDULING_ONLY + * + * Macro which should be defined as an integer value. + * + * If this setting is enabled (= 1), only scheduling events are recorded. + * If disabled (= 0), all events are recorded (unless filtered in other ways). + * + * Default value is 0 (= include additional events). + ******************************************************************************/ +#define TRC_CFG_SCHEDULING_ONLY 0 + + /****************************************************************************** + * TRC_CFG_INCLUDE_MEMMANG_EVENTS + * + * Macro which should be defined as either zero (0) or one (1). + * + * This controls if malloc and free calls should be traced. Set this to zero (0) + * to exclude malloc/free calls, or one (1) to include such events in the trace. + * + * Default value is 1. + *****************************************************************************/ +#define TRC_CFG_INCLUDE_MEMMANG_EVENTS 1 + + /****************************************************************************** + * TRC_CFG_INCLUDE_USER_EVENTS + * + * Macro which should be defined as either zero (0) or one (1). + * + * If this is zero (0), all code related to User Events is excluded in order + * to reduce code size. Any attempts of storing User Events are then silently + * ignored. + * + * User Events are application-generated events, like "printf" but for the + * trace log, generated using vTracePrint and vTracePrintF. + * The formatting is done on host-side, by Tracealyzer. User Events are + * therefore much faster than a console printf and can often be used + * in timing critical code without problems. + * + * Note: In streaming mode, User Events are used to provide error messages + * and warnings from the recorder (in case of incorrect configuration) for + * display in Tracealyzer. Disabling user events will also disable these + * warnings. You can however still catch them by calling xTraceGetLastError + * or by putting breakpoints in prvTraceError and prvTraceWarning. + * + * Default value is 1. + *****************************************************************************/ +#define TRC_CFG_INCLUDE_USER_EVENTS 1 + + /***************************************************************************** + * TRC_CFG_INCLUDE_ISR_TRACING + * + * Macro which should be defined as either zero (0) or one (1). + * + * If this is zero (0), the code for recording Interrupt Service Routines is + * excluded, in order to reduce code size. This means that any calls to + * vTraceStoreISRBegin/vTraceStoreISREnd will be ignored. + * This does not completely disable ISR tracing, in cases where an ISR is + * calling a traced kernel service. These events will still be recorded and + * show up in anonymous ISR instances in Tracealyzer, with names such as + * "ISR sending to <queue name>". + * To disable such tracing, please refer to vTraceSetFilterGroup and + * vTraceSetFilterMask. + * + * Default value is 1. + * + * Note: tracing ISRs requires that you insert calls to vTraceStoreISRBegin + * and vTraceStoreISREnd in your interrupt handlers. + *****************************************************************************/ +#define TRC_CFG_INCLUDE_ISR_TRACING 1 + + /***************************************************************************** + * TRC_CFG_INCLUDE_READY_EVENTS + * + * Macro which should be defined as either zero (0) or one (1). + * + * If one (1), events are recorded when tasks enter scheduling state "ready". + * This allows Tracealyzer to show the initial pending time before tasks enter + * the execution state, and present accurate response times. + * If zero (0), "ready events" are not created, which allows for recording + * longer traces in the same amount of RAM. + * + * Default value is 1. + *****************************************************************************/ +#define TRC_CFG_INCLUDE_READY_EVENTS 1 + + /***************************************************************************** + * TRC_CFG_INCLUDE_OSTICK_EVENTS + * + * Macro which should be defined as either zero (0) or one (1). + * + * If this is one (1), events will be generated whenever the OS clock is + * increased. If zero (0), OS tick events are not generated, which allows for + * recording longer traces in the same amount of RAM. + * + * Default value is 1. + *****************************************************************************/ +#define TRC_CFG_INCLUDE_OSTICK_EVENTS 1 + + /***************************************************************************** + * TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS + * + * Macro which should be defined as either zero (0) or one (1). + * + * If this is zero (0), the trace will exclude any "event group" events. + * + * Default value is 0 (excluded) since dependent on event_groups.c + *****************************************************************************/ +#define TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS 0 + + /***************************************************************************** + * TRC_CFG_INCLUDE_TIMER_EVENTS + * + * Macro which should be defined as either zero (0) or one (1). + * + * If this is zero (0), the trace will exclude any Timer events. + * + * Default value is 0 since dependent on timers.c + *****************************************************************************/ +#define TRC_CFG_INCLUDE_TIMER_EVENTS 0 + + /***************************************************************************** + * TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS + * + * Macro which should be defined as either zero (0) or one (1). + * + * If this is zero (0), the trace will exclude any "pending function call" + * events, such as xTimerPendFunctionCall(). + * + * Default value is 0 since dependent on timers.c + *****************************************************************************/ +#define TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS 0 + +/******************************************************************************* + * Configuration Macro: TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS + * + * Macro which should be defined as either zero (0) or one (1). + * + * If this is zero (0), the trace will exclude any stream buffer or message + * buffer events. + * + * Default value is 0 since dependent on stream_buffer.c (new in FreeRTOS v10) + ******************************************************************************/ +#define TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS 0 + + /****************************************************************************** + * TRC_CFG_ENABLE_STACK_MONITOR + * + * If enabled (1), the recorder periodically reports the unused stack space of + * all active tasks. + * The stack monitoring runs in the Tracealyzer Control task, TzCtrl. This task + * is always created by the recorder when in streaming mode. + * In snapshot mode, the TzCtrl task is only used for stack monitoring and is + * not created unless this is enabled. + *****************************************************************************/ +#define TRC_CFG_ENABLE_STACK_MONITOR 1 + + /****************************************************************************** + * TRC_CFG_STACK_MONITOR_MAX_TASKS + * + * Macro which should be defined as a non-zero integer value. + * + * This controls how many tasks that can be monitored by the stack monitor. + * If this is too small, some tasks will be excluded and a warning is shown. + * + * Default value is 10. + *****************************************************************************/ +#define TRC_CFG_STACK_MONITOR_MAX_TASKS 10 + + /****************************************************************************** + * TRC_CFG_STACK_MONITOR_MAX_REPORTS + * + * Macro which should be defined as a non-zero integer value. + * + * This defines how many tasks that will be subject to stack usage analysis for + * each execution of the Tracealyzer Control task (TzCtrl). Note that the stack + * monitoring cycles between the tasks, so this does not affect WHICH tasks that + * are monitored, but HOW OFTEN each task stack is analyzed. + * + * This setting can be combined with TRC_CFG_CTRL_TASK_DELAY to tune the + * frequency of the stack monitoring. This is motivated since the stack analysis + * can take some time to execute. + * However, note that the stack analysis runs in a separate task (TzCtrl) that + * can be executed on low priority. This way, you can avoid that the stack + * analysis disturbs any time-sensitive tasks. + * + * Default value is 1. + *****************************************************************************/ +#define TRC_CFG_STACK_MONITOR_MAX_REPORTS 1 + + /******************************************************************************* + * Configuration Macro: TRC_CFG_CTRL_TASK_PRIORITY + * + * The scheduling priority of the Tracealyzer Control (TzCtrl) task. + * + * In streaming mode, TzCtrl is used to receive start/stop commands from + * Tracealyzer and in some cases also to transmit the trace data (for stream + * ports that uses the internal buffer, like TCP/IP). For such stream ports, + * make sure the TzCtrl priority is high enough to ensure reliable periodic + * execution and transfer of the data, but low enough to avoid disturbing any + * time-sensitive functions. + * + * In Snapshot mode, TzCtrl is only used for the stack usage monitoring and is + * not created if stack monitoring is disabled. TRC_CFG_CTRL_TASK_PRIORITY should + * be low, to avoid disturbing any time-sensitive tasks. + ******************************************************************************/ +#define TRC_CFG_CTRL_TASK_PRIORITY 1 + + /******************************************************************************* + * Configuration Macro: TRC_CFG_CTRL_TASK_DELAY + * + * The delay between loops of the TzCtrl task (see TRC_CFG_CTRL_TASK_PRIORITY), + * which affects the frequency of the stack monitoring. + * + * In streaming mode, this also affects the trace data transfer if you are using + * a stream port leveraging the internal buffer (like TCP/IP). A shorter delay + * increases the CPU load of TzCtrl somewhat, but may improve the performance of + * of the trace streaming, especially if the trace buffer is small. + ******************************************************************************/ +#define TRC_CFG_CTRL_TASK_DELAY 10 + + /******************************************************************************* + * Configuration Macro: TRC_CFG_CTRL_TASK_STACK_SIZE + * + * The stack size of the Tracealyzer Control (TzCtrl) task. + * See TRC_CFG_CTRL_TASK_PRIORITY for further information about TzCtrl. + ******************************************************************************/ +#define TRC_CFG_CTRL_TASK_STACK_SIZE (configMINIMAL_STACK_SIZE * 2) + +/******************************************************************************* + * Configuration Macro: TRC_CFG_RECORDER_BUFFER_ALLOCATION + * + * Specifies how the recorder buffer is allocated (also in case of streaming, in + * port using the recorder's internal temporary buffer) + * + * Values: + * TRC_RECORDER_BUFFER_ALLOCATION_STATIC - Static allocation (internal) + * TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC - Malloc in vTraceEnable + * TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM - Use vTraceSetRecorderDataBuffer + * + * Static and dynamic mode does the allocation for you, either in compile time + * (static) or in runtime (malloc). + * The custom mode allows you to control how and where the allocation is made, + * for details see TRC_ALLOC_CUSTOM_BUFFER and vTraceSetRecorderDataBuffer(). + ******************************************************************************/ +#define TRC_CFG_RECORDER_BUFFER_ALLOCATION TRC_RECORDER_BUFFER_ALLOCATION_STATIC + +/****************************************************************************** + * TRC_CFG_MAX_ISR_NESTING + * + * Defines how many levels of interrupt nesting the recorder can handle, in + * case multiple ISRs are traced and ISR nesting is possible. If this + * is exceeded, the particular ISR will not be traced and the recorder then + * logs an error message. This setting is used to allocate an internal stack + * for keeping track of the previous execution context (4 byte per entry). + * + * This value must be a non-zero positive constant, at least 1. + * + * Default value: 8 + *****************************************************************************/ +#define TRC_CFG_MAX_ISR_NESTING 8 + +/****************************************************************************** + * TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND + * + * When using FreeRTOS v10.3.0 or v10.3.1, please make sure that the trace + * point in prvNotifyQueueSetContainer() in queue.c is renamed from + * traceQUEUE_SEND to traceQUEUE_SET_SEND in order to tell them apart from + * other traceQUEUE_SEND trace points. Then set this to TRC_ACKNOWLEDGED. + *****************************************************************************/ +#define TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND 0 /* TRC_ACKNOWLEDGED */ + +/* Specific configuration, depending on Streaming/Snapshot mode */ +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) +#include "trcSnapshotConfig.h" +#elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) +#include "trcStreamingConfig.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _TRC_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcSnapshotConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcSnapshotConfig.h index 5ce12fcaa..601dfda68 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcSnapshotConfig.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcSnapshotConfig.h @@ -1,377 +1,377 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.4
- * Percepio AB, www.percepio.com
- *
- * trcSnapshotConfig.h
- *
- * Configuration parameters for trace recorder library in snapshot mode.
- * Read more at http://percepio.com/2016/10/05/rtos-tracing/
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_SNAPSHOT_CONFIG_H
-#define TRC_SNAPSHOT_CONFIG_H
-
-#define TRC_SNAPSHOT_MODE_RING_BUFFER (0x01)
-#define TRC_SNAPSHOT_MODE_STOP_WHEN_FULL (0x02)
-
-/******************************************************************************
- * TRC_CFG_SNAPSHOT_MODE
- *
- * Macro which should be defined as one of:
- * - TRC_SNAPSHOT_MODE_RING_BUFFER
- * - TRC_SNAPSHOT_MODE_STOP_WHEN_FULL
- * Default is TRC_SNAPSHOT_MODE_RING_BUFFER.
- *
- * With TRC_CFG_SNAPSHOT_MODE set to TRC_SNAPSHOT_MODE_RING_BUFFER, the
- * events are stored in a ring buffer, i.e., where the oldest events are
- * overwritten when the buffer becomes full. This allows you to get the last
- * events leading up to an interesting state, e.g., an error, without having
- * to store the whole run since startup.
- *
- * When TRC_CFG_SNAPSHOT_MODE is TRC_SNAPSHOT_MODE_STOP_WHEN_FULL, the
- * recording is stopped when the buffer becomes full. This is useful for
- * recording events following a specific state, e.g., the startup sequence.
- *****************************************************************************/
-#define TRC_CFG_SNAPSHOT_MODE TRC_SNAPSHOT_MODE_RING_BUFFER
-
-/*******************************************************************************
- * TRC_CFG_EVENT_BUFFER_SIZE
- *
- * Macro which should be defined as an integer value.
- *
- * This defines the capacity of the event buffer, i.e., the number of records
- * it may store. Most events use one record (4 byte), although some events
- * require multiple 4-byte records. You should adjust this to the amount of RAM
- * available in the target system.
- *
- * Default value is 1000, which means that 4000 bytes is allocated for the
- * event buffer.
- ******************************************************************************/
-#define TRC_CFG_EVENT_BUFFER_SIZE 1000
-
-/*******************************************************************************
- * TRC_CFG_NTASK, TRC_CFG_NISR, TRC_CFG_NQUEUE, TRC_CFG_NSEMAPHORE...
- *
- * A group of macros which should be defined as integer values, zero or larger.
- *
- * These define the capacity of the Object Property Table, i.e., the maximum
- * number of objects active at any given point, within each object class (e.g.,
- * task, queue, semaphore, ...).
- *
- * If tasks or other objects are deleted in your system, this
- * setting does not limit the total amount of objects created, only the number
- * of objects that have been successfully created but not yet deleted.
- *
- * Using too small values will cause vTraceError to be called, which stores an
- * error message in the trace that is shown when opening the trace file. The
- * error message can also be retrieved using xTraceGetLastError.
- *
- * It can be wise to start with large values for these constants,
- * unless you are very confident on these numbers. Then do a recording and
- * check the actual usage by selecting View menu -> Trace Details ->
- * Resource Usage -> Object Table.
- ******************************************************************************/
-#define TRC_CFG_NTASK 15
-#define TRC_CFG_NISR 5
-#define TRC_CFG_NQUEUE 10
-#define TRC_CFG_NSEMAPHORE 10
-#define TRC_CFG_NMUTEX 10
-#define TRC_CFG_NTIMER 5
-#define TRC_CFG_NEVENTGROUP 5
-#define TRC_CFG_NSTREAMBUFFER 5
-#define TRC_CFG_NMESSAGEBUFFER 5
-
-/******************************************************************************
- * TRC_CFG_INCLUDE_FLOAT_SUPPORT
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * If this is zero (0), the support for logging floating point values in
- * vTracePrintF is stripped out, in case floating point values are not used or
- * supported by the platform used.
- *
- * Floating point values are only used in vTracePrintF and its subroutines, to
- * allow for storing float (%f) or double (%lf) arguments.
- *
- * vTracePrintF can be used with integer and string arguments in either case.
- *
- * Default value is 0.
- *****************************************************************************/
-#define TRC_CFG_INCLUDE_FLOAT_SUPPORT 0
-
-/*******************************************************************************
- * TRC_CFG_SYMBOL_TABLE_SIZE
- *
- * Macro which should be defined as an integer value.
- *
- * This defines the capacity of the symbol table, in bytes. This symbol table
- * stores User Events labels and names of deleted tasks, queues, or other kernel
- * objects. If you don't use User Events or delete any kernel
- * objects you set this to a very low value. The minimum recommended value is 4.
- * A size of zero (0) is not allowed since a zero-sized array may result in a
- * 32-bit pointer, i.e., using 4 bytes rather than 0.
- *
- * Default value is 800.
- ******************************************************************************/
-#define TRC_CFG_SYMBOL_TABLE_SIZE 800
-
-#if (TRC_CFG_SYMBOL_TABLE_SIZE == 0)
-#error "TRC_CFG_SYMBOL_TABLE_SIZE may not be zero!"
-#endif
-
-/******************************************************************************
- * TRC_CFG_NAME_LEN_TASK, TRC_CFG_NAME_LEN_QUEUE, ...
- *
- * Macros that specify the maximum lengths (number of characters) for names of
- * kernel objects, such as tasks and queues. If longer names are used, they will
- * be truncated when stored in the recorder.
- *****************************************************************************/
-#define TRC_CFG_NAME_LEN_TASK 15
-#define TRC_CFG_NAME_LEN_ISR 15
-#define TRC_CFG_NAME_LEN_QUEUE 15
-#define TRC_CFG_NAME_LEN_SEMAPHORE 15
-#define TRC_CFG_NAME_LEN_MUTEX 15
-#define TRC_CFG_NAME_LEN_TIMER 15
-#define TRC_CFG_NAME_LEN_EVENTGROUP 15
-#define TRC_CFG_NAME_LEN_STREAMBUFFER 15
-#define TRC_CFG_NAME_LEN_MESSAGEBUFFER 15
-
-/******************************************************************************
- *** ADVANCED SETTINGS ********************************************************
- ******************************************************************************
- * The remaining settings are not necessary to modify but allows for optimizing
- * the recorder setup for your specific needs, e.g., to exclude events that you
- * are not interested in, in order to get longer traces.
- *****************************************************************************/
-
-/******************************************************************************
-* TRC_CFG_HEAP_SIZE_BELOW_16M
-*
-* An integer constant that can be used to reduce the buffer usage of memory
-* allocation events (malloc/free). This value should be 1 if the heap size is
-* below 16 MB (2^24 byte), and you can live with reported addresses showing the
-* lower 24 bits only. If 0, you get the full 32-bit addresses.
-*
-* Default value is 0.
-******************************************************************************/
-#define TRC_CFG_HEAP_SIZE_BELOW_16M 0
-
-/******************************************************************************
- * TRC_CFG_USE_IMPLICIT_IFE_RULES
- *
- * Macro which should be defined as either zero (0) or one (1).
- * Default is 1.
- *
- * Tracealyzer groups the events into "instances" based on Instance Finish
- * Events (IFEs), produced either by default rules or calls to the recorder
- * functions vTraceInstanceFinishedNow and vTraceInstanceFinishedNext.
- *
- * If TRC_CFG_USE_IMPLICIT_IFE_RULES is one (1), the default IFE rules is
- * used, resulting in a "typical" grouping of events into instances.
- * If these rules don't give appropriate instances in your case, you can
- * override the default rules using vTraceInstanceFinishedNow/Next for one
- * or several tasks. The default IFE rules are then disabled for those tasks.
- *
- * If TRC_CFG_USE_IMPLICIT_IFE_RULES is zero (0), the implicit IFE rules are
- * disabled globally. You must then call vTraceInstanceFinishedNow or
- * vTraceInstanceFinishedNext to manually group the events into instances,
- * otherwise the tasks will appear a single long instance.
- *
- * The default IFE rules count the following events as "instance finished":
- * - Task delay, delay until
- * - Task suspend
- * - Blocking on "input" operations, i.e., when the task is waiting for the
- * next a message/signal/event. But only if this event is blocking.
- *
- * For details, see trcSnapshotKernelPort.h and look for references to the
- * macro trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED.
- *****************************************************************************/
-#define TRC_CFG_USE_IMPLICIT_IFE_RULES 1
-
-/******************************************************************************
- * TRC_CFG_USE_16BIT_OBJECT_HANDLES
- *
- * Macro which should be defined as either zero (0) or one (1).
- *
- * If set to 0 (zero), the recorder uses 8-bit handles to identify kernel
- * objects such as tasks and queues. This limits the supported number of
- * concurrently active objects to 255 of each type (tasks, queues, mutexes,
- * etc.) Note: 255, not 256, since handle 0 is reserved.
- *
- * If set to 1 (one), the recorder uses 16-bit handles to identify kernel
- * objects such as tasks and queues. This limits the supported number of
- * concurrent objects to 65535 of each type (object class). However, since the
- * object property table is limited to 64 KB, the practical limit is about
- * 3000 objects in total.
- *
- * Default is 0 (8-bit handles)
- *
- * NOTE: An object with handle above 255 will use an extra 4-byte record in
- * the event buffer whenever the object is referenced. Moreover, some internal
- * tables in the recorder gets slightly larger when using 16-bit handles.
- *****************************************************************************/
-#define TRC_CFG_USE_16BIT_OBJECT_HANDLES 0
-
-/******************************************************************************
- * TRC_CFG_USE_TRACE_ASSERT
- *
- * Macro which should be defined as either zero (0) or one (1).
- * Default is 1.
- *
- * If this is one (1), the TRACE_ASSERT macro (used at various locations in the
- * trace recorder) will verify that a relevant condition is true.
- * If the condition is false, prvTraceError() will be called, which stops the
- * recording and stores an error message that is displayed when opening the
- * trace in Tracealyzer.
- *
- * This is used on several places in the recorder code for sanity checks on
- * parameters. Can be switched off to reduce the footprint of the tracing, but
- * we recommend to have it enabled initially.
- *****************************************************************************/
-#define TRC_CFG_USE_TRACE_ASSERT 1
-
-/*******************************************************************************
- * TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER
- *
- * Macro which should be defined as an integer value.
- *
- * Set TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER to 1 to enable the
- * separate user event buffer (UB).
- * In this mode, user events are stored separately from other events,
- * e.g., RTOS events. Thereby you can get a much longer history of
- * user events as they don't need to share the buffer space with more
- * frequent events.
- *
- * The UB is typically used with the snapshot ring-buffer mode, so the
- * recording can continue when the main buffer gets full. And since the
- * main buffer then overwrites the earliest events, Tracealyzer displays
- * "Unknown Actor" instead of task scheduling for periods with UB data only.
- *
- * In UB mode, user events are structured as UB channels, which contains
- * a channel name and a default format string. Register a UB channel using
- * xTraceRegisterUBChannel.
- *
- * Events and data arguments are written using vTraceUBEvent and
- * vTraceUBData. They are designed to provide efficient logging of
- * repeating events, using the same format string within each channel.
- *
- * Examples:
- *
- * traceString chn1 = xTraceRegisterString("Channel 1");
- * traceString fmt1 = xTraceRegisterString("Event!");
- * traceUBChannel UBCh1 = xTraceRegisterUBChannel(chn1, fmt1);
- *
- * traceString chn2 = xTraceRegisterString("Channel 2");
- * traceString fmt2 = xTraceRegisterString("X: %d, Y: %d");
- * traceUBChannel UBCh2 = xTraceRegisterUBChannel(chn2, fmt2);
- *
- * // Result in "[Channel 1] Event!"
- * vTraceUBEvent(UBCh1);
- *
- * // Result in "[Channel 2] X: 23, Y: 19"
- * vTraceUBData(UBCh2, 23, 19);
- *
- * You can also use the other user event functions, like vTracePrintF.
- * as they are then rerouted to the UB instead of the main event buffer.
- * vTracePrintF then looks up the correct UB channel based on the
- * provided channel name and format string, or creates a new UB channel
- * if no match is found. The format string should therefore not contain
- * "random" messages but mainly format specifiers. Random strings should
- * be stored using %s and with the string as an argument.
- *
- * // Creates a new UB channel ("Channel 2", "%Z: %d")
- * vTracePrintF(chn2, "%Z: %d", value1);
- *
- * // Finds the existing UB channel
- * vTracePrintF(chn2, "%Z: %d", value2);
-
- ******************************************************************************/
-#define TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER 0
-
-/*******************************************************************************
- * TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE
- *
- * Macro which should be defined as an integer value.
- *
- * This defines the capacity of the user event buffer (UB), in number of slots.
- * A single user event can use multiple slots, depending on the arguments.
- *
- * Only applicable if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is 1.
- ******************************************************************************/
-#define TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE 200
-
-/*******************************************************************************
- * TRC_CFG_UB_CHANNELS
- *
- * Macro which should be defined as an integer value.
- *
- * This defines the number of User Event Buffer Channels (UB channels).
- * These are used to structure the events when using the separate user
- * event buffer, and contains both a User Event Channel (the name) and
- * a default format string for the channel.
- *
- * Only applicable if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is 1.
- ******************************************************************************/
-#define TRC_CFG_UB_CHANNELS 32
-
-/*******************************************************************************
- * TRC_CFG_ISR_TAILCHAINING_THRESHOLD
- *
- * Macro which should be defined as an integer value.
- *
- * If tracing multiple ISRs, this setting allows for accurate display of the
- * context-switching also in cases when the ISRs execute in direct sequence.
- *
- * vTraceStoreISREnd normally assumes that the ISR returns to the previous
- * context, i.e., a task or a preempted ISR. But if another traced ISR
- * executes in direct sequence, Tracealyzer may incorrectly display a minimal
- * fragment of the previous context in between the ISRs.
- *
- * By using TRC_CFG_ISR_TAILCHAINING_THRESHOLD you can avoid this. This is
- * however a threshold value that must be measured for your specific setup.
- * See http://percepio.com/2014/03/21/isr_tailchaining_threshold/
- *
- * The default setting is 0, meaning "disabled" and that you may get an
- * extra fragments of the previous context in between tail-chained ISRs.
- *
- * Note: This setting has separate definitions in trcSnapshotConfig.h and
- * trcStreamingConfig.h, since it is affected by the recorder mode.
- ******************************************************************************/
-#define TRC_CFG_ISR_TAILCHAINING_THRESHOLD 0
-
-#endif /*TRC_SNAPSHOT_CONFIG_H*/
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcSnapshotConfig.h + * + * Configuration parameters for trace recorder library in snapshot mode. + * Read more at http://percepio.com/2016/10/05/rtos-tracing/ + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_SNAPSHOT_CONFIG_H +#define TRC_SNAPSHOT_CONFIG_H + +#define TRC_SNAPSHOT_MODE_RING_BUFFER (0x01) +#define TRC_SNAPSHOT_MODE_STOP_WHEN_FULL (0x02) + +/****************************************************************************** + * TRC_CFG_SNAPSHOT_MODE + * + * Macro which should be defined as one of: + * - TRC_SNAPSHOT_MODE_RING_BUFFER + * - TRC_SNAPSHOT_MODE_STOP_WHEN_FULL + * Default is TRC_SNAPSHOT_MODE_RING_BUFFER. + * + * With TRC_CFG_SNAPSHOT_MODE set to TRC_SNAPSHOT_MODE_RING_BUFFER, the + * events are stored in a ring buffer, i.e., where the oldest events are + * overwritten when the buffer becomes full. This allows you to get the last + * events leading up to an interesting state, e.g., an error, without having + * to store the whole run since startup. + * + * When TRC_CFG_SNAPSHOT_MODE is TRC_SNAPSHOT_MODE_STOP_WHEN_FULL, the + * recording is stopped when the buffer becomes full. This is useful for + * recording events following a specific state, e.g., the startup sequence. + *****************************************************************************/ +#define TRC_CFG_SNAPSHOT_MODE TRC_SNAPSHOT_MODE_RING_BUFFER + +/******************************************************************************* + * TRC_CFG_EVENT_BUFFER_SIZE + * + * Macro which should be defined as an integer value. + * + * This defines the capacity of the event buffer, i.e., the number of records + * it may store. Most events use one record (4 byte), although some events + * require multiple 4-byte records. You should adjust this to the amount of RAM + * available in the target system. + * + * Default value is 1000, which means that 4000 bytes is allocated for the + * event buffer. + ******************************************************************************/ +#define TRC_CFG_EVENT_BUFFER_SIZE 1000 + +/******************************************************************************* + * TRC_CFG_NTASK, TRC_CFG_NISR, TRC_CFG_NQUEUE, TRC_CFG_NSEMAPHORE... + * + * A group of macros which should be defined as integer values, zero or larger. + * + * These define the capacity of the Object Property Table, i.e., the maximum + * number of objects active at any given point, within each object class (e.g., + * task, queue, semaphore, ...). + * + * If tasks or other objects are deleted in your system, this + * setting does not limit the total amount of objects created, only the number + * of objects that have been successfully created but not yet deleted. + * + * Using too small values will cause vTraceError to be called, which stores an + * error message in the trace that is shown when opening the trace file. The + * error message can also be retrieved using xTraceGetLastError. + * + * It can be wise to start with large values for these constants, + * unless you are very confident on these numbers. Then do a recording and + * check the actual usage by selecting View menu -> Trace Details -> + * Resource Usage -> Object Table. + ******************************************************************************/ +#define TRC_CFG_NTASK 15 +#define TRC_CFG_NISR 5 +#define TRC_CFG_NQUEUE 10 +#define TRC_CFG_NSEMAPHORE 10 +#define TRC_CFG_NMUTEX 10 +#define TRC_CFG_NTIMER 5 +#define TRC_CFG_NEVENTGROUP 5 +#define TRC_CFG_NSTREAMBUFFER 5 +#define TRC_CFG_NMESSAGEBUFFER 5 + +/****************************************************************************** + * TRC_CFG_INCLUDE_FLOAT_SUPPORT + * + * Macro which should be defined as either zero (0) or one (1). + * + * If this is zero (0), the support for logging floating point values in + * vTracePrintF is stripped out, in case floating point values are not used or + * supported by the platform used. + * + * Floating point values are only used in vTracePrintF and its subroutines, to + * allow for storing float (%f) or double (%lf) arguments. + * + * vTracePrintF can be used with integer and string arguments in either case. + * + * Default value is 0. + *****************************************************************************/ +#define TRC_CFG_INCLUDE_FLOAT_SUPPORT 0 + +/******************************************************************************* + * TRC_CFG_SYMBOL_TABLE_SIZE + * + * Macro which should be defined as an integer value. + * + * This defines the capacity of the symbol table, in bytes. This symbol table + * stores User Events labels and names of deleted tasks, queues, or other kernel + * objects. If you don't use User Events or delete any kernel + * objects you set this to a very low value. The minimum recommended value is 4. + * A size of zero (0) is not allowed since a zero-sized array may result in a + * 32-bit pointer, i.e., using 4 bytes rather than 0. + * + * Default value is 800. + ******************************************************************************/ +#define TRC_CFG_SYMBOL_TABLE_SIZE 800 + +#if (TRC_CFG_SYMBOL_TABLE_SIZE == 0) +#error "TRC_CFG_SYMBOL_TABLE_SIZE may not be zero!" +#endif + +/****************************************************************************** + * TRC_CFG_NAME_LEN_TASK, TRC_CFG_NAME_LEN_QUEUE, ... + * + * Macros that specify the maximum lengths (number of characters) for names of + * kernel objects, such as tasks and queues. If longer names are used, they will + * be truncated when stored in the recorder. + *****************************************************************************/ +#define TRC_CFG_NAME_LEN_TASK 15 +#define TRC_CFG_NAME_LEN_ISR 15 +#define TRC_CFG_NAME_LEN_QUEUE 15 +#define TRC_CFG_NAME_LEN_SEMAPHORE 15 +#define TRC_CFG_NAME_LEN_MUTEX 15 +#define TRC_CFG_NAME_LEN_TIMER 15 +#define TRC_CFG_NAME_LEN_EVENTGROUP 15 +#define TRC_CFG_NAME_LEN_STREAMBUFFER 15 +#define TRC_CFG_NAME_LEN_MESSAGEBUFFER 15 + +/****************************************************************************** + *** ADVANCED SETTINGS ******************************************************** + ****************************************************************************** + * The remaining settings are not necessary to modify but allows for optimizing + * the recorder setup for your specific needs, e.g., to exclude events that you + * are not interested in, in order to get longer traces. + *****************************************************************************/ + +/****************************************************************************** +* TRC_CFG_HEAP_SIZE_BELOW_16M +* +* An integer constant that can be used to reduce the buffer usage of memory +* allocation events (malloc/free). This value should be 1 if the heap size is +* below 16 MB (2^24 byte), and you can live with reported addresses showing the +* lower 24 bits only. If 0, you get the full 32-bit addresses. +* +* Default value is 0. +******************************************************************************/ +#define TRC_CFG_HEAP_SIZE_BELOW_16M 0 + +/****************************************************************************** + * TRC_CFG_USE_IMPLICIT_IFE_RULES + * + * Macro which should be defined as either zero (0) or one (1). + * Default is 1. + * + * Tracealyzer groups the events into "instances" based on Instance Finish + * Events (IFEs), produced either by default rules or calls to the recorder + * functions vTraceInstanceFinishedNow and vTraceInstanceFinishedNext. + * + * If TRC_CFG_USE_IMPLICIT_IFE_RULES is one (1), the default IFE rules is + * used, resulting in a "typical" grouping of events into instances. + * If these rules don't give appropriate instances in your case, you can + * override the default rules using vTraceInstanceFinishedNow/Next for one + * or several tasks. The default IFE rules are then disabled for those tasks. + * + * If TRC_CFG_USE_IMPLICIT_IFE_RULES is zero (0), the implicit IFE rules are + * disabled globally. You must then call vTraceInstanceFinishedNow or + * vTraceInstanceFinishedNext to manually group the events into instances, + * otherwise the tasks will appear a single long instance. + * + * The default IFE rules count the following events as "instance finished": + * - Task delay, delay until + * - Task suspend + * - Blocking on "input" operations, i.e., when the task is waiting for the + * next a message/signal/event. But only if this event is blocking. + * + * For details, see trcSnapshotKernelPort.h and look for references to the + * macro trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED. + *****************************************************************************/ +#define TRC_CFG_USE_IMPLICIT_IFE_RULES 1 + +/****************************************************************************** + * TRC_CFG_USE_16BIT_OBJECT_HANDLES + * + * Macro which should be defined as either zero (0) or one (1). + * + * If set to 0 (zero), the recorder uses 8-bit handles to identify kernel + * objects such as tasks and queues. This limits the supported number of + * concurrently active objects to 255 of each type (tasks, queues, mutexes, + * etc.) Note: 255, not 256, since handle 0 is reserved. + * + * If set to 1 (one), the recorder uses 16-bit handles to identify kernel + * objects such as tasks and queues. This limits the supported number of + * concurrent objects to 65535 of each type (object class). However, since the + * object property table is limited to 64 KB, the practical limit is about + * 3000 objects in total. + * + * Default is 0 (8-bit handles) + * + * NOTE: An object with handle above 255 will use an extra 4-byte record in + * the event buffer whenever the object is referenced. Moreover, some internal + * tables in the recorder gets slightly larger when using 16-bit handles. + *****************************************************************************/ +#define TRC_CFG_USE_16BIT_OBJECT_HANDLES 0 + +/****************************************************************************** + * TRC_CFG_USE_TRACE_ASSERT + * + * Macro which should be defined as either zero (0) or one (1). + * Default is 1. + * + * If this is one (1), the TRACE_ASSERT macro (used at various locations in the + * trace recorder) will verify that a relevant condition is true. + * If the condition is false, prvTraceError() will be called, which stops the + * recording and stores an error message that is displayed when opening the + * trace in Tracealyzer. + * + * This is used on several places in the recorder code for sanity checks on + * parameters. Can be switched off to reduce the footprint of the tracing, but + * we recommend to have it enabled initially. + *****************************************************************************/ +#define TRC_CFG_USE_TRACE_ASSERT 1 + +/******************************************************************************* + * TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER + * + * Macro which should be defined as an integer value. + * + * Set TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER to 1 to enable the + * separate user event buffer (UB). + * In this mode, user events are stored separately from other events, + * e.g., RTOS events. Thereby you can get a much longer history of + * user events as they don't need to share the buffer space with more + * frequent events. + * + * The UB is typically used with the snapshot ring-buffer mode, so the + * recording can continue when the main buffer gets full. And since the + * main buffer then overwrites the earliest events, Tracealyzer displays + * "Unknown Actor" instead of task scheduling for periods with UB data only. + * + * In UB mode, user events are structured as UB channels, which contains + * a channel name and a default format string. Register a UB channel using + * xTraceRegisterUBChannel. + * + * Events and data arguments are written using vTraceUBEvent and + * vTraceUBData. They are designed to provide efficient logging of + * repeating events, using the same format string within each channel. + * + * Examples: + * + * traceString chn1 = xTraceRegisterString("Channel 1"); + * traceString fmt1 = xTraceRegisterString("Event!"); + * traceUBChannel UBCh1 = xTraceRegisterUBChannel(chn1, fmt1); + * + * traceString chn2 = xTraceRegisterString("Channel 2"); + * traceString fmt2 = xTraceRegisterString("X: %d, Y: %d"); + * traceUBChannel UBCh2 = xTraceRegisterUBChannel(chn2, fmt2); + * + * // Result in "[Channel 1] Event!" + * vTraceUBEvent(UBCh1); + * + * // Result in "[Channel 2] X: 23, Y: 19" + * vTraceUBData(UBCh2, 23, 19); + * + * You can also use the other user event functions, like vTracePrintF. + * as they are then rerouted to the UB instead of the main event buffer. + * vTracePrintF then looks up the correct UB channel based on the + * provided channel name and format string, or creates a new UB channel + * if no match is found. The format string should therefore not contain + * "random" messages but mainly format specifiers. Random strings should + * be stored using %s and with the string as an argument. + * + * // Creates a new UB channel ("Channel 2", "%Z: %d") + * vTracePrintF(chn2, "%Z: %d", value1); + * + * // Finds the existing UB channel + * vTracePrintF(chn2, "%Z: %d", value2); + + ******************************************************************************/ +#define TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER 0 + +/******************************************************************************* + * TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE + * + * Macro which should be defined as an integer value. + * + * This defines the capacity of the user event buffer (UB), in number of slots. + * A single user event can use multiple slots, depending on the arguments. + * + * Only applicable if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is 1. + ******************************************************************************/ +#define TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE 200 + +/******************************************************************************* + * TRC_CFG_UB_CHANNELS + * + * Macro which should be defined as an integer value. + * + * This defines the number of User Event Buffer Channels (UB channels). + * These are used to structure the events when using the separate user + * event buffer, and contains both a User Event Channel (the name) and + * a default format string for the channel. + * + * Only applicable if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is 1. + ******************************************************************************/ +#define TRC_CFG_UB_CHANNELS 32 + +/******************************************************************************* + * TRC_CFG_ISR_TAILCHAINING_THRESHOLD + * + * Macro which should be defined as an integer value. + * + * If tracing multiple ISRs, this setting allows for accurate display of the + * context-switching also in cases when the ISRs execute in direct sequence. + * + * vTraceStoreISREnd normally assumes that the ISR returns to the previous + * context, i.e., a task or a preempted ISR. But if another traced ISR + * executes in direct sequence, Tracealyzer may incorrectly display a minimal + * fragment of the previous context in between the ISRs. + * + * By using TRC_CFG_ISR_TAILCHAINING_THRESHOLD you can avoid this. This is + * however a threshold value that must be measured for your specific setup. + * See http://percepio.com/2014/03/21/isr_tailchaining_threshold/ + * + * The default setting is 0, meaning "disabled" and that you may get an + * extra fragments of the previous context in between tail-chained ISRs. + * + * Note: This setting has separate definitions in trcSnapshotConfig.h and + * trcStreamingConfig.h, since it is affected by the recorder mode. + ******************************************************************************/ +#define TRC_CFG_ISR_TAILCHAINING_THRESHOLD 0 + +#endif /*TRC_SNAPSHOT_CONFIG_H*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcStreamingConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcStreamingConfig.h index f578f10ec..9ad2ce577 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcStreamingConfig.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcStreamingConfig.h @@ -1,170 +1,144 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.4
- * Percepio AB, www.percepio.com
- *
- * trcStreamingConfig.h
- *
- * Configuration parameters for the trace recorder library in streaming mode.
- * Read more at http://percepio.com/2016/10/05/rtos-tracing/
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_STREAMING_CONFIG_H
-#define TRC_STREAMING_CONFIG_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_SYMBOL_TABLE_SLOTS
- *
- * The maximum number of symbols names that can be stored. This includes:
- * - Task names
- * - Named ISRs (vTraceSetISRProperties)
- * - Named kernel objects (vTraceStoreKernelObjectName)
- * - User event channels (xTraceRegisterString)
- *
- * If this value is too small, not all symbol names will be stored and the
- * trace display will be affected. In that case, there will be warnings
- * (as User Events) from TzCtrl task, that monitors this.
- ******************************************************************************/
-#define TRC_CFG_SYMBOL_TABLE_SLOTS 40
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_SYMBOL_MAX_LENGTH
- *
- * The maximum length of symbol names, including:
- * - Task names
- * - Named ISRs (vTraceSetISRProperties)
- * - Named kernel objects (vTraceStoreKernelObjectName)
- * - User event channel names (xTraceRegisterString)
- *
- * If longer symbol names are used, they will be truncated by the recorder,
- * which will affect the trace display. In that case, there will be warnings
- * (as User Events) from TzCtrl task, that monitors this.
- ******************************************************************************/
-#define TRC_CFG_SYMBOL_MAX_LENGTH 25
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_OBJECT_DATA_SLOTS
- *
- * The maximum number of object data entries (used for task priorities) that can
- * be stored at the same time. Must be sufficient for all tasks, otherwise there
- * will be warnings (as User Events) from TzCtrl task, that monitors this.
- ******************************************************************************/
-#define TRC_CFG_OBJECT_DATA_SLOTS 40
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_CTRL_TASK_STACK_SIZE
- *
- * The stack size of the TzCtrl task, that receive commands.
- * We are aiming to remove this extra task in future versions.
- ******************************************************************************/
-#define TRC_CFG_CTRL_TASK_STACK_SIZE (configMINIMAL_STACK_SIZE * 2)
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_CTRL_TASK_PRIORITY
- *
- * The priority of the TzCtrl task, that receive commands from Tracealyzer.
- * Most stream ports also rely on the TzCtrl task to transmit the data from the
- * internal buffer to the stream interface (all except for the J-Link port).
- * For such ports, make sure the TzCtrl priority is high enough to ensure
- * reliable periodic execution and transfer of the data.
- ******************************************************************************/
-#define TRC_CFG_CTRL_TASK_PRIORITY 1
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_CTRL_TASK_DELAY
- *
- * The delay between every loop of the TzCtrl task. A high delay will reduce the
- * CPU load, but may cause missed events if the TzCtrl task is performing the
- * trace transfer.
- ******************************************************************************/
-#define TRC_CFG_CTRL_TASK_DELAY ((10 * configTICK_RATE_HZ) / 1000)
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT
- *
- * Specifies the number of pages used by the paged event buffer.
- * This may need to be increased if there are a lot of missed events.
- *
- * Note: not used by the J-Link RTT stream port (see trcStreamingPort.h instead)
- ******************************************************************************/
-#define TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT 2
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE
- *
- * Specifies the size of each page in the paged event buffer. This can be tuned
- * to match any internal low-level buffers used by the streaming interface, like
- * the Ethernet MTU (Maximum Transmission Unit).
- *
- * Note: not used by the J-Link RTT stream port (see trcStreamingPort.h instead)
- ******************************************************************************/
-#define TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE 2500
-
-/*******************************************************************************
- * TRC_CFG_ISR_TAILCHAINING_THRESHOLD
- *
- * Macro which should be defined as an integer value.
- *
- * If tracing multiple ISRs, this setting allows for accurate display of the
- * context-switching also in cases when the ISRs execute in direct sequence.
- *
- * vTraceStoreISREnd normally assumes that the ISR returns to the previous
- * context, i.e., a task or a preempted ISR. But if another traced ISR
- * executes in direct sequence, Tracealyzer may incorrectly display a minimal
- * fragment of the previous context in between the ISRs.
- *
- * By using TRC_CFG_ISR_TAILCHAINING_THRESHOLD you can avoid this. This is
- * however a threshold value that must be measured for your specific setup.
- * See http://percepio.com/2014/03/21/isr_tailchaining_threshold/
- *
- * The default setting is 0, meaning "disabled" and that you may get an
- * extra fragments of the previous context in between tail-chained ISRs.
- *
- * Note: This setting has separate definitions in trcSnapshotConfig.h and
- * trcStreamingConfig.h, since it is affected by the recorder mode.
- ******************************************************************************/
-#define TRC_CFG_ISR_TAILCHAINING_THRESHOLD 0
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TRC_STREAMING_CONFIG_H */
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingConfig.h + * + * Configuration parameters for the trace recorder library in streaming mode. + * Read more at http://percepio.com/2016/10/05/rtos-tracing/ + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_STREAMING_CONFIG_H +#define TRC_STREAMING_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Configuration Macro: TRC_CFG_SYMBOL_TABLE_SLOTS + * + * The maximum number of symbols names that can be stored. This includes: + * - Task names + * - Named ISRs (vTraceSetISRProperties) + * - Named kernel objects (vTraceStoreKernelObjectName) + * - User event channels (xTraceRegisterString) + * + * If this value is too small, not all symbol names will be stored and the + * trace display will be affected. In that case, there will be warnings + * (as User Events) from TzCtrl task, that monitors this. + ******************************************************************************/ +#define TRC_CFG_SYMBOL_TABLE_SLOTS 40 + +/******************************************************************************* + * Configuration Macro: TRC_CFG_SYMBOL_MAX_LENGTH + * + * The maximum length of symbol names, including: + * - Task names + * - Named ISRs (vTraceSetISRProperties) + * - Named kernel objects (vTraceStoreKernelObjectName) + * - User event channel names (xTraceRegisterString) + * + * If longer symbol names are used, they will be truncated by the recorder, + * which will affect the trace display. In that case, there will be warnings + * (as User Events) from TzCtrl task, that monitors this. + ******************************************************************************/ +#define TRC_CFG_SYMBOL_MAX_LENGTH 25 + +/******************************************************************************* + * Configuration Macro: TRC_CFG_OBJECT_DATA_SLOTS + * + * The maximum number of object data entries (used for task priorities) that can + * be stored at the same time. Must be sufficient for all tasks, otherwise there + * will be warnings (as User Events) from TzCtrl task, that monitors this. + ******************************************************************************/ +#define TRC_CFG_OBJECT_DATA_SLOTS 40 + +/******************************************************************************* + * Configuration Macro: TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT + * + * Specifies the number of pages used by the paged event buffer. + * This may need to be increased if there are a lot of missed events. + * + * Note: not used by the J-Link RTT stream port (see trcStreamingPort.h instead) + ******************************************************************************/ +#define TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT 10 + +/******************************************************************************* + * Configuration Macro: TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE + * + * Specifies the size of each page in the paged event buffer. This can be tuned + * to match any internal low-level buffers used by the streaming interface, like + * the Ethernet MTU (Maximum Transmission Unit). However, since the currently + * active page can't be transfered, having more but smaller pages is more + * efficient with respect memory usage, than having a few large pages. + * + * Note: not used by the J-Link RTT stream port (see trcStreamingPort.h instead) + ******************************************************************************/ +#define TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE 500 + +/******************************************************************************* + * TRC_CFG_ISR_TAILCHAINING_THRESHOLD + * + * Macro which should be defined as an integer value. + * + * If tracing multiple ISRs, this setting allows for accurate display of the + * context-switching also in cases when the ISRs execute in direct sequence. + * + * vTraceStoreISREnd normally assumes that the ISR returns to the previous + * context, i.e., a task or a preempted ISR. But if another traced ISR + * executes in direct sequence, Tracealyzer may incorrectly display a minimal + * fragment of the previous context in between the ISRs. + * + * By using TRC_CFG_ISR_TAILCHAINING_THRESHOLD you can avoid this. This is + * however a threshold value that must be measured for your specific setup. + * See http://percepio.com/2014/03/21/isr_tailchaining_threshold/ + * + * The default setting is 0, meaning "disabled" and that you may get an + * extra fragments of the previous context in between tail-chained ISRs. + * + * Note: This setting has separate definitions in trcSnapshotConfig.h and + * trcStreamingConfig.h, since it is affected by the recorder mode. + ******************************************************************************/ +#define TRC_CFG_ISR_TAILCHAINING_THRESHOLD 0 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAMING_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/readme.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/readme.txt deleted file mode 100644 index 79b64006d..000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/readme.txt +++ /dev/null @@ -1,152 +0,0 @@ --------------------------------------------------------------------------------
- Tracealyzer for FreeRTOS - Trace Recorder Library v3.1.1
--------------------------------------------------------------------------------
-
-Tracealyzer for FreeRTOS is a sophisticated tool for tracing and visualization
-of FreeRTOS-based systems. Tracealyzer gives an unprecedented insight into the
-runtime behavior, which speeds up debugging, validation and optimization.
-
-To learn more about this, see
-
- - Getting Started (videos etc): http://percepio.com/gettingstarted/tz-freertos/
-
- - User Manual (incl. Recorder API): http://percepio.com/docs/FreeRTOS/manual
-
- - FAQ: http://percepio.com/category/faq/
-
-In case you have any questions, don't hesitate to contact support@percepio.com
-
--------------------------------------------------------------------------------
-
-Changes, v3.1.1 -> v3.1.2
-
-- Fixed two bugs related to User Events, one in vTracePrintF and other in vTracePrint.
-
-- Fixed a build problem related to a single reference of the old FreeRTOS type "xTaskHandle", in trcKernelPort.c.
- Changed to "TaskHandle_t", unless if using an older FreeRTOS kernel or the "compatibility mode".
-
-- Removed traceCREATE_MUTEX hook for FreeRTOS v9 or later (no longer required)
-
-- Updated the User Manual regarding snapshot trace via IAR Embedded Workbench.
-
-- Renamed vTraceGetTraceBuffer to xTraceGetTraceBuffer, since returning a pointer.
-
--------------------------------------------------------------------------------
-
-Changes, v3.1.0 -> v3.1.1
-
-After the major changes in the v3.1.0 trace recorder library, this update
-corrects a number of minor issues. Only minor functional improvements.
-
-- You can now use TRC_ALLOC_CUSTOM_BUFFER to declare a trace buffer on a custom
- location (using linker directives).
- The related function vTraceSetRecorderDataBuffer has been promoted to the
- Common API (previously only supported in snapshot mode, but custom allocation
- is now generally supported also in streaming mode).
-
-- Removed TRC_CFG_USE_LINKER_PRAGMA. No longer necessary thanks to the custom
- allocation mode.
-
-- Added support for timestamping from custom periodic timers, required for
- accurate timestamping on Cortex-M0/M0+ devices when using tickless idle.
- Only for streaming mode so far. See TRC_CUSTOM_TIMER_INCR / DECR.
-
-- ARM Cortex-M port: Made sure the DWT unit is initialized properly, in case
- the debugger doesn't handle this.
-
-- ARM Cortex-M port: Added possibility to use Systick timestamping also on
- Cortex-M3/M4/M7 devices (that otherwise use DWT timestamping by default).
- To use this option, define the macro TRC_CFG_ARM_CM_USE_SYSTICK.
-
-- J-Link streaming: The default RTT buffer has been changed from 0 to 1.
-
-- J-Link streaming: The RTT buffer settings for buffer 1 and higher, are now
- found in trcStreamingPort.h. Note: These settings don't apply to buffer 0.
-
-- vTracePrint has been optimized for better performance in string logging.
-
-- Minor performance improvement related to symbol table transfer in streaming mode.
-
-- Timer names now registered also in streaming mode.
-
-- Timer start and stop event are now traced.
-
-- Implemented support for queue registry (traceQUEUE_REGISTRY_ADD) also for streaming.
-
-- Fixed a bug related to repeated calls of vTraceEnable.
-
-- Fixed a bug where task-switches seemed to occur even though the scheduler was disabled.
-
-- Renamed HARDWARE_PORT_TEXAS_INSTRUMENTS_TMS570_RM48, added prefix TRC.
-
-- Fixed several language issues in the comments and documentation.
-
-- Fixed several minor issues and warnings from different compilers
- (including PowerPC/gcc) and configurations.
-
--------------------------------------------------------------------------------
-
-Changes, v3.0.9 -> v3.1.0
-
-- Merge of previously separated snapshot and streaming recorders into a single
- recorder supporting both streaming and snapshot as different modes.
-
-- New common API for supporting both streaming and snapshot modes.
-
-- New integration guide, see the User Manual.
-
-- Major improvement of API documentation in source files and User Manual.
-
-- New concept of "stream ports", giving a better structure defining streaming
- interfaces, and restructured the J-Link and TCP/IP streaming as stream ports.
-
-- Added a stream port for USB CDC connections, with STM32 as example.
- Since Tracealyzer now can receive serial data on Windows COM ports, this is
- really easy to use.
-
-- Added a warning (#error) for cases where FreeRTOS tickless idle mode is used
- together with timestamping using SysTick or other periodic interrupt timers,
- Tracing with tickless idle requires an independent time source to correctly
- capture the length of the idle periods.
-
-- Major changes in the recorder API. Important examples are:
-
- * Some configuration macros have changed names, e.g. for "hardware port".
- Make sure to remove any old "trcConfig.h" files if upgrading from an
- earlier version!
-
- * Recorder configuration in trcConfig.h has been minimized and now only
- includes the important settings that are independent of recorder mode.
- Advanced settings for each mode are found in trcSnapshotConfig.h and
- trcStreamingConfig.h.
-
- * vTraceEnable replaces Trace_Init and vTraceInitTraceData, as well as
- vTraceStart and uiTraceStart.
-
- * vTraceStop now part of the common API and thereby available also in
- streaming. And since vTraceEnable can start the streaming directly
- you have the option control the tracing from target, e.g., for
- streaming to a device file system.
-
- * vTraceStoreKernelObjectName from old streaming recorder has been replaced
- by vTraceSetQueueName, vTraceSetSemaphoreName, etc.
-
- * vTraceSetISRProperties now returns a "traceHandle" that should be passed as
- parameter to vTraceStoreISRBegin and vTraceStoreISREnd.
-
- * xTraceRegisterString has replaced the old functions xTraceOpenLabel and
- vTraceStoreUserEventChannelName. This now returns a "traceString" for use
- as "channel" parameter in vTracePrintF, and in other places where strings
- are stored.
-
- * Removed vTraceStoreISREndManual and vTraceStoreISREndAuto, use
- vTraceStoreISREnd instead.
-
- * Renamed the functions for saving User Events in a separate buffer:
- - xTraceRegisterChannelFormat -> xTraceRegisterUBChannel
- - vTraceChannelPrintF -> vTraceUBData
- - vTraceChannelUserEvent -> vTraceUBEvent
-
-
--------------------------------------------------------------------------------
-Copyright Percepio AB, 2017.
\ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/Readme-Streamport.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/Readme-Streamport.txt new file mode 100644 index 000000000..8774f20f5 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/Readme-Streamport.txt @@ -0,0 +1,22 @@ +Tracealyzer Stream Port for Amazon FreeRTOS TCP/WIFI +---------------------------------------------------- + +This directory contains a "stream port" for the Tracealyzer recorder library, +i.e., the specific code needed to use a particular interface for streaming a +Tracealyzer RTOS trace. The stream port is defined by a set of macros in +trcStreamingPort.h, found in the "include" directory. + +This particular stream port is for streaming via a TCP socket in Amazon +FreeRTOS (AFR) directly to a host computer on the local network, typically +using Wifi. Read more in trcStreamingPort.h. + +To use this stream port, make sure that include/trcStreamingPort.h is found +by the compiler (i.e., add this folder to your project's include paths) and +add all included source files to your build. Make sure no other versions of +trcStreamingPort.h are included by mistake! + +See also http://percepio.com/2016/10/05/rtos-tracing +and https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming/ + +Percepio AB +www.percepio.com
\ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/include/trcStreamingPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/include/trcStreamingPort.h new file mode 100644 index 000000000..4d4322d92 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/include/trcStreamingPort.h @@ -0,0 +1,161 @@ +/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.c + * + * This stream port provides trace streaming using the Amazon FreeRTOS sockets + * layer and is intended for streaming over Wifi directly to a computer on the + * local Wifi network. + * + * Note that this does NOT use the TLS encryption available in Amazon + * FreeRTOS, due to performance and memory usage concerns. However, it does not + * use any AWS services either, and is intended for your local network only. + * + * This should be started using vTraceEnable(TRC_START) and this call should be + * made AFTER the kernel has started and the Wifi interface is ready. + * + * In the Tracealyzer setting -> "PSF Streaming Settings" make sure that the + * "Target Connection" setting is "TCP (Target Initiated)". + * + * To use this, make sure to start the trace recording in Tracealyzer before + * you start your target system. This ensures that Tracealyzer is ready when + * the target system connects. + * + * And don't forget to enter the IP address of the Tracealyzer host computer + * in trcStreamingPort.h. + * + * NOTES: + * + * 1: The tracing will increase the stack usage of you application, so you + * may want to increase configMINIMAL_STACK_SIZE in your FreeRTOSConfig.h. + * + * 2: To reduce the amount of trace data, we recommend disabling the tracing + * of OS Ticks and memory allocation events. + * See TRC_CFG_INCLUDE_OSTICK_EVENTS in trcConfig.h. + * + * 3: The transmission of trace data is done in the TzCtrl task. To avoid that + * the trace streaming is blocked during the (long) MQTT connection phase, + * make sure the scheduling priority of TzCtrl is higher than the MQTT task. + * Otherwise, if you prefer to run the TzCtrl task at lower priority to avoid + * interfering with your application, wait with the vTraceEnable call until + * after the MQTT connection is established. + * See TRC_CFG_CTRL_TASK_PRIORITY in trcStreamingConfig.h. + * + * 4: The Wifi transmission of trace data often uses FreeRTOS functions, that + * are traced and thus produce additional trace data. This may cause a fast + * increase in trace data rate, that may saturate the trace buffer and cause + * data loss (i.e. incomplete traces). + * To eliminate this effect and reduce the amount of trace data produced, we + * recommend excluding all FreeRTOS objects that are used by Wifi stack. + * This is done using vTraceSetFilterGroup and vTraceSetFilterMask: + * + * // Just before wifi initialization: + * + * // All objects created after this point are assigned to group 15. + * vTraceSetFilterGroup(FilterGroup15); + * + * // Only trace objects assigned to group 0 (the default group). + * vTraceSetFilterMask(FilterGroup0); + * + * // The wifi stack initialization... (creates semaphores etc.) + * if ( eWifi_Connected == prvWifiConnect() ) + * { + * yMainState = eMain_StartApplication; + * + * // When connected, restore the FilterGroup setting to Group 0, so + * // that later created objects are included, like the TzCtrl task + * // created in vTraceEnable. Excluding tasks is not recommended! + * vTraceSetFilterGroup(FilterGroup0); + * + * // Then call vTraceEnable to start the tracing. + * vTraceEnable(TRC_START); + * } + * + * 5: If you still get "red sections" in Tracealyzer (lost data), you need + * to adjust the other settings in trcStreamingConfig.h. + * + * - TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT + * Increase this, as long as you have memory to spare. + * + * - TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE + * Increase this, as long as you have memory to spare. + * But don't exceed the maximum payload size of the Wifi chip, which + * is often limited to 1000-1500 bytes. Some chips crash if you try to + * send to large chunks... + * + * - TRC_CFG_CTRL_TASK_DELAY + * Decrease this to flush the trace buffer more frequently. + * + * See also http://percepio.com/2016/10/05/rtos-tracing + * and https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming/ + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_STREAMING_PORT_H +#define TRC_STREAMING_PORT_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#define HOST_IPADDRESS_0 192 +#define HOST_IPADDRESS_1 168 +#define HOST_IPADDRESS_2 10 +#define HOST_IPADDRESS_3 116 +#define HOST_PORT 12000 + +void prvInitSocket(void); +int32_t prvReadFromSocket(void* ptrData, uint32_t size, int32_t* ptrBytesRead); +int32_t prvWriteToSocket(void* ptrData, uint32_t size, int32_t* ptrBytesWritten); + +#define TRC_STREAM_PORT_INIT() \ + TRC_STREAM_PORT_MALLOC(); \ + prvInitSocket(); + +#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 1 + +#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) prvWriteToSocket(_ptrData, _size, _ptrBytesWritten) + +#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) prvReadFromSocket(_ptrData, _size, _ptrBytesRead) + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAMING_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/trcStreamingPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/trcStreamingPort.c new file mode 100644 index 000000000..1edee04c3 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/trcStreamingPort.c @@ -0,0 +1,191 @@ +/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.c + * + * This stream port provides trace streaming using the Amazon FreeRTOS sockets + * layer and is intended for streaming over Wifi directly to a computer on the + * local Wifi network. + * + * Note that this does NOT use the TLS encryption available in Amazon + * FreeRTOS, due to performance and memory usage concerns. However, it does not + * use any AWS services either, and is intended for your local network only. + * + * This should be started using vTraceEnable(TRC_START) and this call should be + * made AFTER the kernel has started and the Wifi interface is ready. + * + * In the Tracealyzer setting -> "PSF Streaming Settings" make sure that the + * "Target Connection" setting is "TCP (Target Initiated)". + * + * To use this, make sure to start the trace recording in Tracealyzer before + * you start your target system. This ensures that Tracealyzer is ready when + * the target system connects. + * + * And don't forget to enter the IP address of the Tracealyzer host computer + * in trcStreamingPort.h. + * + * NOTES: + * + * 1: The tracing will increase the stack usage of you application, so you + * may want to increase configMINIMAL_STACK_SIZE in your FreeRTOSConfig.h. + * + * 2: To reduce the amount of trace data, we recommend disabling the tracing + * of OS Ticks and memory allocation events. + * See TRC_CFG_INCLUDE_OSTICK_EVENTS in trcConfig.h. + * + * 3: The transmission of trace data is done in the TzCtrl task. To avoid that + * the trace streaming is blocked during the (long) MQTT connection phase, + * make sure the scheduling priority of TzCtrl is higher than the MQTT task. + * Otherwise, if you prefer to run the TzCtrl task at lower priority to avoid + * interfering with your application, wait with the vTraceEnable call until + * after the MQTT connection is established. + * See TRC_CFG_CTRL_TASK_PRIORITY in trcStreamingConfig.h. + * + * 4: The Wifi transmission of trace data often uses FreeRTOS functions, that + * are traced and thus produce additional trace data. This may cause a fast + * increase in trace data rate, that may saturate the trace buffer and cause + * data loss (i.e. incomplete traces). + * To eliminate this effect and reduce the amount of trace data produced, we + * recommend excluding all FreeRTOS objects that are used by Wifi stack. + * This is done using vTraceSetFilterGroup and vTraceSetFilterMask: + * + * // Just before wifi initialization: + * + * // All objects created after this point are assigned to group 15. + * vTraceSetFilterGroup(FilterGroup15); + * + * // Only trace objects assigned to group 0 (the default group). + * vTraceSetFilterMask(FilterGroup0); + * + * // The wifi stack initialization... (creates semaphores etc.) + * if ( eWifi_Connected == prvWifiConnect() ) + * { + * yMainState = eMain_StartApplication; + * + * // When connected, restore the FilterGroup setting to Group 0, so + * // that later created objects are included, like the TzCtrl task + * // created in vTraceEnable. Excluding tasks is not recommended! + * vTraceSetFilterGroup(FilterGroup0); + * + * // Then call vTraceEnable to start the tracing. + * vTraceEnable(TRC_START); + * } + * + * 5: If you still get "red sections" in Tracealyzer (lost data), you need + * to adjust the other settings in trcStreamingConfig.h. + * + * - TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT + * Increase this, as long as you have memory to spare. + * + * - TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE + * Increase this, as long as you have memory to spare. + * But don't exceed the maximum payload size of the Wifi chip, which + * is often limited to 1000-1500 bytes. Some chips crash if you try to + * send to large chunks... + * + * - TRC_CFG_CTRL_TASK_DELAY + * Decrease this to flush the trace buffer more frequently. + * + * See also http://percepio.com/2016/10/05/rtos-tracing + * and https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming/ + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ +#include "trcRecorder.h" + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include "aws_secure_sockets.h" +#include "trcExtensions.h" + +SocketsSockaddr_t addr = {sizeof(SocketsSockaddr_t), SOCKETS_AF_INET, 0, 0}; + +#define IPv4(a,b,c,d) (uint32_t)((d << 24) + (c << 16) + (b << 8) + a) + +Socket_t sock = NULL; + +void prvInitSocket(void) +{ + int32_t status; + + SOCKETS_Init(); + + sock = SOCKETS_Socket(SOCKETS_AF_INET, SOCKETS_SOCK_STREAM, SOCKETS_IPPROTO_TCP); + + configPRINTF( ( "Connecting to %d.%d.%d.%d, port %d\r\n", HOST_IPADDRESS_0, HOST_IPADDRESS_1, HOST_IPADDRESS_2, HOST_IPADDRESS_3, HOST_PORT) ); + + addr.ulAddress = IPv4(HOST_IPADDRESS_0, HOST_IPADDRESS_1, HOST_IPADDRESS_2, HOST_IPADDRESS_3); + addr.usPort = SOCKETS_htons(HOST_PORT); + + status = SOCKETS_Connect(sock, &addr, sizeof( SocketsSockaddr_t ) ); + + if (status != SOCKETS_ERROR_NONE) + { + //prvTraceError(PSF_ERROR_STREAM_PORT_FAIL); + configPRINTF( ( "Failed to connect, status: %d\r\n", status) ); + } + else + { + configPRINTF( ( "Connected.\r\n") ); + } +} + + +int32_t prvWriteToSocket(void* ptrData, uint32_t size, int32_t* ptrBytesWritten) +{ + uint32_t bytesWritten = SOCKETS_Send(sock, ptrData, size, 0); + + if (ptrBytesWritten != NULL) + *ptrBytesWritten = (int32_t)bytesWritten; + + if (bytesWritten != size) + { + return -1; + } + + return 0; +} + +int32_t prvReadFromSocket(void* ptrData, uint32_t size, int32_t* ptrBytesRead) +{ + // Not yet implemented, since not necessary. + return 0; +} + +#endif +#endif diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/Readme-ARM_ITM.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/Readme-ARM_ITM.txt index 0802b5331..be48c6df3 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/Readme-ARM_ITM.txt +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/Readme-ARM_ITM.txt @@ -1,28 +1,32 @@ -Tracealyzer Stream Port for ARM Cortex-M ITM
---------------------------------------------
-2018-05-04
-
-This directory contains a "stream port" for the Tracealyzer recorder library,
-i.e., the specific code needed to use a particular interface for streaming a
-Tracealyzer RTOS trace. The stream port is defined by a set of macros in
-trcStreamingPort.h, found in the "include" directory.
-
-This particular stream port targets ARM's ITM interface, which together with
-a fast debug probe such as a Keil ULINKpro or ULINKplus provides excellent
-performance. This stream port does not use any RAM buffer for the trace, but
-writes the data directly to the ITM registers. This is very fast.
-
-To setup Keil uVision for ITM tracing with a Keil ULINKpro (or ULINKplus),
-see Percepio Application Note PA-021 https://percepio.com/2018/05/04/keil-itm-support/
-
-Learning more:
- - Tracealyzer User Manual (Help -> User Manual)
- - https://percepio.com/gettingstarted
- - Percepio Application Note PA-021 https://percepio.com/2018/05/04/keil-itm-support/
- - About ITM trace, https://percepio.com/2016/06/09/arm-itm/
- - About the recorder and custom streaming, http://percepio.com/2016/10/05/rtos-tracing
-
-For questions, please contact support@percepio.com
-
-Percepio AB
+Tracealyzer Stream Port for ARM Cortex-M ITM +-------------------------------------------- +2018-05-04 + +This directory contains a "stream port" for the Tracealyzer recorder library, +i.e., the specific code needed to use a particular interface for streaming a +Tracealyzer RTOS trace. The stream port is defined by a set of macros in +trcStreamingPort.h, found in the "include" directory. + +This particular stream port targets ARM's ITM interface, which together with +a fast debug probe such as a Keil ULINKpro or ULINKplus provides excellent +performance. This stream port does not use any RAM buffer for the trace, but +writes the data directly to the ITM registers. This is very fast. + +To setup Keil uVision for ITM tracing with a Keil ULINKpro (or ULINKplus), +see Percepio Application Note PA-021, https://percepio.com/2018/05/04/keil-itm-support/ + +To setup IAR Embedded Workbench for ITM tracing with an IAR I-Jet, +see Percepio Application Note PA-023, https://percepio.com/iar + +Learning more: + - Tracealyzer User Manual (Help -> User Manual) + - https://percepio.com/gettingstarted + - Percepio Application Note PA-021 (Keil), https://percepio.com/2018/05/04/keil-itm-support/ + - Percepio Application Note PA-023 (IAR), https://percepio.com/iar + - About ITM trace, https://percepio.com/2016/06/09/arm-itm/ + - About the recorder and custom streaming, http://percepio.com/2016/10/05/rtos-tracing + +For questions, please contact support@percepio.com + +Percepio AB www.percepio.com
\ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/include/trcStreamingPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/include/trcStreamingPort.h index ca20ae753..c14c4e1f9 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/include/trcStreamingPort.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/include/trcStreamingPort.h @@ -1,91 +1,137 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcStreamingPort.h
- *
- * The interface definitions for trace streaming ("stream ports").
- * This "stream port" sets up the recorder to use ARM ITM as streaming channel.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_STREAMING_PORT_H
-#define TRC_STREAMING_PORT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-int32_t itm_write(void* ptrData, uint32_t size, int32_t* ptrBytesWritten);
-int32_t read_from_host(void* ptrData, uint32_t size, int32_t* ptrBytesRead);
-
-/*******************************************************************************
- * TRC_CFG_ITM_PORT
- *
- * Possible values: 0 - 31
- *
- * What ITM port to use for the ITM software events. Make sure the IDE is
- * configured for the same channel.
- *
- * Default: 1 (0 is typically terminal output and 31 is used by Keil)
- *
- ******************************************************************************/
-#define TRC_CFG_ITM_PORT 1
-
-#if (TRC_CFG_ITM_PORT < 0) || (TRC_CFG_ITM_PORT > 31)
-#error "Bad ITM port selected."
-#endif
-
-// Not used for ITM - no RAM buffer...
-#define TRC_STREAM_PORT_ALLOCATE_FIELDS()
-
-// Not used for ITM - assume the IDE configures the ITM setup
-#define TRC_STREAM_PORT_INIT()
-
-/* Important for the ITM port - no RAM buffer, direct writes. In most other ports this can be skipped (default is 1) */
-#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 0
-
-#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) itm_write(_ptrData, _size, _ptrBytesWritten)
-
-#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) read_from_host(_ptrData, _size, _ptrBytesRead)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TRC_STREAMING_PORT_H */
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.h + * + * The interface definitions for trace streaming ("stream ports"). + * This "stream port" sets up the recorder to use ARM ITM as streaming channel. + * + * To setup Keil uVision for ITM tracing with a Keil ULINKpro (or ULINKplus), + * see Percepio Application Note PA-021, available at + * https://percepio.com/2018/05/04/keil-itm-support/ + * + * To setup IAR Embedded Workbench for ITM tracing with an IAR I-Jet, + * see Percepio Application Note PA-023, https://percepio.com/iar + * + * NOTE: This stream port may block the application in case the ITM port + * is not ready for more data (the TPIU FIFO has become full). This is + * necessary to avoid data loss, as the TPIU FIFO is often quite small. + * + * --- Direct vs. Indirect ITM streaming --- + * Direct streaming: By default, this stream port writes directly to the ITM + * register mode without any RAM buffer. This assumes you have a fast debug + * probe, like aKeil ULINKpro or IAR I-Jet, to avoid excessive blocking. + * In case the ITM blocking appears to disturb your application, make sure your + * debugger is configured for maximum performance, as described in the above + * Application Nodes. + * + * Indirect streaming: If direct streaming gives too much overhead, you may + * instead try indirect ITM streaming. This is done by enabling the internal + * RAM buffer, like below. This reconfigures the recorder to store the events + * in the internal RAM buffer instead of writing them directly to the ITM port. + * + * Set TRC_STREAM_PORT_USE_INTERNAL_BUFFER to 1 to use the indirect mode. + * + * This increases RAM usage but eliminates peaks in the trace data rate. + * Moreover, the ITM writes are then performed in a separate task (TzCtrl). + * You find relevant settings (buffer size etc.) in trcStreamingConfig.h. + * + * See also https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming + * + * --- One-way vs. Two-way Communication --- + * The ITM port only provides one-way communication, from target to host. + * This is sufficient if you start the tracing from the target application, + * using vTraceEnable(TRC_START). Just make sure to start the Tracealyzer + * recording before you start the target system. + * + * In case you prefer to interactively start and stop the tracing from the host + * computer, you need two-way communication to send commands to the recorder. + * This is possible by writing such "start" and "stop" commands to a special + * buffer, monitored by the recorder library, using the debugger IDE. + * See trcStreamingPort.c and also the example macro for Keil uVision + * (Keil-uVision-Tracealyzer-ITM-Exporter.ini). + * + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_STREAMING_PORT_H +#define TRC_STREAMING_PORT_H + +#ifdef __cplusplus +extern "C" { +#endif + + +int32_t itm_write(void* ptrData, uint32_t size, int32_t* ptrBytesWritten); +int32_t read_from_host(void* ptrData, uint32_t size, int32_t* ptrBytesRead); + +/******************************************************************************* + * TRC_CFG_ITM_PORT + * + * Possible values: 0 - 31 + * + * What ITM port to use for the ITM software events. Make sure the IDE is + * configured for the same channel. + * + * Default: 1 (0 is typically terminal output and 31 is used by Keil) + * + ******************************************************************************/ +#define TRC_CFG_ITM_PORT 1 + +#if (TRC_CFG_ITM_PORT < 0) || (TRC_CFG_ITM_PORT > 31) +#error "Bad ITM port selected." +#endif + +// Not used for ITM - no RAM buffer... +#define TRC_STREAM_PORT_ALLOCATE_FIELDS() + +// Not used for ITM - assume the IDE configures the ITM setup +#define TRC_STREAM_PORT_INIT() + +/* Important for the ITM port - no RAM buffer, direct writes. In most other ports this can be skipped (default is 1) */ +#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 0 + +#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) itm_write(_ptrData, _size, _ptrBytesWritten) + +#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) read_from_host(_ptrData, _size, _ptrBytesRead) + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAMING_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/trcStreamingPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/trcStreamingPort.c index 0d36b4ab3..4b51d7f0e 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/trcStreamingPort.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/trcStreamingPort.c @@ -1,71 +1,169 @@ -
-#include "trcRecorder.h"
-
-#if (TRC_USE_TRACEALYZER_RECORDER == 1)
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-
-static void itm_write_32(uint32_t data);
-
-volatile int32_t tz_host_command_bytes_to_read = 0; // This is set by the Tracealyzer host application (to the number of bytes written), after having written to tz_host_commands. Set to zero by the read function after the message in tz_host_commands has been read.
-volatile char tz_host_command_data[32];
-
-/* This reads "command" data from a RAM buffer, written by a host macro in the debugger */
-int32_t read_from_host(void* ptrData, uint32_t size, int32_t* ptrBytesRead)
-{
- if ( tz_host_command_bytes_to_read > 0)
- {
- int i;
- uint8_t * bytesBuffer = (uint8_t*) ptrData;
-
- if (ptrBytesRead != NULL)
- *ptrBytesRead = (int32_t)tz_host_command_bytes_to_read;
-
- if (tz_host_command_bytes_to_read != size)
- {
- return -1;
- }
-
- for (i=0; i < tz_host_command_bytes_to_read; i++)
- {
- bytesBuffer[i] = tz_host_command_data[i];
- }
-
- tz_host_command_bytes_to_read = 0;
- }
-
- return 0;
-}
-
-static void itm_write_32(uint32_t data)
-{
- if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) && // Trace enabled
- (ITM->TCR & ITM_TCR_ITMENA_Msk) && // ITM enabled
- (ITM->TER & (1UL << TRC_CFG_ITM_PORT))) // ITM port enabled
- {
- while (ITM->PORT[TRC_CFG_ITM_PORT].u32 == 0); // Block until room in ITM FIFO - This stream port is always in "blocking mode", since intended for high-speed ITM!
- ITM->PORT[TRC_CFG_ITM_PORT].u32 = data; // Write the data
- }
-}
-
-/* This is assumed to execute from within the recorder, with interrupts disabled */
-int32_t itm_write(void* ptrData, uint32_t size, int32_t* ptrBytesWritten)
-{
- uint32_t bytesWritten = 0;
- uint32_t* ptr32 = (uint32_t*)ptrData;
-
- if (size % 4 != 0) return -2;
-
- while(bytesWritten < size)
- {
- itm_write_32(*ptr32);
- ptr32++;
- bytesWritten += 4;
- }
-
- *ptrBytesWritten = bytesWritten;
-
- return 0;
-}
-
-#endif
-#endif
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.c + * + * Supporting functions for trace streaming, used by the "stream ports" + * for reading and writing data to the interface. + * Existing ports can easily be modified to fit another setup, e.g., a + * different TCP/IP stack, or to define your own stream port. + * + * This stream port is for ITM streaming on Arm Cortex-M devices. + * + * To setup Keil uVision for ITM tracing with a Keil ULINKpro (or ULINKplus), + * see Percepio Application Note PA-021, available at + * https://percepio.com/2018/05/04/keil-itm-support/ + * + * To setup IAR Embedded Workbench for ITM tracing with an IAR I-Jet, + * see Percepio Application Note PA-023, https://percepio.com/iar + * + * NOTE: This stream port may block the application in case the ITM port + * is not ready for more data (the TPIU FIFO has become full). This is + * necessary to avoid data loss, as the TPIU FIFO is often quite small. + * + * --- Direct vs. Indirect ITM streaming --- + * Direct streaming: By default, this stream port writes directly to the ITM + * register mode without any RAM buffer. This assumes you have a fast debug + * probe, like aKeil ULINKpro or IAR I-Jet, to avoid excessive blocking. + * In case the ITM blocking appears to disturb your application, make sure your + * debugger is configured for maximum performance, as described in the above + * Application Nodes. + * + * Indirect streaming: If direct streaming gives too much overhead, you may + * instead try indirect ITM streaming. This is done by enabling the internal + * RAM buffer, like below. This reconfigures the recorder to store the events + * in the internal RAM buffer instead of writing them directly to the ITM port. + * + * Set TRC_STREAM_PORT_USE_INTERNAL_BUFFER to 1 to use the indirect mode. + * + * This increases RAM usage but eliminates peaks in the trace data rate. + * Moreover, the ITM writes are then performed in a separate task (TzCtrl). + * You find relevant settings (buffer size etc.) in trcStreamingConfig.h. + * + * See also https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming + * + * --- One-way vs. Two-way Communication --- + * The ITM port only provides one-way communication, from target to host. + * This is sufficient if you start the tracing from the target application, + * using vTraceEnable(TRC_START). Just make sure to start the Tracealyzer + * recording before you start the target system. + * + * In case you prefer to interactively start and stop the tracing from the host + * computer, you need two-way communication to send commands to the recorder. + * This is possible by writing such "start" and "stop" commands to a special + * buffer, monitored by the recorder library, using the debugger IDE. + * See trcStreamingPort.c and also the example macro for Keil uVision + * (Keil-uVision-Tracealyzer-ITM-Exporter.ini). + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#include "trcRecorder.h" + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +static void itm_write_32(uint32_t data); + +/* These variables are used for reading commands from the host, using read_from_host(). + * This is not required if using vTraceEnable(TRC_START). + * A debugger IDE may write to these functions using a macro. + * An example for Keil is included (Keil-uVision-Tracealyzer-ITM-Exporter.ini). */ + +volatile int32_t tz_host_command_bytes_to_read = 0; +volatile char tz_host_command_data[32]; + +/* This reads "command" data from a RAM buffer, written by a host macro in the debugger */ +int32_t read_from_host(void* ptrData, uint32_t size, int32_t* ptrBytesRead) +{ + if ( tz_host_command_bytes_to_read > 0) + { + int i; + uint8_t * bytesBuffer = (uint8_t*) ptrData; + + if (ptrBytesRead != NULL) + *ptrBytesRead = (int32_t)tz_host_command_bytes_to_read; + + if (tz_host_command_bytes_to_read != size) + { + return -1; + } + + for (i=0; i < tz_host_command_bytes_to_read; i++) + { + bytesBuffer[i] = tz_host_command_data[i]; + } + + tz_host_command_bytes_to_read = 0; + } + + return 0; +} + +static void itm_write_32(uint32_t data) +{ + if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) && // Trace enabled + (ITM->TCR & ITM_TCR_ITMENA_Msk) && // ITM enabled + (ITM->TER & (1UL << TRC_CFG_ITM_PORT))) // ITM port enabled + { + while (ITM->PORT[TRC_CFG_ITM_PORT].u32 == 0); // Block until room in ITM FIFO - This stream port is always in "blocking mode", since intended for high-speed ITM! + ITM->PORT[TRC_CFG_ITM_PORT].u32 = data; // Write the data + } +} + +/* This is assumed to execute from within the recorder, with interrupts disabled */ +int32_t itm_write(void* ptrData, uint32_t size, int32_t* ptrBytesWritten) +{ + uint32_t bytesWritten = 0; + uint32_t* ptr32 = (uint32_t*)ptrData; + + if (size % 4 != 0) return -2; + + while(bytesWritten < size) + { + itm_write_32(*ptr32); + ptr32++; + bytesWritten += 4; + } + + *ptrBytesWritten = bytesWritten; + + return 0; +} + +#endif +#endif diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/Readme-Streamport.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/Readme-Streamport.txt index afc5a0951..c88517ef1 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/Readme-Streamport.txt +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/Readme-Streamport.txt @@ -1,19 +1,19 @@ -Tracealyzer Stream Port for Files
--------------------------------------------------
-
-This directory contains a "stream port" for the Tracealyzer recorder library,
-i.e., the specific code needed to use a particular interface for streaming a
-Tracealyzer RTOS trace. The stream port is defined by a set of macros in
-trcStreamingPort.h, found in the "include" directory.
-
-This particular stream port is for streaming to a file via stdio.h (fwrite).
-
-To use this stream port, make sure that include/trcStreamingPort.h is found
-by the compiler (i.e., add this folder to your project's include paths) and
-add all included source files to your build. Make sure no other versions of
-trcStreamingPort.h are included by mistake!
-
-See also http://percepio.com/2016/10/05/rtos-tracing.
-
-Percepio AB
+Tracealyzer Stream Port for Files +------------------------------------------------- + +This directory contains a "stream port" for the Tracealyzer recorder library, +i.e., the specific code needed to use a particular interface for streaming a +Tracealyzer RTOS trace. The stream port is defined by a set of macros in +trcStreamingPort.h, found in the "include" directory. + +This particular stream port is for streaming to a file via stdio.h (fwrite). + +To use this stream port, make sure that include/trcStreamingPort.h is found +by the compiler (i.e., add this folder to your project's include paths) and +add all included source files to your build. Make sure no other versions of +trcStreamingPort.h are included by mistake! + +See also http://percepio.com/2016/10/05/rtos-tracing. + +Percepio AB www.percepio.com
\ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/include/trcStreamingPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/include/trcStreamingPort.h index 2897b7ce2..0deb9ad1c 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/include/trcStreamingPort.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/include/trcStreamingPort.h @@ -1,87 +1,87 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcStreamingPort.h
- *
- * The interface definitions for trace streaming ("stream ports").
- * This "stream port" sets up the recorder to stream the trace to file.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_STREAMING_PORT_H
-#define TRC_STREAMING_PORT_H
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int32_t writeToFile(void* data, uint32_t size, int32_t *ptrBytesWritten);
-
-void closeFile(void);
-
-void openFile(char* fileName);
-
-/* This define will determine whether to use the internal PagedEventBuffer or not.
-If file writing creates additional trace events (i.e. it uses semaphores or mutexes),
-then the paged event buffer must be enabled to avoid infinite recursion. */
-#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 1
-
-#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) 0 /* Does not read commands from Tz (yet) */
-
-#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) writeToFile(_ptrData, _size, _ptrBytesSent)
-
-#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC)
-#define TRC_STREAM_PORT_MALLOC() \
- _TzTraceData = TRC_PORT_MALLOC((TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE));
-extern char* _TzTraceData;
-#else
-#define TRC_STREAM_PORT_MALLOC() /* Custom or static allocation. Not used. */
-#endif
-#define TRC_STREAM_PORT_INIT() \
- TRC_STREAM_PORT_MALLOC(); \
- openFile("trace.psf")
-
-#define TRC_STREAM_PORT_ON_TRACE_END() closeFile()
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TRC_STREAMING_PORT_H */
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.h + * + * The interface definitions for trace streaming ("stream ports"). + * This "stream port" sets up the recorder to stream the trace to file. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_STREAMING_PORT_H +#define TRC_STREAMING_PORT_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t writeToFile(void* data, uint32_t size, int32_t *ptrBytesWritten); + +void closeFile(void); + +void openFile(char* fileName); + +/* This define will determine whether to use the internal PagedEventBuffer or not. +If file writing creates additional trace events (i.e. it uses semaphores or mutexes), +then the paged event buffer must be enabled to avoid infinite recursion. */ +#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 1 + +#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) 0 /* Does not read commands from Tz (yet) */ + +#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) writeToFile(_ptrData, _size, _ptrBytesSent) + +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC) +#define TRC_STREAM_PORT_MALLOC() \ + _TzTraceData = TRC_PORT_MALLOC((TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)); +extern char* _TzTraceData; +#else +#define TRC_STREAM_PORT_MALLOC() /* Custom or static allocation. Not used. */ +#endif +#define TRC_STREAM_PORT_INIT() \ + TRC_STREAM_PORT_MALLOC(); \ + openFile("trace.psf") + +#define TRC_STREAM_PORT_ON_TRACE_END() closeFile() + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAMING_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c index a019791cd..03a5a9a6f 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c @@ -1,103 +1,103 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcStreamingPort.c
- *
- * Supporting functions for trace streaming, used by the "stream ports"
- * for reading and writing data to the interface.
- * Existing ports can easily be modified to fit another setup, e.g., a
- * different TCP/IP stack, or to define your own stream port.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#include "trcRecorder.h"
-
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-#if (TRC_USE_TRACEALYZER_RECORDER == 1)
-
-FILE* traceFile = NULL;
-
-void openFile(char* fileName)
-{
- if (traceFile == NULL)
- {
- errno_t err = fopen_s(&traceFile, fileName, "wb");
- if (err != 0)
- {
- printf("Could not open trace file, error code %d.\n", err);
- exit(-1);
- }
- else {
- printf("Trace file created.\n");
- }
- }
-}
-
-int32_t writeToFile(void* data, uint32_t size, int32_t *ptrBytesWritten)
-{
- int32_t written = 0;
- if (traceFile != NULL)
- {
- written = fwrite(data, 1, size, traceFile);
- }
- else
- {
- written = 0;
- }
-
- if (ptrBytesWritten != 0)
- *ptrBytesWritten = written;
-
- if ((int32_t)size == written)
- return 0;
- else
- return -1;
-}
-
-void closeFile(void)
-{
- if (traceFile != NULL)
- {
- fclose(traceFile);
- traceFile = NULL;
- printf("Trace file closed.\n");
- }
-}
-
-#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
-#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.c + * + * Supporting functions for trace streaming, used by the "stream ports" + * for reading and writing data to the interface. + * Existing ports can easily be modified to fit another setup, e.g., a + * different TCP/IP stack, or to define your own stream port. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#include "trcRecorder.h" + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +FILE* traceFile = NULL; + +void openFile(char* fileName) +{ + if (traceFile == NULL) + { + errno_t err = fopen_s(&traceFile, fileName, "wb"); + if (err != 0) + { + printf("Could not open trace file, error code %d.\n", err); + exit(-1); + } + else { + printf("Trace file created.\n"); + } + } +} + +int32_t writeToFile(void* data, uint32_t size, int32_t *ptrBytesWritten) +{ + int32_t written = 0; + if (traceFile != NULL) + { + written = fwrite(data, 1, size, traceFile); + } + else + { + written = 0; + } + + if (ptrBytesWritten != 0) + *ptrBytesWritten = written; + + if ((int32_t)size == written) + return 0; + else + return -1; +} + +void closeFile(void) +{ + if (traceFile != NULL) + { + fclose(traceFile); + traceFile = NULL; + printf("Trace file closed.\n"); + } +} + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/Readme-Streamport.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/Readme-Streamport.txt index cae5e8ecc..0dcd1591e 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/Readme-Streamport.txt +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/Readme-Streamport.txt @@ -1,22 +1,22 @@ -Tracealyzer Stream Port for SEGGER J-Link
------------------------------------------
-
-This directory contains a "stream port" for the Tracealyzer recorder library,
-i.e., the specific code needed to use a particular interface for streaming a
-Tracealyzer RTOS trace. The stream port is defined by a set of macros in
-trcStreamingPort.h, found in the "include" directory.
-
-This particular stream port targets SEGGER J-Link debug probes, using the RTT
-interface provided by SEGGER.
-
-To use this stream port, make sure that include/trcStreamingPort.h is found
-by the compiler (i.e., add this folder to your project's include paths) and
-add all included source files to your build. Make sure no other versions of
-trcStreamingPort.h are included by mistake!
-
-Note that this stream port also contains SEGGER's RTT driver.
-
-See also http://percepio.com/2016/10/05/rtos-tracing.
-
-Percepio AB
+Tracealyzer Stream Port for SEGGER J-Link +----------------------------------------- + +This directory contains a "stream port" for the Tracealyzer recorder library, +i.e., the specific code needed to use a particular interface for streaming a +Tracealyzer RTOS trace. The stream port is defined by a set of macros in +trcStreamingPort.h, found in the "include" directory. + +This particular stream port targets SEGGER J-Link debug probes, using the RTT +interface provided by SEGGER. + +To use this stream port, make sure that include/trcStreamingPort.h is found +by the compiler (i.e., add this folder to your project's include paths) and +add all included source files to your build. Make sure no other versions of +trcStreamingPort.h are included by mistake! + +Note that this stream port also contains SEGGER's RTT driver. + +See also http://percepio.com/2016/10/05/rtos-tracing. + +Percepio AB www.percepio.com
\ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/SEGGER_RTT_Conf.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/SEGGER_RTT_Conf.h index 4f7f4cc3c..4bb1fdb5a 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/SEGGER_RTT_Conf.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/SEGGER_RTT_Conf.h @@ -78,6 +78,10 @@ Revision: $Rev: 3892 $ #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0)
+// This can be used to place the RTT control block in the right memory range, if no found automatically.
+// This example is for NXP LPC54018, needs to be adapted for each MCU family.
+//#define SEGGER_RTT_SECTION ".data.$RAM2"
+
//
// Target is not allowed to perform other RTT operations while string still has not been stored completely.
// Otherwise we would probably end up with a mixed string in the buffer.
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/trcStreamingPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/trcStreamingPort.h index b1074b424..6ad22d507 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/trcStreamingPort.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/trcStreamingPort.h @@ -1,196 +1,196 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcStreamingPort.h
- *
- * The interface definitions for trace streaming ("stream ports").
- * This "stream port" sets up the recorder to use SEGGER RTT as streaming channel.
- *
- * Note that this stream port is more complex than the typical case, since
- * the J-Link interface uses a separate RAM buffer in SEGGER_RTT.c, instead
- * of the default buffer included in the recorder core. The other stream ports
- * offer more typical examples of how to define a custom streaming interface.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_STREAMING_PORT_H
-#define TRC_STREAMING_PORT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_RTT_BUFFER_SIZE_UP
- *
- * Defines the size of the "up" RTT buffer (target -> host) to use for writing
- * the trace data, for RTT buffer 1 or higher.
- *
- * This setting is ignored for RTT buffer 0, which can't be reconfigured
- * in runtime and therefore hard-coded to use the defines in SEGGER_RTT_Conf.h.
- *
- * Default buffer size for Tracealyzer is 5000 bytes.
- *
- * If you have a stand-alone J-Link probe, the can be decreased to around 1 KB.
- * But integrated J-Link OB interfaces are slower and needs about 5-10 KB,
- * depending on the amount of data produced.
- ******************************************************************************/
-#define TRC_CFG_RTT_BUFFER_SIZE_UP 5000
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_RTT_BUFFER_SIZE_DOWN
- *
- * Defines the size of the "down" RTT buffer (host -> target) to use for reading
- * commands from Tracealyzer, for RTT buffer 1 or higher.
- *
- * Default buffer size for Tracealyzer is 32 bytes.
- *
- * This setting is ignored for RTT buffer 0, which can't be reconfigured
- * in runtime and therefore hard-coded to use the defines in SEGGER_RTT_Conf.h.
- ******************************************************************************/
-#define TRC_CFG_RTT_BUFFER_SIZE_DOWN 32
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_RTT_UP_BUFFER_INDEX
- *
- * Defines the RTT buffer to use for writing the trace data. Make sure that
- * the PC application has the same setting (File->Settings).
- *
- * Default: 1
- *
- * We don't recommend using RTT buffer 0, since mainly intended for terminals.
- * If you prefer to use buffer 0, it must be configured in SEGGER_RTT_Conf.h.
- ******************************************************************************/
-#define TRC_CFG_RTT_UP_BUFFER_INDEX 1
-
-/*******************************************************************************
- * Configuration Macro: TRC_CFG_RTT_DOWN_BUFFER_INDEX
- *
- * Defines the RTT buffer to use for reading the trace data. Make sure that
- * the PC application has the same setting (File->Settings).
- *
- * Default: 1
- *
- * We don't recommend using RTT buffer 0, since mainly intended for terminals.
- * If you prefer to use buffer 0, it must be configured in SEGGER_RTT_Conf.h.
- ******************************************************************************/
-#define TRC_CFG_RTT_DOWN_BUFFER_INDEX 1
-
-/*******************************************************************************
- * TRC_CFG_RTT_MODE
- * This stream port for J-Link streaming relies on SEGGER RTT, that contains an
- * internal RAM buffer read by the J-Link probes during execution.
- *
- * Possible values:
- * - SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
- * - SEGGER_RTT_MODE_NO_BLOCK_SKIP (default)
- *
- * Using SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL ensure that you get a
- * complete and valid trace. This may however cause blocking if your streaming
- * interface isn't fast enough, which may disturb the real-time behavior.
- *
- * We therefore recommend SEGGER_RTT_MODE_NO_BLOCK_SKIP. In this mode,
- * Tracealyzer will report lost events if the transfer is not
- * fast enough. In that case, try increasing the size of the "up buffer".
- ******************************************************************************/
-#define TRC_CFG_RTT_MODE SEGGER_RTT_MODE_NO_BLOCK_SKIP
-
-#include "SEGGER_RTT_Conf.h"
-#include "SEGGER_RTT.h"
-
-#if (TRC_CFG_RTT_UP_BUFFER_INDEX >= SEGGER_RTT_MAX_NUM_UP_BUFFERS)
-#error "TRC_CFG_RTT_UP_BUFFER_INDEX must be smaller than SEGGER_RTT_MAX_NUM_UP_BUFFERS"
-#endif
-
-#if (TRC_CFG_RTT_DOWN_BUFFER_INDEX >= SEGGER_RTT_MAX_NUM_DOWN_BUFFERS)
-#error "TRC_CFG_RTT_DOWN_BUFFER_INDEX must be smaller than SEGGER_RTT_MAX_NUM_DOWN_BUFFERS"
-#endif
-
-/* If index is defined as 0, the internal RTT buffers will be used instead of this. */
-#if TRC_CFG_RTT_UP_BUFFER_INDEX == 0
-#define TRC_RTT_ALLOC_UP() static char* _TzTraceData = NULL; /* Not actually used. Ignore allocation method. */
-#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
-#else
-#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC
-#define TRC_RTT_ALLOC_UP() char _TzTraceData[TRC_CFG_RTT_BUFFER_SIZE_UP]; /* Static allocation */
-#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */
-#endif
-#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC
-#define TRC_RTT_ALLOC_UP() char* _TzTraceData = NULL; /* Dynamic allocation */
-#define TRC_STREAM_PORT_MALLOC() _TzTraceData = TRC_PORT_MALLOC(TRC_CFG_RTT_BUFFER_SIZE_UP);
-#endif
-#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM
-#define TRC_RTT_ALLOC_UP() char* _TzTraceData = NULL; /* Custom allocation, user needs to call vTraceSetRecorderDataBuffer before vTraceEnable, to assign this */
-#define TRC_STREAM_PORT_MALLOC() /* Not used in custom mode */
-#endif
-#endif
-
-/* Down-buffer. If index is defined as 0, the internal RTT buffers will be used instead of this. */ \
-#if TRC_CFG_RTT_DOWN_BUFFER_INDEX == 0
-#define TRC_RTT_ALLOC_DOWN() static char* _TzCtrlData = NULL; /* Not actually used. Ignore allocation method. */
-#else
-#define TRC_RTT_ALLOC_DOWN() static char _TzCtrlData[TRC_CFG_RTT_BUFFER_SIZE_DOWN]; /* Always static allocation, since usually small. */
-#endif
-
-#define TRC_STREAM_PORT_ALLOCATE_FIELDS() \
- TRC_RTT_ALLOC_UP() /* Macro that will result in proper UP buffer allocation */ \
- TRC_RTT_ALLOC_DOWN() /* Macro that will result in proper DOWN buffer allocation */
-
-int32_t readFromRTT(void* ptrData, uint32_t size, int32_t* ptrBytesRead);
-
-int32_t writeToRTT(void* ptrData, uint32_t size, int32_t* ptrBytesWritten);
-
-
-#define TRC_STREAM_PORT_INIT() \
- TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */ \
- SEGGER_RTT_ConfigUpBuffer(TRC_CFG_RTT_UP_BUFFER_INDEX, "TzData", _TzTraceData, TRC_CFG_RTT_BUFFER_SIZE_UP, TRC_CFG_RTT_MODE ); \
- SEGGER_RTT_ConfigDownBuffer(TRC_CFG_RTT_DOWN_BUFFER_INDEX, "TzCtrl", _TzCtrlData, TRC_CFG_RTT_BUFFER_SIZE_DOWN, TRC_CFG_RTT_MODE);
-
-/* Important for the J-Link port, in most other ports this can be skipped (default is 1) */
-#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 0
-
-#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) writeToRTT(_ptrData, _size, _ptrBytesWritten)
-
-#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) readFromRTT(_ptrData, _size, _ptrBytesRead)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TRC_STREAMING_PORT_H */
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.h + * + * The interface definitions for trace streaming ("stream ports"). + * This "stream port" sets up the recorder to use SEGGER RTT as streaming channel. + * + * Note that this stream port is more complex than the typical case, since + * the J-Link interface uses a separate RAM buffer in SEGGER_RTT.c, instead + * of the default buffer included in the recorder core. The other stream ports + * offer more typical examples of how to define a custom streaming interface. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_STREAMING_PORT_H +#define TRC_STREAMING_PORT_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/******************************************************************************* + * Configuration Macro: TRC_CFG_RTT_BUFFER_SIZE_UP + * + * Defines the size of the "up" RTT buffer (target -> host) to use for writing + * the trace data, for RTT buffer 1 or higher. + * + * This setting is ignored for RTT buffer 0, which can't be reconfigured + * in runtime and therefore hard-coded to use the defines in SEGGER_RTT_Conf.h. + * + * Default buffer size for Tracealyzer is 5000 bytes. + * + * If you have a stand-alone J-Link probe, the can be decreased to around 1 KB. + * But integrated J-Link OB interfaces are slower and needs about 5-10 KB, + * depending on the amount of data produced. + ******************************************************************************/ +#define TRC_CFG_RTT_BUFFER_SIZE_UP 5000 + +/******************************************************************************* + * Configuration Macro: TRC_CFG_RTT_BUFFER_SIZE_DOWN + * + * Defines the size of the "down" RTT buffer (host -> target) to use for reading + * commands from Tracealyzer, for RTT buffer 1 or higher. + * + * Default buffer size for Tracealyzer is 32 bytes. + * + * This setting is ignored for RTT buffer 0, which can't be reconfigured + * in runtime and therefore hard-coded to use the defines in SEGGER_RTT_Conf.h. + ******************************************************************************/ +#define TRC_CFG_RTT_BUFFER_SIZE_DOWN 32 + +/******************************************************************************* + * Configuration Macro: TRC_CFG_RTT_UP_BUFFER_INDEX + * + * Defines the RTT buffer to use for writing the trace data. Make sure that + * the PC application has the same setting (File->Settings). + * + * Default: 1 + * + * We don't recommend using RTT buffer 0, since mainly intended for terminals. + * If you prefer to use buffer 0, it must be configured in SEGGER_RTT_Conf.h. + ******************************************************************************/ +#define TRC_CFG_RTT_UP_BUFFER_INDEX 1 + +/******************************************************************************* + * Configuration Macro: TRC_CFG_RTT_DOWN_BUFFER_INDEX + * + * Defines the RTT buffer to use for reading the trace data. Make sure that + * the PC application has the same setting (File->Settings). + * + * Default: 1 + * + * We don't recommend using RTT buffer 0, since mainly intended for terminals. + * If you prefer to use buffer 0, it must be configured in SEGGER_RTT_Conf.h. + ******************************************************************************/ +#define TRC_CFG_RTT_DOWN_BUFFER_INDEX 1 + +/******************************************************************************* + * TRC_CFG_RTT_MODE + * This stream port for J-Link streaming relies on SEGGER RTT, that contains an + * internal RAM buffer read by the J-Link probes during execution. + * + * Possible values: + * - SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL + * - SEGGER_RTT_MODE_NO_BLOCK_SKIP (default) + * + * Using SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL ensure that you get a + * complete and valid trace. This may however cause blocking if your streaming + * interface isn't fast enough, which may disturb the real-time behavior. + * + * We therefore recommend SEGGER_RTT_MODE_NO_BLOCK_SKIP. In this mode, + * Tracealyzer will report lost events if the transfer is not + * fast enough. In that case, try increasing the size of the "up buffer". + ******************************************************************************/ +#define TRC_CFG_RTT_MODE SEGGER_RTT_MODE_NO_BLOCK_SKIP + +#include "SEGGER_RTT_Conf.h" +#include "SEGGER_RTT.h" + +#if (TRC_CFG_RTT_UP_BUFFER_INDEX >= SEGGER_RTT_MAX_NUM_UP_BUFFERS) +#error "TRC_CFG_RTT_UP_BUFFER_INDEX must be smaller than SEGGER_RTT_MAX_NUM_UP_BUFFERS" +#endif + +#if (TRC_CFG_RTT_DOWN_BUFFER_INDEX >= SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) +#error "TRC_CFG_RTT_DOWN_BUFFER_INDEX must be smaller than SEGGER_RTT_MAX_NUM_DOWN_BUFFERS" +#endif + +/* If index is defined as 0, the internal RTT buffers will be used instead of this. */ +#if TRC_CFG_RTT_UP_BUFFER_INDEX == 0 +#define TRC_RTT_ALLOC_UP() static char* _TzTraceData = NULL; /* Not actually used. Ignore allocation method. */ +#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */ +#else +#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC +#define TRC_RTT_ALLOC_UP() char _TzTraceData[TRC_CFG_RTT_BUFFER_SIZE_UP]; /* Static allocation */ +#define TRC_STREAM_PORT_MALLOC() /* Static allocation. Not used. */ +#endif +#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC +#define TRC_RTT_ALLOC_UP() char* _TzTraceData = NULL; /* Dynamic allocation */ +#define TRC_STREAM_PORT_MALLOC() _TzTraceData = TRC_PORT_MALLOC(TRC_CFG_RTT_BUFFER_SIZE_UP); +#endif +#if TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM +#define TRC_RTT_ALLOC_UP() char* _TzTraceData = NULL; /* Custom allocation, user needs to call vTraceSetRecorderDataBuffer before vTraceEnable, to assign this */ +#define TRC_STREAM_PORT_MALLOC() /* Not used in custom mode */ +#endif +#endif + +/* Down-buffer. If index is defined as 0, the internal RTT buffers will be used instead of this. */ \ +#if TRC_CFG_RTT_DOWN_BUFFER_INDEX == 0 +#define TRC_RTT_ALLOC_DOWN() static char* _TzCtrlData = NULL; /* Not actually used. Ignore allocation method. */ +#else +#define TRC_RTT_ALLOC_DOWN() static char _TzCtrlData[TRC_CFG_RTT_BUFFER_SIZE_DOWN]; /* Always static allocation, since usually small. */ +#endif + +#define TRC_STREAM_PORT_ALLOCATE_FIELDS() \ + TRC_RTT_ALLOC_UP() /* Macro that will result in proper UP buffer allocation */ \ + TRC_RTT_ALLOC_DOWN() /* Macro that will result in proper DOWN buffer allocation */ + +int32_t readFromRTT(void* ptrData, uint32_t size, int32_t* ptrBytesRead); + +int32_t writeToRTT(void* ptrData, uint32_t size, int32_t* ptrBytesWritten); + + +#define TRC_STREAM_PORT_INIT() \ + TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */ \ + SEGGER_RTT_ConfigUpBuffer(TRC_CFG_RTT_UP_BUFFER_INDEX, "TzData", _TzTraceData, TRC_CFG_RTT_BUFFER_SIZE_UP, TRC_CFG_RTT_MODE ); \ + SEGGER_RTT_ConfigDownBuffer(TRC_CFG_RTT_DOWN_BUFFER_INDEX, "TzCtrl", _TzCtrlData, TRC_CFG_RTT_BUFFER_SIZE_DOWN, TRC_CFG_RTT_MODE); + +/* Important for the J-Link port, in most other ports this can be skipped (default is 1) */ +#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 0 + +#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) writeToRTT(_ptrData, _size, _ptrBytesWritten) + +#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) readFromRTT(_ptrData, _size, _ptrBytesRead) + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAMING_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/trcStreamingPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/trcStreamingPort.c index d279f83b9..d4d7ec118 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/trcStreamingPort.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/trcStreamingPort.c @@ -1,44 +1,83 @@ -
-#include "trcRecorder.h"
-
-#if (TRC_USE_TRACEALYZER_RECORDER == 1)
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-
-int32_t readFromRTT(void* ptrData, uint32_t size, int32_t* ptrBytesRead)
-{
- uint32_t bytesRead = 0;
-
- if (SEGGER_RTT_HASDATA(TRC_CFG_RTT_DOWN_BUFFER_INDEX))
- {
- bytesRead = SEGGER_RTT_Read((TRC_CFG_RTT_DOWN_BUFFER_INDEX), (char*)ptrData, size);
-
- if (ptrBytesRead != NULL)
- *ptrBytesRead = (int32_t)bytesRead;
-
- if (bytesRead != size)
- {
- return -1;
- }
-
- }
-
- return 0;
-}
-
-int32_t writeToRTT(void* ptrData, uint32_t size, int32_t* ptrBytesWritten)
-{
- uint32_t bytesWritten = SEGGER_RTT_Write((TRC_CFG_RTT_UP_BUFFER_INDEX), (const char*)ptrData, size);
-
- if (ptrBytesWritten != NULL)
- *ptrBytesWritten = (int32_t)bytesWritten;
-
- if (bytesWritten != size)
- {
- return -1;
- }
-
- return 0;
-}
-
-#endif
-#endif
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.c + * + * Supporting functions for trace streaming, used by the "stream ports" + * for reading and writing data to the interface. + * + * Note that this stream port is more complex than the typical case, since + * the J-Link interface uses a separate RAM buffer in SEGGER_RTT.c, instead + * of the default buffer included in the recorder core. The other stream ports + * offer more typical examples of how to define a custom streaming interface. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#include "trcRecorder.h" + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +int32_t readFromRTT(void* ptrData, uint32_t size, int32_t* ptrBytesRead) +{ + uint32_t bytesRead = 0; + + if (SEGGER_RTT_HASDATA(TRC_CFG_RTT_DOWN_BUFFER_INDEX)) + { + bytesRead = SEGGER_RTT_Read((TRC_CFG_RTT_DOWN_BUFFER_INDEX), (char*)ptrData, size); + + if (ptrBytesRead != NULL) + *ptrBytesRead = (int32_t)bytesRead; + + } + + return 0; +} + +int32_t writeToRTT(void* ptrData, uint32_t size, int32_t* ptrBytesWritten) +{ + uint32_t bytesWritten = SEGGER_RTT_Write((TRC_CFG_RTT_UP_BUFFER_INDEX), (const char*)ptrData, size); + + if (ptrBytesWritten != NULL) + *ptrBytesWritten = (int32_t)bytesWritten; + + return 0; +} + +#endif +#endif diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/Readme-Streamport.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/Readme-Streamport.txt index f8f097baa..c2d9ce78d 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/Readme-Streamport.txt +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/Readme-Streamport.txt @@ -1,22 +1,50 @@ -Tracealyzer Stream Port for TCP/IP (lwIP example)
--------------------------------------------------
-
-This directory contains a "stream port" for the Tracealyzer recorder library,
-i.e., the specific code needed to use a particular interface for streaming a
-Tracealyzer RTOS trace. The stream port is defined by a set of macros in
-trcStreamingPort.h, found in the "include" directory.
-
-This particular stream port targets TCP/IP. This example assumes lwIP but is
-easy to modify for other TCP/IP stacks.
-
-To use this stream port, make sure that include/trcStreamingPort.h is found
-by the compiler (i.e., add this folder to your project's include paths) and
-add all included source files to your build. Make sure no other versions of
-trcStreamingPort.h are included by mistake!
-
-Note that lwIP is not included, but assumed to exist in the project already.
-
-See also http://percepio.com/2016/10/05/rtos-tracing.
-
-Percepio AB
+Tracealyzer Stream Port for TCP/IP (lwIP example) +------------------------------------------------- + +This directory contains a "stream port" for the Tracealyzer recorder library, +i.e., the specific code needed to use a particular interface for streaming a +Tracealyzer RTOS trace. The stream port is defined by a set of macros in +trcStreamingPort.h, found in the "include" directory. + +This particular stream port targets TCP/IP. This example assumes lwIP but is +easy to modify for other TCP/IP stacks. + +Instructions: + +1. Integrate the trace recorder and configure it for streaming, as described + in the Tracealyzer User Manual. For FreeRTOS this is found at: + https://percepio.com/docs/FreeRTOS/manual/index.html#Creating_and_Loading_Traces___Introduction + +2. Make sure all .c and .h files from this stream port folder is included in + your build, and that no other variant of trcStreamingPort.h is included. + +3. In lwipopts.h, make sure you have this line: + + #define LWIP_SOCKET 1 + +4. Make sure that vTraceEnable(TRC_INIT) is called during the startup, before + any RTOS calls are made. + +5. In Tracealyzer, open File -> Settings -> PSF Streaming Settings and + select Target Connection: TCP. Enter the IP address of the target system + and the port number (by default 12000). + +6. Start your target system, wait a few seconds to ensure that the lwIP is operational, + then select Start Recording in Tracealyzer. + +Troubleshooting: + +- If the tracing suddenly stops, check the "errno" value in trcSocketSend (trcStreamingPort.c). +You can see the error code definitions in lwip/errno.h. If errno is ENOMEM, may you need to +increase MEM_SIZE in lwipopts.h. + +- Since lwIP performs a lot of semaphore and mutex operations, we recommend filtering out +such events from the trace, at least those caused by the transmission of trace data in the +TzCtrl task. This can be done using vTraceSetFilterGroup() and vTraceSetFilterMask(). + +Note that lwIP is not included in the stream port, but assumed to exist in the project already. + +See also http://percepio.com/2016/10/05/rtos-tracing. + +Percepio AB www.percepio.com
\ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/include/trcStreamingPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/include/trcStreamingPort.h index 51e52e862..b305df4f5 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/include/trcStreamingPort.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/include/trcStreamingPort.h @@ -1,66 +1,68 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcStreamingPort.h
- *
- * The interface definitions for trace streaming ("stream ports").
- * This "stream port" sets up the recorder to use TCP/IP as streaming channel.
- * The example is for lwIP.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_STREAMING_PORT_H
-#define TRC_STREAMING_PORT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int32_t trcTcpRead(void* data, uint32_t size, int32_t *ptrBytesRead);
-
-int32_t trcTcpWrite(void* data, uint32_t size, int32_t *ptrBytesWritten);
-
-#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcTcpRead(_ptrData, _size, _ptrBytesRead)
-
-#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) trcTcpWrite(_ptrData, _size, _ptrBytesSent)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TRC_STREAMING_PORT_H */
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.h + * + * The interface definitions for trace streaming ("stream ports"). + * This "stream port" sets up the recorder to use TCP/IP as streaming channel. + * The example is for lwIP. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_STREAMING_PORT_H +#define TRC_STREAMING_PORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 1 + +int32_t trcTcpRead(void* data, uint32_t size, int32_t *ptrBytesRead); + +int32_t trcTcpWrite(void* data, uint32_t size, int32_t *ptrBytesWritten); + +#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcTcpRead(_ptrData, _size, _ptrBytesRead) + +#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) trcTcpWrite(_ptrData, _size, _ptrBytesSent) + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAMING_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/trcStreamingPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/trcStreamingPort.c index d420d121a..df92f6f0a 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/trcStreamingPort.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/trcStreamingPort.c @@ -1,186 +1,180 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcStreamingPort.c
- *
- * Supporting functions for trace streaming, used by the "stream ports"
- * for reading and writing data to the interface.
- * Existing ports can easily be modified to fit another setup, e.g., a
- * different TCP/IP stack, or to define your own stream port.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#include "trcRecorder.h"
-
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-#if (TRC_USE_TRACEALYZER_RECORDER == 1)
-
-/* TCP/IP includes - for lwIP in this case */
-#include "lwip/tcpip.h"
-#include "lwip/sockets.h"
-
-int errno;
-
-#define TRC_TCPIP_PORT 12000
-
-int sock = -1, new_sd = -1;
-int flags = 0;
-int remoteSize;
-struct sockaddr_in address, remote;
-
-int32_t trcSocketSend( void* data, int32_t size, int32_t* bytesWritten )
-{
- if (new_sd < 0)
- return -1;
-
- if (bytesWritten == NULL)
- return -1;
-
- *bytesWritten = send( new_sd, data, size, 0 );
- if (*bytesWritten < 0)
- {
- /* EWOULDBLOCK may be expected when buffers are full */
- if (errno != 0 && errno != EWOULDBLOCK)
- {
- closesocket(new_sd);
- new_sd = -1;
- return -1;
- }
- else
- *bytesWritten = 0;
- }
-
- return 0;
-}
-
-int32_t trcSocketReceive( void* data, int32_t size, int32_t* bytesRead )
-{
- if (new_sd < 0)
- return -1;
-
- *bytesRead = recv( new_sd, data, size, 0 );
- if ( *bytesRead < 0 )
- {
- /* EWOULDBLOCK may be expected when there is no data to receive */
- if (errno != 0 && errno != EWOULDBLOCK)
- {
- closesocket(new_sd);
- new_sd = -1;
- return -1;
- }
- else
- *bytesRead = 0;
- }
-
- return 0;
-}
-
-int32_t trcSocketInitializeListener()
-{
- if (sock >= 0)
- return 0;
-
- sock = lwip_socket(AF_INET, SOCK_STREAM, 0);
-
- if (sock < 0)
- return -1;
-
- address.sin_family = AF_INET;
- address.sin_port = htons( TRC_TCPIP_PORT );
- address.sin_addr.s_addr = INADDR_ANY;
-
- if (bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0)
- {
- closesocket(sock);
- sock = -1;
- return -1;
- }
-
- if (lwip_listen(sock, 5) < 0)
- {
- closesocket(sock);
- sock = -1;
- return -1;
- }
-
- return 0;
-}
-
-int32_t trcSocketAccept()
-{
- if (sock < 0)
- return -1;
-
- if (new_sd >= 0)
- return 0;
-
- remoteSize = sizeof( remote );
- new_sd = accept( sock, (struct sockaddr *)&remote, (socklen_t*)&remoteSize );
-
- flags = fcntl( new_sd, F_GETFL, 0 );
- fcntl( new_sd, F_SETFL, flags | O_NONBLOCK );
-
- if( new_sd < 0 )
- {
- closesocket(new_sd);
- new_sd = -1;
- closesocket(sock);
- sock = -1;
- return -1;
- }
-
- return 0;
-}
-/************** MODIFY THE ABOVE PART TO USE YOUR TPC/IP STACK ****************/
-
-int32_t trcTcpWrite(void* data, uint32_t size, int32_t *ptrBytesWritten)
-{
- return trcSocketSend(data, size, ptrBytesWritten);
-}
-
-int32_t trcTcpRead(void* data, uint32_t size, int32_t *ptrBytesRead)
-{
- trcSocketInitializeListener();
-
- trcSocketAccept();
-
- return trcSocketReceive(data, size, ptrBytesRead);
-}
-
-#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
-#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.c + * + * Supporting functions for trace streaming, used by the "stream ports" + * for reading and writing data to the interface. + * Existing ports can easily be modified to fit another setup, e.g., a + * different TCP/IP stack, or to define your own stream port. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#include "trcRecorder.h" + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +/* TCP/IP includes - for lwIP in this case */ +#include "lwip/tcpip.h" +#include "lwip/sockets.h" +#include "lwip/errno.h" + +#define TRC_TCPIP_PORT 12000 + +int sock = -1, new_sd = -1; +int flags = 0; +int remoteSize; +struct sockaddr_in address, remote; + +int32_t trcSocketSend( void* data, int32_t size, int32_t* bytesWritten ) +{ + if (new_sd < 0) + return -1; + + if (bytesWritten == NULL) + return -1; + + *bytesWritten = send( new_sd, data, size, 0 ); + if (*bytesWritten < 0) + { + /* EWOULDBLOCK may be expected when buffers are full */ + if ((errno != 0) && (errno != EWOULDBLOCK)) + { + closesocket(new_sd); + new_sd = -1; + return -1; + } + else + *bytesWritten = 0; + } + + return 0; +} + +int32_t trcSocketReceive( void* data, int32_t size, int32_t* bytesRead ) +{ + if (new_sd < 0) + return -1; + + *bytesRead = recv( new_sd, data, size, 0 ); + /* EWOULDBLOCK may be expected when there is no data to receive */ + if (errno != 0 && errno != EWOULDBLOCK) + { + closesocket(new_sd); + new_sd = -1; + return -1; + } + + return 0; +} + +int32_t trcSocketInitializeListener() +{ + if (sock >= 0) + return 0; + + sock = lwip_socket(AF_INET, SOCK_STREAM, 0); + + if (sock < 0) + return -1; + + address.sin_family = AF_INET; + address.sin_port = htons( TRC_TCPIP_PORT ); + address.sin_addr.s_addr = INADDR_ANY; + + if (bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0) + { + closesocket(sock); + sock = -1; + return -1; + } + + if (lwip_listen(sock, 5) < 0) + { + closesocket(sock); + sock = -1; + return -1; + } + + return 0; +} + +int32_t trcSocketAccept() +{ + if (sock < 0) + return -1; + + if (new_sd >= 0) + return 0; + + remoteSize = sizeof( remote ); + new_sd = accept( sock, (struct sockaddr *)&remote, (socklen_t*)&remoteSize ); + + if( new_sd < 0 ) + { + closesocket(new_sd); + new_sd = -1; + closesocket(sock); + sock = -1; + return -1; + } + + flags = fcntl( new_sd, F_GETFL, 0 ); + fcntl( new_sd, F_SETFL, flags | O_NONBLOCK ); + + return 0; +} +/************** MODIFY THE ABOVE PART TO USE YOUR TPC/IP STACK ****************/ + +int32_t trcTcpWrite(void* data, uint32_t size, int32_t *ptrBytesWritten) +{ + return trcSocketSend(data, size, ptrBytesWritten); +} + +int32_t trcTcpRead(void* data, uint32_t size, int32_t *ptrBytesRead) +{ + trcSocketInitializeListener(); + + trcSocketAccept(); + + return trcSocketReceive(data, size, ptrBytesRead); +} + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/Readme-Streamport.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/Readme-Streamport.txt new file mode 100644 index 000000000..b61ecff8f --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/Readme-Streamport.txt @@ -0,0 +1,38 @@ +Tracealyzer Stream Port for TCP/IP (Win32 example) +------------------------------------------------- + +This directory contains a "stream port" for the Tracealyzer recorder library, +i.e., the I/O code needed for streaming a Tracealyzer RTOS trace over specific +interface. The stream port is defined by a set of macros in trcStreamingPort.h, +found in the "include" directory. + +This particular stream port is for streaming over TCP/IP on Windows, intended +for the FreeRTOS Windows port (WIN32-MSVC). To try it: + +1. Open the WIN32-MSVC demo project found in the FreeRTOS demo folder. You +need will Visual Studio, but there are free versions (Express or Community). + +2. Make sure the project includes a recent version or the recorder library +(v3.1.x). + +3. Make sure the recorder library is configured for streaming mode (see +trcConfig.h). + +4. Make sure the project's include paths contains trcStreamingPort.h found in +this include folder (and not any other stream port), and the related code +in this folder. + +5. Build and start the Win32 demo application. It should begin waiting for +a connection. + +6. In Tracealyzer, open File -> Settings... -> Streaming Trace Settings. +Specify target connection: TCP, host: 127.0.0.1 (i.e. localhost) and port 8888. + +7. In Tracealyzer, now open File -> Connect to Target System... and there +click "Start Recording". Now you should see a live CPU load graph and some +counters. Let it record for a few seconds, then click "Stop Recording" and then "View Trace". + +See also http://percepio.com/2016/10/05/rtos-tracing. + +Percepio AB +www.percepio.com
\ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/include/trcStreamingPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/include/trcStreamingPort.h new file mode 100644 index 000000000..594ba2150 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/include/trcStreamingPort.h @@ -0,0 +1,75 @@ +/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.h + * + * The interface definitions for trace streaming ("stream ports"). + * This "stream port" sets up the recorder to use TCP/IP as streaming channel. + * The example is for Windows sockets (Winsock), for use with Windows ports. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_STREAMING_PORT_H +#define TRC_STREAMING_PORT_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t readFromSocket(void* data, uint32_t size, int32_t *ptrBytesRead); +int32_t writeToSocket(void* data, uint32_t size, int32_t *ptrBytesWritten); + +/* This port supports both direct write and buffered mode ...*/ +#define TRC_STREAM_PORT_USE_INTERNAL_BUFFER 0 + +#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) readFromSocket(_ptrData, _size, _ptrBytesRead) + +#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) + #define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesWritten) writeToSocket(_ptrData, _size, _ptrBytesWritten) +#else + /* In the direct mode, _ptrBytesWritten is not used, so it is assumed that "all or nothing" is written. */ + #define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, UNUSED) writeToSocket(_ptrData, _size, NULL) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAMING_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/trcStreamingPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/trcStreamingPort.c new file mode 100644 index 000000000..d6eb0e3b7 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/trcStreamingPort.c @@ -0,0 +1,210 @@ +/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.c + * + * Supporting functions for trace streaming, used by the "stream ports" + * for reading and writing data to the interface. + * Existing ports can easily be modified to fit another setup, e.g., a + * different TCP/IP stack, or to define your own stream port. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#include<stdio.h> +#include<winsock2.h> + +#include "trcRecorder.h" + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + + +#pragma comment(lib,"ws2_32.lib") //Winsock Library + +SOCKET server_socket = (UINT_PTR)NULL, trace_socket = (UINT_PTR)NULL; +struct sockaddr_in server, client; + +int initServerSocketIfNeeded(void); +int initWinsockIfNeeded(void); + +int initWinsockIfNeeded(void) +{ + WSADATA wsa; + + if (server_socket) + return 0; + + if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) + { + return -1; + } + + return 0; +} + + +int initServerSocketIfNeeded(void) +{ + if (initWinsockIfNeeded() < 0) + { + return -1; + } + + if (server_socket) + return 0; + + if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + { + return -1; + } + + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(8888); + + if (bind(server_socket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) + { + closesocket(server_socket); + WSACleanup(); + server_socket = (UINT_PTR)NULL; + return -1; + } + + if (listen(server_socket, 3) < 0) + { + closesocket(server_socket); + WSACleanup(); + server_socket = (UINT_PTR)NULL; + return -1; + } + + return 0; +} + +int initTraceSocketIfNeeded(void) +{ + int c; + + if (!server_socket) + return -1; + + if (trace_socket) + return 0; + + c = sizeof(struct sockaddr_in); + trace_socket = accept(server_socket, (struct sockaddr *)&client, &c); + if (trace_socket == INVALID_SOCKET) + { + trace_socket = (UINT_PTR)NULL; + + closesocket(server_socket); + WSACleanup(); + server_socket = (UINT_PTR)NULL; + + return -1; + } + + return 0; +} + +int32_t writeToSocket(void* data, uint32_t size, int32_t *ptrBytesWritten) +{ + int ret; + + if (!trace_socket) + { + if (ptrBytesWritten != NULL) + { + *ptrBytesWritten = 0; + } + return -1; + } + ret = send(trace_socket, data, size, 0); + if (ret <= 0) + { + if (ptrBytesWritten != NULL) + { + *ptrBytesWritten = 0; + } + + closesocket(trace_socket); + trace_socket = (UINT_PTR)NULL; + return ret; + } + + if (ptrBytesWritten != NULL) + { + *ptrBytesWritten = ret; + } + + return 0; +} + +int32_t readFromSocket(void* data, uint32_t bufsize, int32_t *ptrBytesRead) +{ + unsigned long bytesAvailable = 0; + + if (initServerSocketIfNeeded() < 0) + return -1; + + if (initTraceSocketIfNeeded() < 0) + return -1; + + if (ioctlsocket(trace_socket, FIONREAD, &bytesAvailable) != NO_ERROR) + { + closesocket(trace_socket); + trace_socket = (UINT_PTR)NULL; + return -1; + } + + if (bytesAvailable > 0) + { + *ptrBytesRead = recv(trace_socket, data, bufsize, 0); + if (*ptrBytesRead == SOCKET_ERROR) + { + closesocket(trace_socket); + trace_socket = (UINT_PTR)NULL; + return -1; + } + } + + return 0; +} + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/Readme-Streamport.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/Readme-Streamport.txt index 260f12ace..a23151805 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/Readme-Streamport.txt +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/Readme-Streamport.txt @@ -1,27 +1,27 @@ -Tracealyzer Stream Port for USB CDC (STM32 example)
----------------------------------------------------
-
-This directory contains a "stream port" for the Tracealyzer recorder library,
-i.e., the specific code needed to use a particular interface for streaming a
-Tracealyzer RTOS trace. The stream port is defined by a set of macros in
-trcStreamingPort.h, found in the "include" directory.
-
-This particular stream port targets USB CDC. This is an example for the STM32 USB
-stack (from the STM32CubeMX code generation tool, v1.4.1) and has been tested on
-a STM32F767ZI device on a Nucleo board. See this blog post:
-
-http://percepio.com/2017/02/03/usb-trace-streaming-st-nucleo-f767zi-board/
-
-However, it should be straight-forward to modify this for other USB stacks.
-
-To use this stream port, make sure that include/trcStreamingPort.h is found
-by the compiler (i.e., add this folder to your project's include paths) and
-add all included source files to your build. Make sure no other versions of
-trcStreamingPort.h are included by mistake!
-
-Note that the USB stack not included, but assumed to exist in the project already.
-
-See also http://percepio.com/2016/10/05/rtos-tracing.
-
-Percepio AB
+Tracealyzer Stream Port for USB CDC (STM32 example) +--------------------------------------------------- + +This directory contains a "stream port" for the Tracealyzer recorder library, +i.e., the specific code needed to use a particular interface for streaming a +Tracealyzer RTOS trace. The stream port is defined by a set of macros in +trcStreamingPort.h, found in the "include" directory. + +This particular stream port targets USB CDC. This is an example for the STM32 USB +stack (from the STM32CubeMX code generation tool, v1.4.1) and has been tested on +a STM32F767ZI device on a Nucleo board. See this blog post: + +http://percepio.com/2017/02/03/usb-trace-streaming-st-nucleo-f767zi-board/ + +However, it should be straight-forward to modify this for other USB stacks. + +To use this stream port, make sure that include/trcStreamingPort.h is found +by the compiler (i.e., add this folder to your project's include paths) and +add all included source files to your build. Make sure no other versions of +trcStreamingPort.h are included by mistake! + +Note that the USB stack not included, but assumed to exist in the project already. + +See also http://percepio.com/2016/10/05/rtos-tracing. + +Percepio AB www.percepio.com
\ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/include/trcStreamingPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/include/trcStreamingPort.h index 6940b4d6d..082eebf51 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/include/trcStreamingPort.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/include/trcStreamingPort.h @@ -1,83 +1,83 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcStreamingPort.h
- *
- * The interface definitions for trace streaming ("stream ports").
- * This "stream port" sets up the recorder to use USB CDC as streaming channel.
- * The example is for STM32 using STM32Cube.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#ifndef TRC_STREAMING_PORT_H
-#define TRC_STREAMING_PORT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Include files as needed, in this case it is files from STM32Cube FW_F7 V1.4.1 */
-#include "usb_device.h"
-#include "usbd_cdc.h"
-#include "usbd_CDC_if.h"
-#include "usb_device.h"
-
-/* Tested on STM32 devices using Keil/CMSIS USB stack */
-
-extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS;
-
-uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
-
-int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes);
-
-int32_t trcCDCTransmit(void* data, uint32_t size, int32_t * noOfBytesSent );
-
-#define TRC_STREAM_PORT_INIT() \
- MX_USB_DEVICE_Init(); \
- TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */
-
-#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcCDCReceive(_ptrData, _size, _ptrBytesRead)
-
-#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) trcCDCTransmit(_ptrData, _size, _ptrBytesSent)
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TRC_STREAMING_PORT_H */
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.h + * + * The interface definitions for trace streaming ("stream ports"). + * This "stream port" sets up the recorder to use USB CDC as streaming channel. + * The example is for STM32 using STM32Cube. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#ifndef TRC_STREAMING_PORT_H +#define TRC_STREAMING_PORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Include files as needed, in this case it is files from STM32Cube FW_F7 V1.4.1 */ +#include "usb_device.h" +#include "usbd_cdc.h" +#include "usbd_CDC_if.h" +#include "usb_device.h" + +/* Tested on STM32 devices using Keil/CMSIS USB stack */ + +extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; + +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); + +int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes); + +int32_t trcCDCTransmit(void* data, uint32_t size, int32_t * noOfBytesSent ); + +#define TRC_STREAM_PORT_INIT() \ + MX_USB_DEVICE_Init(); \ + TRC_STREAM_PORT_MALLOC(); /*Dynamic allocation or empty if static */ + +#define TRC_STREAM_PORT_READ_DATA(_ptrData, _size, _ptrBytesRead) trcCDCReceive(_ptrData, _size, _ptrBytesRead) + +#define TRC_STREAM_PORT_WRITE_DATA(_ptrData, _size, _ptrBytesSent) trcCDCTransmit(_ptrData, _size, _ptrBytesSent) + + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAMING_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/trcStreamingPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/trcStreamingPort.c index 800022a1b..351d83325 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/trcStreamingPort.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/trcStreamingPort.c @@ -1,246 +1,291 @@ -
-#include "trcRecorder.h"
-
-#if (TRC_USE_TRACEALYZER_RECORDER == 1)
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-
-#include "stdint.h"
-
-/* Include files as needed, in this case it is files from STM32Cube FW_F7 V1.4.1 */
-#include "usb_device.h"
-#include "usbd_cdc.h"
-#include "usbd_CDC_if.h"
-#include "usb_device.h"
-
-#define BUFSIZE 64
-
-typedef struct{
- uint32_t idx;
- uint8_t data[BUFSIZE];
-}recBuf;
-
-/* Define size for the receive and transmit buffer over CDC */
-#define APP_RX_DATA_SIZE 8
-#define APP_TX_DATA_SIZE 64
-
-/* Received Data over USB are stored in this buffer */
-uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
-
-/* Send Data over USB CDC are stored in this buffer */
-uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
-
-extern USBD_HandleTypeDef hUsbDeviceFS;
-
-extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
-
-recBuf commandBuffer;
-
-static int8_t CDC_Init_FS (void);
-static int8_t CDC_DeInit_FS (void);
-static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
-static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
-
-USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
-{
- CDC_Init_FS,
- CDC_DeInit_FS,
- CDC_Control_FS,
- CDC_Receive_FS
-};
-
-/* Private functions ---------------------------------------------------------*/
-/**
- * @brief CDC_Init_FS
- * Initializes the CDC media low layer over the FS USB IP
- * @param None
- * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
- */
-static int8_t CDC_Init_FS(void)
-{
- /* Set Application Buffers */
- USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);
- USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);
- return (USBD_OK);
-}
-
-/**
- * @brief CDC_DeInit_FS
- * DeInitializes the CDC media low layer
- * @param None
- * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
- */
-static int8_t CDC_DeInit_FS(void)
-{
- return (USBD_OK);
-}
-
-/**
- * @brief CDC_Control_FS
- * Manage the CDC class requests
- * @param cmd: Command code
- * @param pbuf: Buffer containing command data (request parameters)
- * @param length: Number of data to be sent (in bytes)
- * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
- */
-static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
-{
- switch (cmd)
- {
- case CDC_SEND_ENCAPSULATED_COMMAND:
- break;
-
- case CDC_GET_ENCAPSULATED_RESPONSE:
- break;
-
- case CDC_SET_COMM_FEATURE:
- break;
-
- case CDC_GET_COMM_FEATURE:
- break;
-
- case CDC_CLEAR_COMM_FEATURE:
- break;
-
- /*******************************************************************************/
- /* Line Coding Structure */
- /*-----------------------------------------------------------------------------*/
- /* Offset | Field | Size | Value | Description */
- /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
- /* 4 | bCharFormat | 1 | Number | Stop bits */
- /* 0 - 1 Stop bit */
- /* 1 - 1.5 Stop bits */
- /* 2 - 2 Stop bits */
- /* 5 | bParityType | 1 | Number | Parity */
- /* 0 - None */
- /* 1 - Odd */
- /* 2 - Even */
- /* 3 - Mark */
- /* 4 - Space */
- /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
- /*******************************************************************************/
- case CDC_SET_LINE_CODING:
- break;
-
- case CDC_GET_LINE_CODING:
- break;
-
- case CDC_SET_CONTROL_LINE_STATE:
- break;
-
- case CDC_SEND_BREAK:
- break;
-
- default:
- break;
- }
- return (USBD_OK);
-}
-
-/**
- * @brief CDC_Receive_FS
- * Data received over USB OUT endpoint are sent over CDC interface
- * through this function.
- *
- * @note
- * This function will block any OUT packet reception on USB endpoint
- * until exiting this function. If you exit this function before transfer
- * is complete on CDC interface (i.e. using DMA controller) it will result
- * in receiving more data while previous ones are still not sent.
- *
- * @param Buf: Buffer of data to be received
- * @param Len: Number of data received (in bytes)
- * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
- */
-static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
-{
- for( uint32_t i=0;i<* Len;i++)
- {
- commandBuffer.data[commandBuffer.idx]=Buf[i];
- commandBuffer.idx++;
- }
- USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
- USBD_CDC_ReceivePacket(&hUsbDeviceFS);
-
- return (USBD_OK);
-}
-
-/**
- * @brief CDC_Transmit_FS
- * Data send over USB IN endpoint are sent over CDC interface
- * through this function.
- * @note
- *
- *
- * @param Buf: Buffer of data to be send
- * @param Len: Number of data to be send (in bytes)
- * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
- */
-uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
-{
- uint8_t result = USBD_OK;
- USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
- if (hcdc->TxState != 0){
- return USBD_BUSY;
- }
- USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
- result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
- return result;
-}
-
-/* The READ function, used in trcStreamingPort.h */
-int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes)
-{
- uint32_t i,diff;
-
- if(commandBuffer.idx>0)
- {
- if (size >= commandBuffer.idx) // more than what is stored, number of bytes will be .idx
- {
- memcpy(data,commandBuffer.data, commandBuffer.idx);
- *NumBytes=commandBuffer.idx;
- commandBuffer.idx=0; // Make the buffer ready for a new command
- }
- else //If some data in the buffer is not read
- {
- diff = commandBuffer.idx-size;
- memcpy(data,commandBuffer.data, size);
- for(i=0;i<diff;i++)
- {
- commandBuffer.data[i]=commandBuffer.data[i+size];
- }
- *NumBytes=size;
- commandBuffer.idx=diff;
- }
- }
- else
- {
- *NumBytes=0;
- }
- return 0;
-}
-
-/* The WRITE function, used in trcStreamingPort.h */
-int32_t trcCDCTransmit(void* data, uint32_t size, int32_t * noOfBytesSent )
-{
- int32_t result;
- result=CDC_Transmit_FS(data, size);
- *noOfBytesSent = size;
-
- /* Return value should be 0 on success (not sure what the value of USBD_OK is) */
- if (result == USBD_OK)
- return 0;
- else
- return -1;
-}
-
-/**
-* @brief This function handles USB On The Go FS global interrupt.
-*/
-void OTG_FS_IRQHandler(void)
-{
- HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
-}
-
-#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
-#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
-
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingPort.c + * + * Supporting functions for trace streaming ("stream ports"). + * This "stream port" sets up the recorder to use USB CDC as streaming channel. + * The example is for STM32 using STM32Cube. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#include "trcRecorder.h" + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include "stdint.h" + +/* Include files as needed, in this case it is files from STM32Cube FW_F7 V1.4.1 */ +#include "usb_device.h" +#include "usbd_cdc.h" +#include "usbd_CDC_if.h" +#include "usb_device.h" + +#define BUFSIZE 64 + +typedef struct{ + uint32_t idx; + uint8_t data[BUFSIZE]; +}recBuf; + +/* Define size for the receive and transmit buffer over CDC */ +#define APP_RX_DATA_SIZE 8 +#define APP_TX_DATA_SIZE 64 + +/* Received Data over USB are stored in this buffer */ +uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; + +/* Send Data over USB CDC are stored in this buffer */ +uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; + +extern USBD_HandleTypeDef hUsbDeviceFS; + +extern PCD_HandleTypeDef hpcd_USB_OTG_FS; + +recBuf commandBuffer; + +static int8_t CDC_Init_FS (void); +static int8_t CDC_DeInit_FS (void); +static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length); +static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len); + +USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = +{ + CDC_Init_FS, + CDC_DeInit_FS, + CDC_Control_FS, + CDC_Receive_FS +}; + +/* Private functions ---------------------------------------------------------*/ +/** + * @brief CDC_Init_FS + * Initializes the CDC media low layer over the FS USB IP + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Init_FS(void) +{ + /* Set Application Buffers */ + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0); + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS); + return (USBD_OK); +} + +/** + * @brief CDC_DeInit_FS + * DeInitializes the CDC media low layer + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_DeInit_FS(void) +{ + return (USBD_OK); +} + +/** + * @brief CDC_Control_FS + * Manage the CDC class requests + * @param cmd: Command code + * @param pbuf: Buffer containing command data (request parameters) + * @param length: Number of data to be sent (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length) +{ + switch (cmd) + { + case CDC_SEND_ENCAPSULATED_COMMAND: + break; + + case CDC_GET_ENCAPSULATED_RESPONSE: + break; + + case CDC_SET_COMM_FEATURE: + break; + + case CDC_GET_COMM_FEATURE: + break; + + case CDC_CLEAR_COMM_FEATURE: + break; + + /*******************************************************************************/ + /* Line Coding Structure */ + /*-----------------------------------------------------------------------------*/ + /* Offset | Field | Size | Value | Description */ + /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ + /* 4 | bCharFormat | 1 | Number | Stop bits */ + /* 0 - 1 Stop bit */ + /* 1 - 1.5 Stop bits */ + /* 2 - 2 Stop bits */ + /* 5 | bParityType | 1 | Number | Parity */ + /* 0 - None */ + /* 1 - Odd */ + /* 2 - Even */ + /* 3 - Mark */ + /* 4 - Space */ + /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ + /*******************************************************************************/ + case CDC_SET_LINE_CODING: + break; + + case CDC_GET_LINE_CODING: + break; + + case CDC_SET_CONTROL_LINE_STATE: + break; + + case CDC_SEND_BREAK: + break; + + default: + break; + } + return (USBD_OK); +} + +/** + * @brief CDC_Receive_FS + * Data received over USB OUT endpoint are sent over CDC interface + * through this function. + * + * @note + * This function will block any OUT packet reception on USB endpoint + * until exiting this function. If you exit this function before transfer + * is complete on CDC interface (i.e. using DMA controller) it will result + * in receiving more data while previous ones are still not sent. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len) +{ + for( uint32_t i=0;i<* Len;i++) + { + commandBuffer.data[commandBuffer.idx]=Buf[i]; + commandBuffer.idx++; + } + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); + USBD_CDC_ReceivePacket(&hUsbDeviceFS); + + return (USBD_OK); +} + +/** + * @brief CDC_Transmit_FS + * Data send over USB IN endpoint are sent over CDC interface + * through this function. + * @note + * + * + * @param Buf: Buffer of data to be send + * @param Len: Number of data to be send (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY + */ +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) +{ + uint8_t result = USBD_OK; + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; + if (hcdc->TxState != 0){ + return USBD_BUSY; + } + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len); + result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); + return result; +} + +/* The READ function, used in trcStreamingPort.h */ +int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes) +{ + uint32_t i,diff; + + if(commandBuffer.idx>0) + { + if (size >= commandBuffer.idx) // more than what is stored, number of bytes will be .idx + { + memcpy(data,commandBuffer.data, commandBuffer.idx); + *NumBytes=commandBuffer.idx; + commandBuffer.idx=0; // Make the buffer ready for a new command + } + else //If some data in the buffer is not read + { + diff = commandBuffer.idx-size; + memcpy(data,commandBuffer.data, size); + for(i=0;i<diff;i++) + { + commandBuffer.data[i]=commandBuffer.data[i+size]; + } + *NumBytes=size; + commandBuffer.idx=diff; + } + } + else + { + *NumBytes=0; + } + return 0; +} + +/* The WRITE function, used in trcStreamingPort.h */ +int32_t trcCDCTransmit(void* data, uint32_t size, int32_t * noOfBytesSent ) +{ + int32_t result; + result=CDC_Transmit_FS(data, size); + *noOfBytesSent = size; + + /* Return value should be 0 on success (not sure what the value of USBD_OK is) */ + if (result == USBD_OK) + return 0; + else + return -1; +} + +/** +* @brief This function handles USB On The Go FS global interrupt. +*/ +void OTG_FS_IRQHandler(void) +{ + HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); +} + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/tracealyzer_readme.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/tracealyzer_readme.txt index 09daa78f4..c707f1e0e 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/tracealyzer_readme.txt +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/tracealyzer_readme.txt @@ -1,337 +1,413 @@ --------------------------------------------------------------------------------
- Tracealyzer Recorder Library for FreeRTOS
--------------------------------------------------------------------------------
-
-Tracealyzer is a sophisticated tool for tracing and visualization
-of FreeRTOS-based software systems.
-
-Tracealyzer gives an unprecedented insight into the runtime behavior, which
-speeds up debugging, validation and optimization.
-
-This, the Trace Recorder Library, is the target-side part of Tracealyzer, that
-performs the actual tracing. The resulting data can then be viewed in the
-Tracealyzer PC application, found at https://percepio.com/tracealyzer
-
-To learn more, see these links.
-
- - Getting Started (videos etc): https://percepio.com/gettingstarted
-
- - FAQ: https://percepio.com/category/faq
-
-In case you have any questions, don't hesitate to contact support@percepio.com
-
-Tracealyzer supports FreeRTOS v7.3 and newer, including Amazon FreeRTOS.
-
--------------------------------------------------------------------------------
-Changes, v4.1.4 -> v4.1.5
-
-- Fixed a bug in the ITM stream port, that required Port 0 to be enabled.
-- Added missing include of stdio.h (needed by vTraceConsoleChannelPrintF).
-- Moved standard includes from trcRecorder.h into the .c files needing them.
-
--------------------------------------------------------------------------------
-
-Changes, v4.1.2 -> v4.1.4
-
-- Fixed a compile error when certain FreeRTOS settings were used
-- Disabled filter support for FreeRTOS v7.3 since it uses "char" for object id
-
--------------------------------------------------------------------------------
-
-Changes, v4.1.0 -> v4.1.2
-
-- Added vTraceConsoleChannelPrintF(...)
-
--------------------------------------------------------------------------------
-
-Changes, v4.0.3 -> v4.1.0
-
-- Improved performance of User Events
-- Fixed handling of format strings ending with '%'
-- Improved handling of creative user configuration macros
-
--------------------------------------------------------------------------------
-
-Changes, v4.0.2 -> v4.0.3
-
-- Minor fix for TCP/IP stream port.
-- Corrected default RTT mode setting.
-
--------------------------------------------------------------------------------
-
-Changes, v4.0.1 -> v4.0.2
-
-- Memory allocation trace events now ignore filters.
-
--------------------------------------------------------------------------------
-
-Changes, v4.0.0 -> v4.0.1
-
-- Minor fixes to default values.
-
--------------------------------------------------------------------------------
-
-Changes, v3.3.0 -> v4.0.0
-
-- Fixed some issues with filters.
-
--------------------------------------------------------------------------------
-
-Changes, v3.2.0 -> v3.3.0
-
-- Added support for FreeRTOS v10, including the new object types Message Buffer
- and Stream Buffer.
-
-- Improved the object-level filtering to also support Timer, Event Group,
- Message Buffer and Stream Buffer objects.
-
-- Fixed a few remaining build problems with older FreeRTOS versions (v7.x).
-
-- vTraceStoreISRBegin now reports an error on invalid handles, i.e., if the
- initialization of the handle (xTraceSetISRProperties) had not been made.
-
--------------------------------------------------------------------------------
-
-Changes, v3.1.2 -> v3.2.0
-
-- Added new filtering system - that works in both snapshot and streaming mode.
- Filtering was previously not supported in streaming mode, but can be very
- useful for slower streaming interfaces. By exluding irrelevant events, the
- amount of data produced can be reduced a lot.
-
- * New functions vTraceSetFilterGroup and vTraceSetFilterMask allows for
- excluding all events from specific objects (like a semaphore or queue).
-
- * Added new "generic" filters (preprocessor level) to trcConfig.h, that
- exclude all events of a particular types.
- - TRC_CFG_INCLUDE_NOTIFY_EVENTS
- - TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS
- - TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS
- - TRC_CFG_INCLUDE_TIMER_EVENTS
-
- * Upgraded some previous filters from "Snapshot only" to the Common API
- and thereby moved them from trcSnapshotConfig.h to trcConfig.h.
- - TRC_CFG_SCHEDULING_ONLY
- - TRC_CFG_INCLUDE_MEMMANG_EVENTS
- - TRC_CFG_INCLUDE_USER_EVENTS
- - TRC_CFG_INCLUDE_ISR_TRACING
- - TRC_CFG_INCLUDE_READY_EVENTS
- - TRC_CFG_INCLUDE_OSTICK_EVENTS
-
- * Removed the old filter system from trcSnapshotRecorder.c.
-
-- Improved streaming interface - Now only two (2) macros are needed to be
- defined in most cases, read and write. This makes it a lot easier to make
- custom stream ports.
-
- * Many definitions that were identical in most stream ports, have been
- replaced by default definitions in the recorder core. If needed, they
- can be overriden by custom definitions in trcStreamingPort.h.
-
- * Stream ports are now assumed to use recorder's internal event buffer.
- Other stream ports that writes directly to the streaming interface
- (like J-Link) should define TRC_STREAM_PORT_USE_INTERNAL_BUFFER
- as zero (0) to make it work correctly.
-
- * Macro TRC_STREAM_PORT_PERIODIC_SEND_DATA has been replaced by
- TRC_STREAM_PORT_WRITE_DATA. Together with TRC_STREAM_PORT_READ_DATA,
- this is all that is necessary for a typical stream port.
-
- * Return values from the stream port macros READ_DATA and WRITE_DATA are
- now checked. Expects 0 on success, anything else produces a warning
- that can be retrived using xTraceGetLastError() and also seen in
- Tracealyzer if a trace was produced.
-
- * Stream ports should no longer call prvPagedEventBufferInit explicitly
- (e.g. in TRC_STREAM_PORT_ON_TRACE_BEGIN). This is now called
- automatically if TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1.
-
- * Macros TRC_STREAM_PORT_ON_TRACE_BEGIN and TRC_STREAM_PORT_ON_TRACE_END
- are now unused by default and don't need to be defined.
- You can however use them to hook in some own function at these events.
-
-- Added two new stream ports
-
- * TCPIP-Win32: allows for testing the streaming on Windows ports of your
- RTOS, using Winsock.
-
- * File: example of streaming to a local file system (tested on Windows,
- but easy to modify).
-
-- Added support for FreeRTOS v9.0.1
-
- * Replaced FreeRTOS version code TRC_FREERTOS_VERSION_9_X with
- - TRC_FREERTOS_VERSION_9_0_0
- - TRC_FREERTOS_VERSION_9_0_1
-
- * Using TRC_FREERTOS_VERSION_9_X is no longer allowed.
-
-- Added additional events for xQueuePeek, for blocking and timeouts events.
-
-- Added event for traceTIMER_EXPIRED, showing when the timer callback
- function is called.
-
-- Improved diagnostics in streaming mode, in case of errors in the recorder.
-
- * Added prvTraceWarning() - registers a "warning" error code, without
- stopping the recorder. Called if READ_DATA or WRITE_DATA returns a
- non-zero value, and in several other cases where the recorder
- configuration is incorrect (e.g., too small symbol table).
-
- * Added several new warning codes (PSF_WARNING_XYZ), corresponding to the
- issues detected by prvCheckRecorderStatus.
-
- * Fixed duplicate definitions of warning messages, so the warnings reported
- to Tracealyzer are the same as those provided in xTraceGetLastError().
-
- * Added better explainations of warning/error messages in the body of
- xTraceGetLastError (in streaming mode).
-
-- Added xTraceIsRecordingEnabled() to Common API.
-
-- Added "unofficial" hardware port for Altera Nios-II.
- This is a user contribition, not yet verified by Percerpio.
-
-- Fixed bug in vTraceEnable - option TRC_START_AWAIT_HOST was ignored if already initialized.
-
-- Fixed a few remaining compiler warnings.
-
-- Changed order of some settings in trcConfig.h - moved advanced stuff to the
- bottom.
-
-- Removed SEGGER_RTT_Printf.c from the J-Link stream port since not required
- for Tracealyzer.
-
--------------------------------------------------------------------------------
-
-Changes, v3.1.1 -> v3.1.2
-- Fixed two bugs related to User Events, one in vTracePrintF and other in vTracePrint.
-
-- Fixed a build problem related to a single reference of the old FreeRTOS type "xTaskHandle", in trcKernelPort.c.
- Changed to "TaskHandle_t", unless if using an older FreeRTOS kernel or the "compatibility mode".
-
-- Removed traceCREATE_MUTEX hook for FreeRTOS v9 or later (no longer required)
-
-- Updated the User Manual regarding snapshot trace via IAR Embedded Workbench.
-
-- Renamed vTraceGetTraceBuffer to xTraceGetTraceBuffer, since returning a pointer.
-
--------------------------------------------------------------------------------
-
-Changes, v3.1.0 -> v3.1.1
-
-After the major changes in the v3.1.0 trace recorder library, this update
-corrects a number of minor issues. Only minor functional improvements.
-
-- You can now use TRC_ALLOC_CUSTOM_BUFFER to declare a trace buffer on a custom
- location (using linker directives).
- The related function vTraceSetRecorderDataBuffer has been promoted to the
- Common API (previously only supported in snapshot mode, but custom allocation
- is now generally supported also in streaming mode).
-
-- Removed TRC_CFG_USE_LINKER_PRAGMA. No longer necessary thanks to the custom
- allocation mode.
-
-- Added support for timestamping from custom periodic timers, required for
- accurate timestamping on Cortex-M0/M0+ devices when using tickless idle.
- Only for streaming mode so far. See TRC_CUSTOM_TIMER_INCR / DECR.
-
-- ARM Cortex-M port: Made sure the DWT unit is initialized properly, in case
- the debugger doesn't handle this.
-
-- ARM Cortex-M port: Added possibility to use Systick timestamping also on
- Cortex-M3/M4/M7 devices (that otherwise use DWT timestamping by default).
- To use this option, define the macro TRC_CFG_ARM_CM_USE_SYSTICK.
-
-- J-Link streaming: The default RTT buffer has been changed from 0 to 1.
-
-- J-Link streaming: The RTT buffer settings for buffer 1 and higher, are now
- found in trcStreamingPort.h. Note: These settings don't apply to buffer 0.
-
-- vTracePrint has been optimized for better performance in string logging.
-
-- Minor performance improvement related to symbol table transfer in streaming mode.
-
-- Timer names now registered also in streaming mode.
-
-- Timer start and stop event are now traced.
-
-- Implemented support for queue registry (traceQUEUE_REGISTRY_ADD) also for streaming.
-
-- Fixed a bug related to repeated calls of vTraceEnable.
-
-- Fixed a bug where task-switches seemed to occur even though the scheduler was disabled.
-
-- Renamed HARDWARE_PORT_TEXAS_INSTRUMENTS_TMS570_RM48, added prefix TRC.
-
-- Fixed several language issues in the comments and documentation.
-
-- Fixed several minor issues and warnings from different compilers
- (including PowerPC/gcc) and configurations.
-
--------------------------------------------------------------------------------
-
-Changes, v3.0.9 -> v3.1.0
-
-- Merge of previously separated snapshot and streaming recorders into a single
- recorder supporting both streaming and snapshot as different modes.
-
-- New common API for supporting both streaming and snapshot modes.
-
-- New integration guide, see the User Manual.
-
-- Major improvement of API documentation in source files and User Manual.
-
-- New concept of "stream ports", giving a better structure defining streaming
- interfaces, and restructured the J-Link and TCP/IP streaming as stream ports.
-
-- Added a stream port for USB CDC connections, with STM32 as example.
- Since Tracealyzer now can receive serial data on Windows COM ports, this is
- really easy to use.
-
-- Added a warning (#error) for cases where FreeRTOS tickless idle mode is used
- together with timestamping using SysTick or other periodic interrupt timers,
- Tracing with tickless idle requires an independent time source to correctly
- capture the length of the idle periods.
-
-- Major changes in the recorder API. Important examples are:
-
- * Some configuration macros have changed names, e.g. for "hardware port".
- Make sure to remove any old "trcConfig.h" files if upgrading from an
- earlier version!
-
- * Recorder configuration in trcConfig.h has been minimized and now only
- includes the important settings that are independent of recorder mode.
- Advanced settings for each mode are found in trcSnapshotConfig.h and
- trcStreamingConfig.h.
-
- * vTraceEnable replaces Trace_Init and vTraceInitTraceData, as well as
- vTraceStart and uiTraceStart.
-
- * vTraceStop now part of the common API and thereby available also in
- streaming. And since vTraceEnable can start the streaming directly
- you have the option control the tracing from target, e.g., for
- streaming to a device file system.
-
- * vTraceStoreKernelObjectName from old streaming recorder has been replaced
- by vTraceSetQueueName, vTraceSetSemaphoreName, etc.
-
- * vTraceSetISRProperties now returns a "traceHandle" that should be passed as
- parameter to vTraceStoreISRBegin and vTraceStoreISREnd.
-
- * xTraceRegisterString has replaced the old functions xTraceOpenLabel and
- vTraceStoreUserEventChannelName. This now returns a "traceString" for use
- as "channel" parameter in vTracePrintF, and in other places where strings
- are stored.
-
- * Removed vTraceStoreISREndManual and vTraceStoreISREndAuto, use
- vTraceStoreISREnd instead.
-
- * Renamed the functions for saving User Events in a separate buffer:
- - xTraceRegisterChannelFormat -> xTraceRegisterUBChannel
- - vTraceChannelPrintF -> vTraceUBData
- - vTraceChannelUserEvent -> vTraceUBEvent
-
-
--------------------------------------------------------------------------------
+------------------------------------------------------------------------------- + Tracealyzer Recorder Library for FreeRTOS +------------------------------------------------------------------------------- + +Tracealyzer is a sophisticated tool for tracing and visualization +of FreeRTOS-based software systems. + +Tracealyzer gives an unprecedented insight into the runtime behavior, which +speeds up debugging, validation and optimization. + +This, the Trace Recorder Library, is the target-side part of Tracealyzer, that +performs the actual tracing. The resulting data can then be viewed in the +Tracealyzer PC application, found at https://percepio.com/tracealyzer + +To learn more, see these links. + + - Getting Started (videos etc): https://percepio.com/gettingstarted + + - FAQ: https://percepio.com/category/faq + +In case you have any questions, don't hesitate to contact support@percepio.com + +Tracealyzer supports FreeRTOS v7.3 and newer, including Amazon FreeRTOS. + +------------------------------------------------------------------------------- + +Changes, v4.3.10 -> v4.3.11 +- Adapted for new Task Notify changes + +------------------------------------------------------------------------------- + +Changes, v4.3.8 -> v4.3.10 +- Fixed accidental C99 reliance + +------------------------------------------------------------------------------- + +Changes, v4.3.7 -> v4.3.8 +- Modified how FreeRTOS versions are configured in the trace library. +- traceQUEUE_SET_SEND() was added. +- Now informs users of FreeRTOS v10.3.X that the trace point traceQUEUE_SEND in + prvNotifyQueueSetContainer() should be changed to traceQUEUE_SET_SEND. + +------------------------------------------------------------------------------- + +Changes, v4.3.5 -> v4.3.7 +- Fixed issue where ISR naming would not always work. +- Fixed "errno" issue with certain compilers when using lwip streaming port. +- Recorder now makes sure all streaming trace header info is successfully sent + before moving on. +- Recorder warns if TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT > 128 since code + isn't designed for that. +- Made sure uiTraceSystemState is always declared in snapshot recorder. + +------------------------------------------------------------------------------- + +Changes, v4.3.1 -> v4.3.5 +- A previously removed define is no longer used when configSUPPORT_STATIC_ALLOCATION is 1 + +------------------------------------------------------------------------------- + +Changes, v4.3.0 -> v4.3.1 +- Name string no longer has to have unique address when calling xTraceSetISRProperties() + +------------------------------------------------------------------------------- + +Changes, v4.2.12 -> v4.3.0 +- Improved Streaming stability in regards to starting/stopping. +- Added support for STACK usage reports. +- Added vTraceVPrintF() that accepts a va_list as argument. + +------------------------------------------------------------------------------- + +Changes, v4.2.2 -> v4.2.12 + +- Changed a call to vTracePrintF() into vTracePrint(). + +------------------------------------------------------------------------------- + +Changes, v4.2.1 -> v4.2.2 + +- TRC_STREAM_PORT_WRITE_DATA() no longer has to deal with null pointers. Better + for custom StreamPort implementations. + +------------------------------------------------------------------------------- + +Changes, v4.1.7 -> v4.2.1 + +- Added support for initial heap usage at trace start in Streaming mode. +- Fixed bug regarding failed malloc calls in Streaming mode. +- Added support for tracing failed malloc calls in Snapshot mode. +- Better way of setting initial task "(startup)" in Streaming mode. + +------------------------------------------------------------------------------- + +Changes, v4.1.5 -> v4.1.7 + +- vQueueSendToFront() and vQueueSendToFrontFromISR() are now traced properly in + Snaphot mode. + +------------------------------------------------------------------------------- + +Changes, v4.1.4 -> v4.1.5 + +- Fixed a bug in the ITM stream port, that required Port 0 to be enabled. +- Added missing include of stdio.h (needed by vTraceConsoleChannelPrintF). +- Moved standard includes from trcRecorder.h into the .c files needing them. + +------------------------------------------------------------------------------- + +Changes, v4.1.2 -> v4.1.4 + +- Fixed a compile error when certain FreeRTOS settings were used +- Disabled filter support for FreeRTOS v7.3 since it uses "char" for object id + +------------------------------------------------------------------------------- + +Changes, v4.1.0 -> v4.1.2 + +- Added vTraceConsoleChannelPrintF(...) + +------------------------------------------------------------------------------- + +Changes, v4.0.3 -> v4.1.0 + +- Improved performance of User Events +- Fixed handling of format strings ending with '%' +- Improved handling of creative user configuration macros + +------------------------------------------------------------------------------- + +Changes, v4.0.2 -> v4.0.3 + +- Minor fix for TCP/IP stream port. +- Corrected default RTT mode setting. + +------------------------------------------------------------------------------- + +Changes, v4.0.1 -> v4.0.2 + +- Memory allocation trace events now ignore filters. + +------------------------------------------------------------------------------- + +Changes, v4.0.0 -> v4.0.1 + +- Minor fixes to default values. + +------------------------------------------------------------------------------- + +Changes, v3.3.0 -> v4.0.0 + +- Fixed some issues with filters. + +------------------------------------------------------------------------------- + +Changes, v3.2.0 -> v3.3.0 + +- Added support for FreeRTOS v10, including the new object types Message Buffer + and Stream Buffer. + +- Improved the object-level filtering to also support Timer, Event Group, + Message Buffer and Stream Buffer objects. + +- Fixed a few remaining build problems with older FreeRTOS versions (v7.x). + +- vTraceStoreISRBegin now reports an error on invalid handles, i.e., if the + initialization of the handle (xTraceSetISRProperties) had not been made. + +------------------------------------------------------------------------------- + +Changes, v3.1.2 -> v3.2.0 + +- Added new filtering system - that works in both snapshot and streaming mode. + Filtering was previously not supported in streaming mode, but can be very + useful for slower streaming interfaces. By exluding irrelevant events, the + amount of data produced can be reduced a lot. + + * New functions vTraceSetFilterGroup and vTraceSetFilterMask allows for + excluding all events from specific objects (like a semaphore or queue). + + * Added new "generic" filters (preprocessor level) to trcConfig.h, that + exclude all events of a particular types. + - TRC_CFG_INCLUDE_NOTIFY_EVENTS + - TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS + - TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS + - TRC_CFG_INCLUDE_TIMER_EVENTS + + * Upgraded some previous filters from "Snapshot only" to the Common API + and thereby moved them from trcSnapshotConfig.h to trcConfig.h. + - TRC_CFG_SCHEDULING_ONLY + - TRC_CFG_INCLUDE_MEMMANG_EVENTS + - TRC_CFG_INCLUDE_USER_EVENTS + - TRC_CFG_INCLUDE_ISR_TRACING + - TRC_CFG_INCLUDE_READY_EVENTS + - TRC_CFG_INCLUDE_OSTICK_EVENTS + + * Removed the old filter system from trcSnapshotRecorder.c. + +- Improved streaming interface - Now only two (2) macros are needed to be + defined in most cases, read and write. This makes it a lot easier to make + custom stream ports. + + * Many definitions that were identical in most stream ports, have been + replaced by default definitions in the recorder core. If needed, they + can be overriden by custom definitions in trcStreamingPort.h. + + * Stream ports are now assumed to use recorder's internal event buffer. + Other stream ports that writes directly to the streaming interface + (like J-Link) should define TRC_STREAM_PORT_USE_INTERNAL_BUFFER + as zero (0) to make it work correctly. + + * Macro TRC_STREAM_PORT_PERIODIC_SEND_DATA has been replaced by + TRC_STREAM_PORT_WRITE_DATA. Together with TRC_STREAM_PORT_READ_DATA, + this is all that is necessary for a typical stream port. + + * Return values from the stream port macros READ_DATA and WRITE_DATA are + now checked. Expects 0 on success, anything else produces a warning + that can be retrived using xTraceGetLastError() and also seen in + Tracealyzer if a trace was produced. + + * Stream ports should no longer call prvPagedEventBufferInit explicitly + (e.g. in TRC_STREAM_PORT_ON_TRACE_BEGIN). This is now called + automatically if TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1. + + * Macros TRC_STREAM_PORT_ON_TRACE_BEGIN and TRC_STREAM_PORT_ON_TRACE_END + are now unused by default and don't need to be defined. + You can however use them to hook in some own function at these events. + +- Added two new stream ports + + * TCPIP-Win32: allows for testing the streaming on Windows ports of your + RTOS, using Winsock. + + * File: example of streaming to a local file system (tested on Windows, + but easy to modify). + +- Added support for FreeRTOS v9.0.1 + + * Replaced FreeRTOS version code TRC_FREERTOS_VERSION_9_X with + - TRC_FREERTOS_VERSION_9_0_0 + - TRC_FREERTOS_VERSION_9_0_1 + + * Using TRC_FREERTOS_VERSION_9_X is no longer allowed. + +- Added additional events for xQueuePeek, for blocking and timeouts events. + +- Added event for traceTIMER_EXPIRED, showing when the timer callback + function is called. + +- Improved diagnostics in streaming mode, in case of errors in the recorder. + + * Added prvTraceWarning() - registers a "warning" error code, without + stopping the recorder. Called if READ_DATA or WRITE_DATA returns a + non-zero value, and in several other cases where the recorder + configuration is incorrect (e.g., too small symbol table). + + * Added several new warning codes (PSF_WARNING_XYZ), corresponding to the + issues detected by prvCheckRecorderStatus. + + * Fixed duplicate definitions of warning messages, so the warnings reported + to Tracealyzer are the same as those provided in xTraceGetLastError(). + + * Added better explainations of warning/error messages in the body of + xTraceGetLastError (in streaming mode). + +- Added xTraceIsRecordingEnabled() to Common API. + +- Added "unofficial" hardware port for Altera Nios-II. + This is a user contribition, not yet verified by Percerpio. + +- Fixed bug in vTraceEnable - option TRC_START_AWAIT_HOST was ignored if already initialized. + +- Fixed a few remaining compiler warnings. + +- Changed order of some settings in trcConfig.h - moved advanced stuff to the + bottom. + +- Removed SEGGER_RTT_Printf.c from the J-Link stream port since not required + for Tracealyzer. + +------------------------------------------------------------------------------- + +Changes, v3.1.1 -> v3.1.2 +- Fixed two bugs related to User Events, one in vTracePrintF and other in vTracePrint. + +- Fixed a build problem related to a single reference of the old FreeRTOS type "xTaskHandle", in trcKernelPort.c. + Changed to "TaskHandle_t", unless if using an older FreeRTOS kernel or the "compatibility mode". + +- Removed traceCREATE_MUTEX hook for FreeRTOS v9 or later (no longer required) + +- Updated the User Manual regarding snapshot trace via IAR Embedded Workbench. + +- Renamed vTraceGetTraceBuffer to xTraceGetTraceBuffer, since returning a pointer. + +------------------------------------------------------------------------------- + +Changes, v3.1.0 -> v3.1.1 + +After the major changes in the v3.1.0 trace recorder library, this update +corrects a number of minor issues. Only minor functional improvements. + +- You can now use TRC_ALLOC_CUSTOM_BUFFER to declare a trace buffer on a custom + location (using linker directives). + The related function vTraceSetRecorderDataBuffer has been promoted to the + Common API (previously only supported in snapshot mode, but custom allocation + is now generally supported also in streaming mode). + +- Removed TRC_CFG_USE_LINKER_PRAGMA. No longer necessary thanks to the custom + allocation mode. + +- Added support for timestamping from custom periodic timers, required for + accurate timestamping on Cortex-M0/M0+ devices when using tickless idle. + Only for streaming mode so far. See TRC_CUSTOM_TIMER_INCR / DECR. + +- ARM Cortex-M port: Made sure the DWT unit is initialized properly, in case + the debugger doesn't handle this. + +- ARM Cortex-M port: Added possibility to use Systick timestamping also on + Cortex-M3/M4/M7 devices (that otherwise use DWT timestamping by default). + To use this option, define the macro TRC_CFG_ARM_CM_USE_SYSTICK. + +- J-Link streaming: The default RTT buffer has been changed from 0 to 1. + +- J-Link streaming: The RTT buffer settings for buffer 1 and higher, are now + found in trcStreamingPort.h. Note: These settings don't apply to buffer 0. + +- vTracePrint has been optimized for better performance in string logging. + +- Minor performance improvement related to symbol table transfer in streaming mode. + +- Timer names now registered also in streaming mode. + +- Timer start and stop event are now traced. + +- Implemented support for queue registry (traceQUEUE_REGISTRY_ADD) also for streaming. + +- Fixed a bug related to repeated calls of vTraceEnable. + +- Fixed a bug where task-switches seemed to occur even though the scheduler was disabled. + +- Renamed HARDWARE_PORT_TEXAS_INSTRUMENTS_TMS570_RM48, added prefix TRC. + +- Fixed several language issues in the comments and documentation. + +- Fixed several minor issues and warnings from different compilers + (including PowerPC/gcc) and configurations. + +------------------------------------------------------------------------------- + +Changes, v3.0.9 -> v3.1.0 + +- Merge of previously separated snapshot and streaming recorders into a single + recorder supporting both streaming and snapshot as different modes. + +- New common API for supporting both streaming and snapshot modes. + +- New integration guide, see the User Manual. + +- Major improvement of API documentation in source files and User Manual. + +- New concept of "stream ports", giving a better structure defining streaming + interfaces, and restructured the J-Link and TCP/IP streaming as stream ports. + +- Added a stream port for USB CDC connections, with STM32 as example. + Since Tracealyzer now can receive serial data on Windows COM ports, this is + really easy to use. + +- Added a warning (#error) for cases where FreeRTOS tickless idle mode is used + together with timestamping using SysTick or other periodic interrupt timers, + Tracing with tickless idle requires an independent time source to correctly + capture the length of the idle periods. + +- Major changes in the recorder API. Important examples are: + + * Some configuration macros have changed names, e.g. for "hardware port". + Make sure to remove any old "trcConfig.h" files if upgrading from an + earlier version! + + * Recorder configuration in trcConfig.h has been minimized and now only + includes the important settings that are independent of recorder mode. + Advanced settings for each mode are found in trcSnapshotConfig.h and + trcStreamingConfig.h. + + * vTraceEnable replaces Trace_Init and vTraceInitTraceData, as well as + vTraceStart and uiTraceStart. + + * vTraceStop now part of the common API and thereby available also in + streaming. And since vTraceEnable can start the streaming directly + you have the option control the tracing from target, e.g., for + streaming to a device file system. + + * vTraceStoreKernelObjectName from old streaming recorder has been replaced + by vTraceSetQueueName, vTraceSetSemaphoreName, etc. + + * vTraceSetISRProperties now returns a "traceHandle" that should be passed as + parameter to vTraceStoreISRBegin and vTraceStoreISREnd. + + * xTraceRegisterString has replaced the old functions xTraceOpenLabel and + vTraceStoreUserEventChannelName. This now returns a "traceString" for use + as "channel" parameter in vTracePrintF, and in other places where strings + are stored. + + * Removed vTraceStoreISREndManual and vTraceStoreISREndAuto, use + vTraceStoreISREnd instead. + + * Renamed the functions for saving User Events in a separate buffer: + - xTraceRegisterChannelFormat -> xTraceRegisterUBChannel + - vTraceChannelPrintF -> vTraceUBData + - vTraceChannelUserEvent -> vTraceUBEvent + + +------------------------------------------------------------------------------- Copyright Percepio AB, 2018.
\ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c index d41b52687..374e9a6d5 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c @@ -1,833 +1,1083 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcKernelPort.c
- *
- * The FreeRTOS-specific parts of the trace recorder
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#include "FreeRTOS.h"
-
-#if (!defined(TRC_USE_TRACEALYZER_RECORDER) && configUSE_TRACE_FACILITY == 1)
-#error Trace Recorder: You need to include trcRecorder.h at the end of your FreeRTOSConfig.h!
-#endif
-
-#if (defined(TRC_USE_TRACEALYZER_RECORDER) && TRC_USE_TRACEALYZER_RECORDER == 1)
-
-#ifndef TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS
- /* TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS is missing in trcConfig.h. */
-#error "TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS must be defined in trcConfig.h."
-#endif
-
-#ifndef TRC_CFG_INCLUDE_TIMER_EVENTS
- /* TRC_CFG_INCLUDE_TIMER_EVENTS is missing in trcConfig.h. */
-#error "TRC_CFG_INCLUDE_TIMER_EVENTS must be defined in trcConfig.h."
-#endif
-
-#ifndef TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS
- /* TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS is missing in trcConfig.h. */
-#error "TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS must be defined in trcConfig.h."
-#endif
-
-#ifndef TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS
- /* TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS is missing in trcConfig.h. Define this as 1 if using FreeRTOS v10 or later and like to trace stream buffer or message buffer events, otherwise 0. */
-#error "TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be defined in trcConfig.h."
-#endif
-
-#if (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))
- /*
- The below error message is to alert you on the following issue:
-
- The hardware port selected in trcConfig.h uses the operating system timer for the
- timestamping, i.e., the periodic interrupt timer that drives the OS tick interrupt.
-
- When using "tickless idle" mode, the recorder needs an independent time source in
- order to correctly record the durations of the idle times. Otherwise, the trace may appear
- to have a different length than in reality, and the reported CPU load is also affected.
-
- You may override this warning by defining the TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
- macro in your trcConfig.h file. But then the time scale may be incorrect during
- tickless idle periods.
-
- To get this correct, override the default timestamping by setting TRC_CFG_HARDWARE_PORT
- in trcConfig.h to TRC_HARDWARE_PORT_APPLICATION_DEFINED and define the HWTC macros
- accordingly, using a free running counter or an independent periodic interrupt timer.
- See trcHardwarePort.h for details.
-
- For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the
- DWT cycle counter for timestamping in these cases.
- */
-
- #ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
- #error Trace Recorder: This timestamping mode is not recommended with Tickless Idle.
- #endif
-#endif /* (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)) */
-
-#include "task.h"
-#include "queue.h"
-
-#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
-/* If the project does not include the FreeRTOS timers, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */
-#include "timers.h"
-#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
-
-#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
-/* If the project does not include the FreeRTOS event groups, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */
-#include "event_groups.h"
-#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
-
-#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-/* If the project does not include the FreeRTOS stream buffers, TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be set to 0 */
-#include "stream_buffer.h"
-#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-uint32_t prvTraceGetQueueNumber(void* handle);
-
-#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X)
-
-extern unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue );
-extern void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber );
-extern unsigned char ucQueueGetQueueType( xQueueHandle pxQueue );
-
-uint32_t prvTraceGetQueueNumber(void* handle)
-{
- return (uint32_t)ucQueueGetQueueNumber(handle);
-}
-#else
-uint32_t prvTraceGetQueueNumber(void* handle)
-{
- return (uint32_t)uxQueueGetQueueNumber(handle);
-}
-#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X) */
-
-uint8_t prvTraceGetQueueType(void* handle)
-{
- // This is either declared in header file in FreeRTOS 8 and later, or as extern above
- return ucQueueGetQueueType(handle);
-}
-
-/* Tasks */
-uint16_t prvTraceGetTaskNumberLow16(void* handle)
-{
- return TRACE_GET_LOW16(uxTaskGetTaskNumber(handle));
-}
-
-uint16_t prvTraceGetTaskNumberHigh16(void* handle)
-{
- return TRACE_GET_HIGH16(uxTaskGetTaskNumber(handle));
-}
-
-void prvTraceSetTaskNumberLow16(void* handle, uint16_t value)
-{
- vTaskSetTaskNumber(handle, TRACE_SET_LOW16(uxTaskGetTaskNumber(handle), value));
-}
-
-void prvTraceSetTaskNumberHigh16(void* handle, uint16_t value)
-{
- vTaskSetTaskNumber(handle, TRACE_SET_HIGH16(uxTaskGetTaskNumber(handle), value));
-}
-
-uint16_t prvTraceGetQueueNumberLow16(void* handle)
-{
- return TRACE_GET_LOW16(prvTraceGetQueueNumber(handle));
-}
-
-uint16_t prvTraceGetQueueNumberHigh16(void* handle)
-{
- return TRACE_GET_HIGH16(prvTraceGetQueueNumber(handle));
-}
-
-void prvTraceSetQueueNumberLow16(void* handle, uint16_t value)
-{
- vQueueSetQueueNumber(handle, TRACE_SET_LOW16(prvTraceGetQueueNumber(handle), value));
-}
-
-void prvTraceSetQueueNumberHigh16(void* handle, uint16_t value)
-{
- vQueueSetQueueNumber(handle, TRACE_SET_HIGH16(prvTraceGetQueueNumber(handle), value));
-}
-
-#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-
-uint16_t prvTraceGetTimerNumberLow16(void* handle)
-{
- return TRACE_GET_LOW16(uxTimerGetTimerNumber(handle));
-}
-
-uint16_t prvTraceGetTimerNumberHigh16(void* handle)
-{
- return TRACE_GET_HIGH16(uxTimerGetTimerNumber(handle));
-}
-
-void prvTraceSetTimerNumberLow16(void* handle, uint16_t value)
-{
- vTimerSetTimerNumber(handle, TRACE_SET_LOW16(uxTimerGetTimerNumber(handle), value));
-}
-
-void prvTraceSetTimerNumberHigh16(void* handle, uint16_t value)
-{
- vTimerSetTimerNumber(handle, TRACE_SET_HIGH16(uxTimerGetTimerNumber(handle), value));
-}
-#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-
-uint16_t prvTraceGetEventGroupNumberLow16(void* handle)
-{
- return TRACE_GET_LOW16(uxEventGroupGetNumber(handle));
-}
-
-uint16_t prvTraceGetEventGroupNumberHigh16(void* handle)
-{
- return TRACE_GET_HIGH16(uxEventGroupGetNumber(handle));
-}
-
-void prvTraceSetEventGroupNumberLow16(void* handle, uint16_t value)
-{
- vEventGroupSetNumber(handle, TRACE_SET_LOW16(uxEventGroupGetNumber(handle), value));
-}
-
-void prvTraceSetEventGroupNumberHigh16(void* handle, uint16_t value)
-{
- vEventGroupSetNumber(handle, TRACE_SET_HIGH16(uxEventGroupGetNumber(handle), value));
-}
-#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-
-uint16_t prvTraceGetStreamBufferNumberLow16(void* handle)
-{
- return TRACE_GET_LOW16(uxStreamBufferGetStreamBufferNumber(handle));
-}
-
-uint16_t prvTraceGetStreamBufferNumberHigh16(void* handle)
-{
- return TRACE_GET_HIGH16(uxStreamBufferGetStreamBufferNumber(handle));
-}
-
-void prvTraceSetStreamBufferNumberLow16(void* handle, uint16_t value)
-{
- vStreamBufferSetStreamBufferNumber(handle, TRACE_SET_LOW16(uxStreamBufferGetStreamBufferNumber(handle), value));
-}
-
-void prvTraceSetStreamBufferNumberHigh16(void* handle, uint16_t value)
-{
- vStreamBufferSetStreamBufferNumber(handle, TRACE_SET_HIGH16(uxStreamBufferGetStreamBufferNumber(handle), value));
-}
-#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-
-static void* pCurrentTCB = NULL;
-#if (defined(configENABLE_BACKWARD_COMPATIBILITY) && configENABLE_BACKWARD_COMPATIBILITY == 0)
-/* We're explicitly not using compatibility mode */
-static TaskHandle_t HandleTzCtrl = NULL; /* TzCtrl task TCB */
-#else
-/* We're using compatibility mode, or we're running an old kernel */
-static xTaskHandle HandleTzCtrl = NULL; /* TzCtrl task TCB */
-#endif
-
-#if defined(configSUPPORT_STATIC_ALLOCATION)
-#if (configSUPPORT_STATIC_ALLOCATION == 1)
-static StackType_t stackTzCtrl[TRC_CFG_CTRL_TASK_STACK_SIZE];
-static StaticTask_t tcbTzCtrl;
-#endif
-#endif
-
-/* Monitored by TzCtrl task, that give warnings as User Events */
-extern volatile uint32_t NoRoomForSymbol;
-extern volatile uint32_t NoRoomForObjectData;
-extern volatile uint32_t LongestSymbolName;
-extern volatile uint32_t MaxBytesTruncated;
-
-/* Keeps track of previous values, to only react on changes. */
-static uint32_t NoRoomForSymbol_last = 0;
-static uint32_t NoRoomForObjectData_last = 0;
-static uint32_t LongestSymbolName_last = 0;
-static uint32_t MaxBytesTruncated_last = 0;
-
-/* User Event Channel for giving warnings regarding NoRoomForSymbol etc. */
-traceString trcWarningChannel;
-
-#define TRC_PORT_MALLOC(size) pvPortMalloc(size)
-
-TRC_STREAM_PORT_ALLOCATE_FIELDS()
-
-/* Called by TzCtrl task periodically (Normally every 100 ms) */
-static void prvCheckRecorderStatus(void);
-
-extern void prvTraceWarning(int errCode);
-
-/* The TzCtrl task - receives commands from Tracealyzer (start/stop) */
-static portTASK_FUNCTION( TzCtrl, pvParameters );
-
-/*******************************************************************************
- * vTraceEnable
- *
- * Function that enables the tracing and creates the control task. It will halt
- * execution until a Start command has been received if haltUntilStart is true.
- *
- ******************************************************************************/
-void vTraceEnable(int startOption)
-{
- int32_t bytes = 0;
- int32_t status;
- extern uint32_t RecorderEnabled;
- TracealyzerCommandType msg;
-
- /* Only do this first time...*/
- if (HandleTzCtrl == NULL)
- {
- TRC_STREAM_PORT_INIT();
-
- /* Note: Requires that TRC_CFG_INCLUDE_USER_EVENTS is 1. */
- trcWarningChannel = xTraceRegisterString("Warnings from Recorder");
-
- /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */
- #if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
- HandleTzCtrl = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);
- #else
- xTaskCreate( TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl );
- #endif
-
- if (HandleTzCtrl == NULL)
- {
- prvTraceError(PSF_ERROR_TZCTRLTASK_NOT_CREATED);
- }
- }
-
- if (startOption == TRC_START_AWAIT_HOST)
- {
- /* We keep trying to read commands until the recorder has been started */
- do
- {
- bytes = 0;
-
- status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes);
-
- if (status != 0)
- {
- prvTraceWarning(PSF_WARNING_STREAM_PORT_READ);
- }
-
- if ((status == 0) && (bytes == sizeof(TracealyzerCommandType)))
- {
- if (prvIsValidCommand(&msg))
- {
- if (msg.cmdCode == CMD_SET_ACTIVE && msg.param1 == 1)
- {
- /* On start, init and reset the timestamping */
- TRC_PORT_SPECIFIC_INIT();
- }
-
- prvProcessCommand(&msg);
- }
- }
- }
- while (RecorderEnabled == 0);
- }
- else if (startOption == TRC_START)
- {
- /* We start streaming directly - this assumes that the interface is ready! */
- TRC_PORT_SPECIFIC_INIT();
-
- msg.cmdCode = CMD_SET_ACTIVE;
- msg.param1 = 1;
- prvProcessCommand(&msg);
- }
- else
- {
- /* On TRC_INIT */
- TRC_PORT_SPECIFIC_INIT();
- }
-}
-
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-/*******************************************************************************
- * vTraceSetQueueName(void* object, const char* name)
- *
- * Parameter object: pointer to the Queue that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for Queue objects for display in Tracealyzer.
- ******************************************************************************/
-void vTraceSetQueueName(void* object, const char* name)
-{
- vTraceStoreKernelObjectName(object, name);
-}
-
-/*******************************************************************************
- * vTraceSetSemaphoreName(void* object, const char* name)
- *
- * Parameter object: pointer to the Semaphore that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for Semaphore objects for display in Tracealyzer.
- ******************************************************************************/
-void vTraceSetSemaphoreName(void* object, const char* name)
-{
- vTraceStoreKernelObjectName(object, name);
-}
-
-/*******************************************************************************
- * vTraceSetMutexName(void* object, const char* name)
- *
- * Parameter object: pointer to the Mutex that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for Mutex objects for display in Tracealyzer.
- ******************************************************************************/
-void vTraceSetMutexName(void* object, const char* name)
-{
- vTraceStoreKernelObjectName(object, name);
-}
-
-#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
-/*******************************************************************************
-* vTraceSetEventGroupName(void* object, const char* name)
-*
-* Parameter object: pointer to the vTraceSetEventGroupName that shall be named
-* Parameter name: the name to set (const string literal)
-*
-* Sets a name for EventGroup objects for display in Tracealyzer.
-******************************************************************************/
-void vTraceSetEventGroupName(void* object, const char* name)
-{
- vTraceStoreKernelObjectName(object, name);
-}
-#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
-
-#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-/*******************************************************************************
-* vTraceSetStreamBufferName(void* object, const char* name)
-*
-* Parameter object: pointer to the StreamBuffer that shall be named
-* Parameter name: the name to set (const string literal)
-*
-* Sets a name for StreamBuffer objects for display in Tracealyzer.
-******************************************************************************/
-void vTraceSetStreamBufferName(void* object, const char* name)
-{
- vTraceStoreKernelObjectName(object, name);
-}
-
-/*******************************************************************************
-* vTraceSetMessageBufferName(void* object, const char* name)
-*
-* Parameter object: pointer to the MessageBuffer that shall be named
-* Parameter name: the name to set (const string literal)
-*
-* Sets a name for MessageBuffer objects for display in Tracealyzer.
-******************************************************************************/
-void vTraceSetMessageBufferName(void* object, const char* name)
-{
- vTraceStoreKernelObjectName(object, name);
-}
-#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */
-
-/*******************************************************************************
- * prvGetCurrentTaskHandle
- *
- * Function that returns the handle to the currently executing task.
- *
- ******************************************************************************/
-void* prvTraceGetCurrentTaskHandle(void)
-{
- return xTaskGetCurrentTaskHandle();
-}
-
-/*******************************************************************************
- * prvIsNewTCB
- *
- * Tells if this task is already executing, or if there has been a task-switch.
- * Assumed to be called within a trace hook in kernel context.
- ******************************************************************************/
-uint32_t prvIsNewTCB(void* pNewTCB)
-{
- if (pCurrentTCB != pNewTCB)
- {
- pCurrentTCB = pNewTCB;
- return 1;
- }
- return 0;
-}
-
-/*******************************************************************************
- * prvTraceIsSchedulerSuspended
- *
- * Returns true if the RTOS scheduler currently is disabled, thus preventing any
- * task-switches from occurring. Only called from vTraceStoreISREnd.
- ******************************************************************************/
-unsigned char prvTraceIsSchedulerSuspended(void)
-{
- /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,
- INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in
- FreeRTOSConfig.h for this function to be available. */
-
- return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;
-}
-
-
-/*******************************************************************************
- * prvCheckRecorderStatus
- *
- * Called by TzCtrl task periodically (every 100 ms - seems reasonable).
- * Checks a number of diagnostic variables and give warnings as user events,
- * in most cases including a suggested solution.
- ******************************************************************************/
-static void prvCheckRecorderStatus(void)
-{
- if (NoRoomForSymbol > NoRoomForSymbol_last)
- {
- if (NoRoomForSymbol > 0)
- {
- prvTraceWarning(PSF_WARNING_SYMBOL_TABLE_SLOTS);
- }
- NoRoomForSymbol_last = NoRoomForSymbol;
- }
-
- if (NoRoomForObjectData > NoRoomForObjectData_last)
- {
- if (NoRoomForObjectData > 0)
- {
- prvTraceWarning(PSF_WARNING_OBJECT_DATA_SLOTS);
- }
- NoRoomForObjectData_last = NoRoomForObjectData;
- }
-
- if (LongestSymbolName > LongestSymbolName_last)
- {
- if (LongestSymbolName > (TRC_CFG_SYMBOL_MAX_LENGTH))
- {
- prvTraceWarning(PSF_WARNING_SYMBOL_MAX_LENGTH);
- }
- LongestSymbolName_last = LongestSymbolName;
- }
-
- if (MaxBytesTruncated > MaxBytesTruncated_last)
- {
- if (MaxBytesTruncated > 0)
- {
- prvTraceWarning(PSF_WARNING_STRING_TOO_LONG);
- }
- MaxBytesTruncated_last = MaxBytesTruncated;
- }
-}
-
-/*******************************************************************************
- * TzCtrl
- *
- * Task for sending the trace data from the internal buffer to the stream
- * interface (assuming TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) and for
- * receiving commands from Tracealyzer. Also does some diagnostics.
- ******************************************************************************/
-static portTASK_FUNCTION( TzCtrl, pvParameters )
-{
- TracealyzerCommandType msg;
- int32_t bytes = 0;
- int32_t status = 0;
- (void)pvParameters;
-
- while (1)
- {
- do
- {
- /* Listen for new commands */
- bytes = 0;
- status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes);
-
- if (status != 0)
- {
- prvTraceWarning(PSF_WARNING_STREAM_PORT_READ);
- }
-
- if ((status == 0) && (bytes == sizeof(TracealyzerCommandType)))
- {
- if (prvIsValidCommand(&msg))
- {
- prvProcessCommand(&msg); /* Start or Stop currently... */
- }
- }
-
-/* If the internal buffer is disabled, the COMMIT macro instead sends the data directly
- from the "event functions" (using TRC_STREAM_PORT_WRITE_DATA). */
-#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
- /* If there is a buffer page, this sends it to the streaming interface using TRC_STREAM_PORT_WRITE_DATA. */
- bytes = prvPagedEventBufferTransfer();
-#endif
-
- /* If there was data sent or received (bytes != 0), loop around and repeat, if there is more data to send or receive.
- Otherwise, step out of this loop and sleep for a while. */
-
- } while (bytes != 0);
-
- prvCheckRecorderStatus();
-
- vTaskDelay(TRC_CFG_CTRL_TASK_DELAY);
- }
-}
-
-#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
-
-
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
-
-/* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */
-int uiInEventGroupSetBitsFromISR = 0;
-
-/******************************************************************************
- * TraceQueueClassTable
- * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_).
- * Has one entry for each QueueType, gives TRACE_CLASS ID.
- ******************************************************************************/
-traceObjectClass TraceQueueClassTable[5] = {
- TRACE_CLASS_QUEUE,
- TRACE_CLASS_MUTEX,
- TRACE_CLASS_SEMAPHORE,
- TRACE_CLASS_SEMAPHORE,
- TRACE_CLASS_MUTEX
-};
-
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-/*******************************************************************************
- * vTraceSetQueueName(void* object, const char* name)
- *
- * Parameter object: pointer to the Queue that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for Queue objects for display in Tracealyzer.
- ******************************************************************************/
-void vTraceSetQueueName(void* object, const char* name)
-{
- prvTraceSetObjectName(TRACE_CLASS_QUEUE, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);
-}
-
-/*******************************************************************************
- * vTraceSetSemaphoreName(void* object, const char* name)
- *
- * Parameter object: pointer to the Semaphore that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for Semaphore objects for display in Tracealyzer.
- ******************************************************************************/
-void vTraceSetSemaphoreName(void* object, const char* name)
-{
- prvTraceSetObjectName(TRACE_CLASS_SEMAPHORE, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);
-}
-
-/*******************************************************************************
- * vTraceSetMutexName(void* object, const char* name)
- *
- * Parameter object: pointer to the Mutex that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for Semaphore objects for display in Tracealyzer.
- ******************************************************************************/
-void vTraceSetMutexName(void* object, const char* name)
-{
- prvTraceSetObjectName(TRACE_CLASS_MUTEX, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name);
-}
-
-#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X)
-/*******************************************************************************
-* vTraceSetEventGroupName(void* object, const char* name)
-*
-* Parameter object: pointer to the EventGroup that shall be named
-* Parameter name: the name to set (const string literal)
-*
-* Sets a name for EventGroup objects for display in Tracealyzer.
-******************************************************************************/
-void vTraceSetEventGroupName(void* object, const char* name)
-{
- prvTraceSetObjectName(TRACE_CLASS_EVENTGROUP, TRACE_GET_OBJECT_NUMBER(EVENTGROUP, object), name);
-}
-#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X) */
-
-#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
-/*******************************************************************************
-* vTraceSetStreamBufferName(void* object, const char* name)
-*
-* Parameter object: pointer to the StreamBuffer that shall be named
-* Parameter name: the name to set (const string literal)
-*
-* Sets a name for StreamBuffer objects for display in Tracealyzer.
-******************************************************************************/
-void vTraceSetStreamBufferName(void* object, const char* name)
-{
- prvTraceSetObjectName(TRACE_CLASS_STREAMBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, object), name);
-}
-
-/*******************************************************************************
-* vTraceSetMessageBufferName(void* object, const char* name)
-*
-* Parameter object: pointer to the MessageBuffer that shall be named
-* Parameter name: the name to set (const string literal)
-*
-* Sets a name for MessageBuffer objects for display in Tracealyzer.
-******************************************************************************/
-void vTraceSetMessageBufferName(void* object, const char* name)
-{
- prvTraceSetObjectName(TRACE_CLASS_MESSAGEBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, object), name);
-}
-#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */
-
-#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */
-
-void* prvTraceGetCurrentTaskHandle()
-{
- return xTaskGetCurrentTaskHandle();
-}
-
-/* Initialization of the object property table */
-void vTraceInitObjectPropertyTable()
-{
- RecorderDataPtr->ObjectPropertyTable.NumberOfObjectClasses = TRACE_NCLASSES;
- RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[0] = TRC_CFG_NQUEUE;
- RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[1] = TRC_CFG_NSEMAPHORE;
- RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = TRC_CFG_NMUTEX;
- RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = TRC_CFG_NTASK;
- RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = TRC_CFG_NISR;
- RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = TRC_CFG_NTIMER;
- RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = TRC_CFG_NEVENTGROUP;
- RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[7] = TRC_CFG_NSTREAMBUFFER;
- RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[8] = TRC_CFG_NMESSAGEBUFFER;
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = TRC_CFG_NAME_LEN_QUEUE;
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = TRC_CFG_NAME_LEN_SEMAPHORE;
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = TRC_CFG_NAME_LEN_MUTEX;
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = TRC_CFG_NAME_LEN_TASK;
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = TRC_CFG_NAME_LEN_ISR;
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = TRC_CFG_NAME_LEN_TIMER;
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = TRC_CFG_NAME_LEN_EVENTGROUP;
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[7] = TRC_CFG_NAME_LEN_STREAMBUFFER;
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[8] = TRC_CFG_NAME_LEN_MESSAGEBUFFER;
- 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.TotalPropertyBytesPerClass[5] = PropertyTableSizeTimer;
- RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[6] = PropertyTableSizeEventGroup;
- RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[7] = PropertyTableSizeStreamBuffer;
- RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[8] = PropertyTableSizeMessageBuffer;
- 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.StartIndexOfClass[5] = StartIndexTimer;
- RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[6] = StartIndexEventGroup;
- RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[7] = StartIndexStreamBuffer;
- RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[8] = StartIndexMessageBuffer;
- RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;
-}
-
-/* Initialization of the handle mechanism, see e.g, prvTraceGetObjectHandle */
-void vTraceInitObjectHandleStack()
-{
- objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0;
- objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = (TRC_CFG_NQUEUE);
- objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE);
- objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX);
- objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK);
- objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR);
- objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER);
- objectHandleStacks.indexOfNextAvailableHandle[7] = objectHandleStacks.lowestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP);
- objectHandleStacks.indexOfNextAvailableHandle[8] = objectHandleStacks.lowestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER);
-
- objectHandleStacks.highestIndexOfClass[0] = (TRC_CFG_NQUEUE) - 1;
- objectHandleStacks.highestIndexOfClass[1] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) - 1;
- objectHandleStacks.highestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) - 1;
- objectHandleStacks.highestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) - 1;
- objectHandleStacks.highestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) - 1;
- objectHandleStacks.highestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) - 1;
- objectHandleStacks.highestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) - 1;
- objectHandleStacks.highestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) - 1;
- objectHandleStacks.highestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) + (TRC_CFG_NMESSAGEBUFFER) - 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 TRC_CFG_NTASK in trcSnapshotConfig.h";
- case TRACE_CLASS_ISR:
- return "Not enough ISR handles - increase TRC_CFG_NISR in trcSnapshotConfig.h";
- case TRACE_CLASS_SEMAPHORE:
- return "Not enough SEMAPHORE handles - increase TRC_CFG_NSEMAPHORE in trcSnapshotConfig.h";
- case TRACE_CLASS_MUTEX:
- return "Not enough MUTEX handles - increase TRC_CFG_NMUTEX in trcSnapshotConfig.h";
- case TRACE_CLASS_QUEUE:
- return "Not enough QUEUE handles - increase TRC_CFG_NQUEUE in trcSnapshotConfig.h";
- case TRACE_CLASS_TIMER:
- return "Not enough TIMER handles - increase TRC_CFG_NTIMER in trcSnapshotConfig.h";
- case TRACE_CLASS_EVENTGROUP:
- return "Not enough EVENTGROUP handles - increase TRC_CFG_NEVENTGROUP in trcSnapshotConfig.h";
- case TRACE_CLASS_STREAMBUFFER:
- return "Not enough STREAMBUFFER handles - increase TRC_CFG_NSTREAMBUFFER in trcSnapshotConfig.h";
- case TRACE_CLASS_MESSAGEBUFFER:
- return "Not enough MESSAGEBUFFER handles - increase TRC_CFG_NMESSAGEBUFFER in trcSnapshotConfig.h";
- default:
- return "pszTraceGetErrorHandles: Invalid objectclass!";
- }
-}
-
-/*******************************************************************************
- * prvTraceIsSchedulerSuspended
- *
- * Returns true if the RTOS scheduler currently is disabled, thus preventing any
- * task-switches from occurring. Only called from vTraceStoreISREnd.
- ******************************************************************************/
-#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
-unsigned char prvTraceIsSchedulerSuspended(void)
-{
- /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,
- INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in
- FreeRTOSConfig.h for this function to be available. */
-
- return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;
-}
-#endif
-
-#endif /* Snapshot mode */
-
-#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcKernelPort.c + * + * The FreeRTOS-specific parts of the trace recorder + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#include "FreeRTOS.h" + +#if (!defined(TRC_USE_TRACEALYZER_RECORDER) && configUSE_TRACE_FACILITY == 1) +#error Trace Recorder: You need to include trcRecorder.h at the end of your FreeRTOSConfig.h! +#endif + +#if (defined(TRC_USE_TRACEALYZER_RECORDER) && TRC_USE_TRACEALYZER_RECORDER == 1) + +#ifndef TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS + /* TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS is missing in trcConfig.h. */ +#error "TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS must be defined in trcConfig.h." +#endif + +#ifndef TRC_CFG_INCLUDE_TIMER_EVENTS + /* TRC_CFG_INCLUDE_TIMER_EVENTS is missing in trcConfig.h. */ +#error "TRC_CFG_INCLUDE_TIMER_EVENTS must be defined in trcConfig.h." +#endif + +#ifndef TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS + /* TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS is missing in trcConfig.h. */ +#error "TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS must be defined in trcConfig.h." +#endif + +#ifndef TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS + /* TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS is missing in trcConfig.h. Define this as 1 if using FreeRTOS v10 or later and like to trace stream buffer or message buffer events, otherwise 0. */ +#error "TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be defined in trcConfig.h." +#endif + +#if (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)) + /* + The below error message is to alert you on the following issue: + + The hardware port selected in trcConfig.h uses the operating system timer for the + timestamping, i.e., the periodic interrupt timer that drives the OS tick interrupt. + + When using "tickless idle" mode, the recorder needs an independent time source in + order to correctly record the durations of the idle times. Otherwise, the trace may appear + to have a different length than in reality, and the reported CPU load is also affected. + + You may override this warning by defining the TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING + macro in your trcConfig.h file. But then the time scale may be incorrect during + tickless idle periods. + + To get this correct, override the default timestamping by setting TRC_CFG_HARDWARE_PORT + in trcConfig.h to TRC_HARDWARE_PORT_APPLICATION_DEFINED and define the HWTC macros + accordingly, using a free running counter or an independent periodic interrupt timer. + See trcHardwarePort.h for details. + + For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the + DWT cycle counter for timestamping in these cases. + */ + + #ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING + #error Trace Recorder: This timestamping mode is not recommended with Tickless Idle. + #endif +#endif /* (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)) */ + +#include "task.h" +#include "queue.h" + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) || (defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)) + +static TaskType HandleTzCtrl = NULL; /* TzCtrl task TCB */ + +#if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1) + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) +static StackType_t stackTzCtrl[TRC_CFG_CTRL_TASK_STACK_SIZE]; +static StaticTask_t tcbTzCtrl; +#else +#error "configSUPPORT_STATIC_ALLOCATION not supported before FreeRTOS v9" +#endif + +#endif /* defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1) */ + + +/* The TzCtrl task - receives commands from Tracealyzer (start/stop) */ +static portTASK_FUNCTION(TzCtrl, pvParameters); + +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) +void prvReportStackUsage(void); +#else /* defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ +#define prvReportStackUsage() +#endif /* defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) || (defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)) */ + +#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) +/* If the project does not include the FreeRTOS timers, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */ +#include "timers.h" +#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) */ + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) +/* If the project does not include the FreeRTOS event groups, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */ +#include "event_groups.h" +#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) */ + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +/* If the project does not include the FreeRTOS stream buffers, TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be set to 0 */ +#include "stream_buffer.h" +#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#if (TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND != TRC_ACKNOWLEDGED) && (TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_10_3_0 || TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_10_3_1) && (configUSE_QUEUE_SETS == 1) +#error "When using FreeRTOS v10.3.0 or v10.3.1, please make sure that the trace point in prvNotifyQueueSetContainer() in queue.c is renamed from traceQUEUE_SEND to traceQUEUE_SET_SEND in order to tell them apart from other traceQUEUE_SEND trace points. Then set TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND in trcConfig.h to TRC_ACKNOWLEDGED to get rid of this error." +#endif /* (TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND != TRC_ACKNOWLEDGED) && (TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_10_3_0 || TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_10_3_1) && (configUSE_QUEUE_SETS == 1) */ + +uint32_t prvTraceGetQueueNumber(void* handle); + +#if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X_X) + +extern unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue ); +extern void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber ); +extern unsigned char ucQueueGetQueueType( xQueueHandle pxQueue ); + +uint32_t prvTraceGetQueueNumber(void* handle) +{ + return (uint32_t)ucQueueGetQueueNumber(handle); +} +#else +uint32_t prvTraceGetQueueNumber(void* handle) +{ + return (uint32_t)uxQueueGetQueueNumber(handle); +} +#endif /* (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X_X) */ + +uint8_t prvTraceGetQueueType(void* handle) +{ + // This is either declared in header file in FreeRTOS 8 and later, or as extern above + return ucQueueGetQueueType(handle); +} + +/* Tasks */ +uint16_t prvTraceGetTaskNumberLow16(void* handle) +{ + return TRACE_GET_LOW16(uxTaskGetTaskNumber(handle)); +} + +uint16_t prvTraceGetTaskNumberHigh16(void* handle) +{ + return TRACE_GET_HIGH16(uxTaskGetTaskNumber(handle)); +} + +void prvTraceSetTaskNumberLow16(void* handle, uint16_t value) +{ + vTaskSetTaskNumber(handle, TRACE_SET_LOW16(uxTaskGetTaskNumber(handle), value)); +} + +void prvTraceSetTaskNumberHigh16(void* handle, uint16_t value) +{ + vTaskSetTaskNumber(handle, TRACE_SET_HIGH16(uxTaskGetTaskNumber(handle), value)); +} + +uint16_t prvTraceGetQueueNumberLow16(void* handle) +{ + return TRACE_GET_LOW16(prvTraceGetQueueNumber(handle)); +} + +uint16_t prvTraceGetQueueNumberHigh16(void* handle) +{ + return TRACE_GET_HIGH16(prvTraceGetQueueNumber(handle)); +} + +void prvTraceSetQueueNumberLow16(void* handle, uint16_t value) +{ + vQueueSetQueueNumber(handle, TRACE_SET_LOW16(prvTraceGetQueueNumber(handle), value)); +} + +void prvTraceSetQueueNumberHigh16(void* handle, uint16_t value) +{ + vQueueSetQueueNumber(handle, TRACE_SET_HIGH16(prvTraceGetQueueNumber(handle), value)); +} + +#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +uint16_t prvTraceGetTimerNumberLow16(void* handle) +{ + return TRACE_GET_LOW16(uxTimerGetTimerNumber(handle)); +} + +uint16_t prvTraceGetTimerNumberHigh16(void* handle) +{ + return TRACE_GET_HIGH16(uxTimerGetTimerNumber(handle)); +} + +void prvTraceSetTimerNumberLow16(void* handle, uint16_t value) +{ + vTimerSetTimerNumber(handle, TRACE_SET_LOW16(uxTimerGetTimerNumber(handle), value)); +} + +void prvTraceSetTimerNumberHigh16(void* handle, uint16_t value) +{ + vTimerSetTimerNumber(handle, TRACE_SET_HIGH16(uxTimerGetTimerNumber(handle), value)); +} +#endif /* (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +uint16_t prvTraceGetEventGroupNumberLow16(void* handle) +{ + return TRACE_GET_LOW16(uxEventGroupGetNumber(handle)); +} + +uint16_t prvTraceGetEventGroupNumberHigh16(void* handle) +{ + return TRACE_GET_HIGH16(uxEventGroupGetNumber(handle)); +} + +void prvTraceSetEventGroupNumberLow16(void* handle, uint16_t value) +{ + vEventGroupSetNumber(handle, TRACE_SET_LOW16(uxEventGroupGetNumber(handle), value)); +} + +void prvTraceSetEventGroupNumberHigh16(void* handle, uint16_t value) +{ + vEventGroupSetNumber(handle, TRACE_SET_HIGH16(uxEventGroupGetNumber(handle), value)); +} +#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +uint16_t prvTraceGetStreamBufferNumberLow16(void* handle) +{ + return TRACE_GET_LOW16(uxStreamBufferGetStreamBufferNumber(handle)); +} + +uint16_t prvTraceGetStreamBufferNumberHigh16(void* handle) +{ + return TRACE_GET_HIGH16(uxStreamBufferGetStreamBufferNumber(handle)); +} + +void prvTraceSetStreamBufferNumberLow16(void* handle, uint16_t value) +{ + vStreamBufferSetStreamBufferNumber(handle, TRACE_SET_LOW16(uxStreamBufferGetStreamBufferNumber(handle), value)); +} + +void prvTraceSetStreamBufferNumberHigh16(void* handle, uint16_t value) +{ + vStreamBufferSetStreamBufferNumber(handle, TRACE_SET_HIGH16(uxStreamBufferGetStreamBufferNumber(handle), value)); +} +#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9) + +#define CS_TYPE_NONE 0 +#define CS_TYPE_TASK 1 +#define CS_TYPE_ISR_MASK_CHANGED 2 +#define CS_TYPE_ISR_MASK_NOT_CHANGED 3 + +#define CS_TYPE_INVALID 0xFFFFFFFF + +int cortex_a9_r5_enter_critical(void) +{ + uint32_t cs_type = CS_TYPE_INVALID; + + if ((prvGetCPSR() & 0x001F) == 0x13) // CSPR (ASPR) mode = SVC + { + /* Executing in an ISR other than the context-switch (where interrupts might have been enabled, motivating a critical section). */ + if (ulPortSetInterruptMask() == pdTRUE) + { + cs_type = CS_TYPE_ISR_MASK_NOT_CHANGED; + } + else + { + cs_type = CS_TYPE_ISR_MASK_CHANGED; + } + } + else if (uiTraceSystemState == TRC_STATE_IN_TASKSWITCH) + { + // In the context-switch code. All interrupts are already masked here, so don't modify the mask. + cs_type = CS_TYPE_NONE; + } + else if (uiTraceSystemState != TRC_STATE_IN_TASKSWITCH) + { + // Not within ISR or task-switch context, use a regular critical section. + vPortEnterCritical(); + cs_type = CS_TYPE_TASK; + } + + return cs_type; +} + +void cortex_a9_r5_exit_critical(int cs_type) +{ + switch (cs_type) + { + case CS_TYPE_TASK: + vPortExitCritical(); + break; + + case CS_TYPE_ISR_MASK_CHANGED: + vPortClearInterruptMask(pdFALSE); // pdFALSE means it will reset the IRQ mask. + break; + + case CS_TYPE_ISR_MASK_NOT_CHANGED: + case CS_TYPE_NONE: + // No action in these two cases. + break; + + default: + // Error, should not be possible; + for (;;); + } +} +#endif + +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) + +typedef struct { + void* tcb; + uint32_t uiPreviousLowMark; +} TaskStackMonitorEntry_t; + +TaskStackMonitorEntry_t tasksInStackMonitor[TRC_CFG_STACK_MONITOR_MAX_TASKS] = { { NULL } }; + +int tasksNotIncluded = 0; + +void prvAddTaskToStackMonitor(void* task) +{ + int i; + int foundEmptySlot = 0; + + // find an empty slot + for (i = 0; i < TRC_CFG_STACK_MONITOR_MAX_TASKS; i++) + { + if (tasksInStackMonitor[i].tcb == NULL) + { + tasksInStackMonitor[i].tcb = task; + tasksInStackMonitor[i].uiPreviousLowMark = 0xFFFFFFFF; + foundEmptySlot = 1; + break; + } + } + + if (foundEmptySlot == 0) + { + tasksNotIncluded++; + } +} + +void prvRemoveTaskFromStackMonitor(void* task) +{ + int i; + + for (i = 0; i < TRC_CFG_STACK_MONITOR_MAX_TASKS; i++) + { + if (tasksInStackMonitor[i].tcb == task) + { + tasksInStackMonitor[i].tcb = NULL; + tasksInStackMonitor[i].uiPreviousLowMark = 0; + } + } +} + +void prvReportStackUsage() +{ + static int i = 0; /* Static index used to loop over the monitored tasks */ + int count = 0; /* The number of generated reports */ + int initial = i; /* Used to make sure we break if we are back at the inital value */ + + do + { + /* Check the current spot */ + if (tasksInStackMonitor[i].tcb != NULL) + { + /* Get the amount of unused stack */ + uint32_t unusedStackSpace = uxTaskGetStackHighWaterMark((TaskType)tasksInStackMonitor[i].tcb); + + /* Store for later use */ + if (tasksInStackMonitor[i].uiPreviousLowMark > unusedStackSpace) + tasksInStackMonitor[i].uiPreviousLowMark = unusedStackSpace; + +#if TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT + prvTraceStoreKernelCallWithParam(TRACE_UNUSED_STACK, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(tasksInStackMonitor[i].tcb), tasksInStackMonitor[i].uiPreviousLowMark); +#else /* TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT */ + prvTraceStoreEvent2(PSF_EVENT_UNUSED_STACK, (uint32_t)tasksInStackMonitor[i].tcb, tasksInStackMonitor[i].uiPreviousLowMark); +#endif /* TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT */ + + count++; + } + + i = (i + 1) % TRC_CFG_STACK_MONITOR_MAX_TASKS; // Move i beyond this task + } while (count < TRC_CFG_STACK_MONITOR_MAX_REPORTS && i != initial); +} +#endif /* defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +static void* pCurrentTCB = NULL; + +/* Monitored by TzCtrl task, that give warnings as User Events */ +extern volatile uint32_t NoRoomForSymbol; +extern volatile uint32_t NoRoomForObjectData; +extern volatile uint32_t LongestSymbolName; +extern volatile uint32_t MaxBytesTruncated; + +/* User Event Channel for giving warnings regarding NoRoomForSymbol etc. */ +traceString trcWarningChannel; + +#define TRC_PORT_MALLOC(size) pvPortMalloc(size) + +TRC_STREAM_PORT_ALLOCATE_FIELDS() + +/* Called by TzCtrl task periodically (Normally every 100 ms) */ +static void prvCheckRecorderStatus(void); + +extern void prvTraceWarning(int errCode); + +/******************************************************************************* + * vTraceEnable + * + * Function that enables the tracing and creates the control task. It will halt + * execution until a Start command has been received if haltUntilStart is true. + * + ******************************************************************************/ +void vTraceEnable(int startOption) +{ + int32_t bytes = 0; + int32_t status; + extern uint32_t RecorderEnabled; + TracealyzerCommandType msg; + + /* Only do this first time...*/ + if (HandleTzCtrl == NULL) + { + TRC_STREAM_PORT_INIT(); + + /* The #WFR channel means "Warnings from Recorder" and + * is used to store warnings and errors from the recorder. + * The abbreviation #WFR is used instead of the longer full name, + * to avoid truncation by small slots in the symbol table. + * This is translated in Tracealyzer and shown as the full name, + * "Warnings from Recorder". + * + * Note: Requires that TRC_CFG_INCLUDE_USER_EVENTS is 1. */ + + trcWarningChannel = xTraceRegisterString("#WFR"); + + /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */ + #if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1) + HandleTzCtrl = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl); + #else + xTaskCreate( TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl ); + #endif + + if (HandleTzCtrl == NULL) + { + prvTraceError(PSF_ERROR_TZCTRLTASK_NOT_CREATED); + } + } + + if (startOption == TRC_START_AWAIT_HOST) + { + /* We keep trying to read commands until the recorder has been started */ + do + { + bytes = 0; + + status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes); + + if (status != 0) + { + prvTraceWarning(PSF_WARNING_STREAM_PORT_READ); + } + + if ((status == 0) && (bytes == sizeof(TracealyzerCommandType))) + { + if (prvIsValidCommand(&msg)) + { + if (msg.cmdCode == CMD_SET_ACTIVE && msg.param1 == 1) + { + /* On start, init and reset the timestamping */ + TRC_PORT_SPECIFIC_INIT(); + } + + prvProcessCommand(&msg); + } + } + } + while (RecorderEnabled == 0); + } + else if (startOption == TRC_START) + { + /* We start streaming directly - this assumes that the interface is ready! */ + TRC_PORT_SPECIFIC_INIT(); + + msg.cmdCode = CMD_SET_ACTIVE; + msg.param1 = 1; + prvProcessCommand(&msg); + } + else + { + /* On TRC_INIT */ + TRC_PORT_SPECIFIC_INIT(); + } +} + +#if (TRC_CFG_SCHEDULING_ONLY == 0) +/******************************************************************************* + * vTraceSetQueueName(void* object, const char* name) + * + * Parameter object: pointer to the Queue that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for Queue objects for display in Tracealyzer. + ******************************************************************************/ +void vTraceSetQueueName(void* object, const char* name) +{ + vTraceStoreKernelObjectName(object, name); +} + +/******************************************************************************* + * vTraceSetSemaphoreName(void* object, const char* name) + * + * Parameter object: pointer to the Semaphore that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for Semaphore objects for display in Tracealyzer. + ******************************************************************************/ +void vTraceSetSemaphoreName(void* object, const char* name) +{ + vTraceStoreKernelObjectName(object, name); +} + +/******************************************************************************* + * vTraceSetMutexName(void* object, const char* name) + * + * Parameter object: pointer to the Mutex that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for Mutex objects for display in Tracealyzer. + ******************************************************************************/ +void vTraceSetMutexName(void* object, const char* name) +{ + vTraceStoreKernelObjectName(object, name); +} + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) +/******************************************************************************* +* vTraceSetEventGroupName(void* object, const char* name) +* +* Parameter object: pointer to the vTraceSetEventGroupName that shall be named +* Parameter name: the name to set (const string literal) +* +* Sets a name for EventGroup objects for display in Tracealyzer. +******************************************************************************/ +void vTraceSetEventGroupName(void* object, const char* name) +{ + vTraceStoreKernelObjectName(object, name); +} +#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) */ + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +/******************************************************************************* +* vTraceSetStreamBufferName(void* object, const char* name) +* +* Parameter object: pointer to the StreamBuffer that shall be named +* Parameter name: the name to set (const string literal) +* +* Sets a name for StreamBuffer objects for display in Tracealyzer. +******************************************************************************/ +void vTraceSetStreamBufferName(void* object, const char* name) +{ + vTraceStoreKernelObjectName(object, name); +} + +/******************************************************************************* +* vTraceSetMessageBufferName(void* object, const char* name) +* +* Parameter object: pointer to the MessageBuffer that shall be named +* Parameter name: the name to set (const string literal) +* +* Sets a name for MessageBuffer objects for display in Tracealyzer. +******************************************************************************/ +void vTraceSetMessageBufferName(void* object, const char* name) +{ + vTraceStoreKernelObjectName(object, name); +} +#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */ + +/******************************************************************************* + * prvGetCurrentTaskHandle + * + * Function that returns the handle to the currently executing task. + * + ******************************************************************************/ +void* prvTraceGetCurrentTaskHandle(void) +{ + return xTaskGetCurrentTaskHandle(); +} + +/******************************************************************************* + * prvIsNewTCB + * + * Tells if this task is already executing, or if there has been a task-switch. + * Assumed to be called within a trace hook in kernel context. + ******************************************************************************/ +uint32_t prvIsNewTCB(void* pNewTCB) +{ + if (pCurrentTCB != pNewTCB) + { + pCurrentTCB = pNewTCB; + return 1; + } + return 0; +} + +/******************************************************************************* + * prvTraceIsSchedulerSuspended + * + * Returns true if the RTOS scheduler currently is disabled, thus preventing any + * task-switches from occurring. Only called from vTraceStoreISREnd. + ******************************************************************************/ +unsigned char prvTraceIsSchedulerSuspended(void) +{ + /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs, + INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in + FreeRTOSConfig.h for this function to be available. */ + + return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED; +} + +/******************************************************************************* + * prvCheckRecorderStatus + * + * Called by TzCtrl task periodically (every 100 ms - seems reasonable). + * Checks a number of diagnostic variables and give warnings as user events, + * in most cases including a suggested solution. + ******************************************************************************/ +static void prvCheckRecorderStatus(void) +{ +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) + if (tasksNotIncluded > 0) + { + prvTraceWarning(PSF_WARNING_STACKMON_NO_SLOTS); + tasksNotIncluded = 0; + } +#endif /* defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ + + if (NoRoomForSymbol > 0) + { + prvTraceWarning(PSF_WARNING_SYMBOL_TABLE_SLOTS); + NoRoomForSymbol = 0; + } + + if (NoRoomForObjectData > 0) + { + prvTraceWarning(PSF_WARNING_OBJECT_DATA_SLOTS); + NoRoomForObjectData = 0; + } + + if (LongestSymbolName > (TRC_CFG_SYMBOL_MAX_LENGTH)) + { + prvTraceWarning(PSF_WARNING_SYMBOL_MAX_LENGTH); + LongestSymbolName = 0; + } + + if (MaxBytesTruncated > 0) + { + prvTraceWarning(PSF_WARNING_STRING_TOO_LONG); + MaxBytesTruncated = 0; + } +} + +/******************************************************************************* + * TzCtrl + * + * Task for sending the trace data from the internal buffer to the stream + * interface (assuming TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) and for + * receiving commands from Tracealyzer. Also does some diagnostics. + ******************************************************************************/ +static portTASK_FUNCTION( TzCtrl, pvParameters ) +{ + TracealyzerCommandType msg; + int32_t bytes = 0; + int32_t status = 0; + (void)pvParameters; + + while (1) + { + do + { + /* Listen for new commands */ + bytes = 0; + status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes); + + if (status != 0) + { + /* The connection has failed, stop tracing */ + vTraceStop(); + } + + if ((status == 0) && (bytes == sizeof(TracealyzerCommandType))) + { + if (prvIsValidCommand(&msg)) + { + prvProcessCommand(&msg); /* Start or Stop currently... */ + } + } + +/* If the internal buffer is disabled, the COMMIT macro instead sends the data directly + from the "event functions" (using TRC_STREAM_PORT_WRITE_DATA). */ +#if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) + /* If there is a buffer page, this sends it to the streaming interface using TRC_STREAM_PORT_WRITE_DATA. */ + bytes = prvPagedEventBufferTransfer(); +#endif + + /* If there was data sent or received (bytes != 0), loop around and repeat, if there is more data to send or receive. + Otherwise, step out of this loop and sleep for a while. */ + + } while (bytes != 0); + + if (xTraceIsRecordingEnabled()) + { + prvCheckRecorderStatus(); + prvReportStackUsage(); + } + + vTaskDelay(TRC_CFG_CTRL_TASK_DELAY); + } +} + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + +/* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */ +int uiInEventGroupSetBitsFromISR = 0; + +/****************************************************************************** + * TraceQueueClassTable + * Translates a FreeRTOS QueueType into trace objects classes (TRACE_CLASS_). + * Has one entry for each QueueType, gives TRACE_CLASS ID. + ******************************************************************************/ +traceObjectClass TraceQueueClassTable[5] = { + TRACE_CLASS_QUEUE, + TRACE_CLASS_MUTEX, + TRACE_CLASS_SEMAPHORE, + TRACE_CLASS_SEMAPHORE, + TRACE_CLASS_MUTEX +}; + +#if (TRC_CFG_SCHEDULING_ONLY == 0) +/******************************************************************************* + * vTraceSetQueueName(void* object, const char* name) + * + * Parameter object: pointer to the Queue that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for Queue objects for display in Tracealyzer. + ******************************************************************************/ +void vTraceSetQueueName(void* object, const char* name) +{ + prvTraceSetObjectName(TRACE_CLASS_QUEUE, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name); +} + +/******************************************************************************* + * vTraceSetSemaphoreName(void* object, const char* name) + * + * Parameter object: pointer to the Semaphore that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for Semaphore objects for display in Tracealyzer. + ******************************************************************************/ +void vTraceSetSemaphoreName(void* object, const char* name) +{ + prvTraceSetObjectName(TRACE_CLASS_SEMAPHORE, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name); +} + +/******************************************************************************* + * vTraceSetMutexName(void* object, const char* name) + * + * Parameter object: pointer to the Mutex that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for Semaphore objects for display in Tracealyzer. + ******************************************************************************/ +void vTraceSetMutexName(void* object, const char* name) +{ + prvTraceSetObjectName(TRACE_CLASS_MUTEX, TRACE_GET_OBJECT_NUMBER(QUEUE, object), name); +} + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) +/******************************************************************************* +* vTraceSetEventGroupName(void* object, const char* name) +* +* Parameter object: pointer to the EventGroup that shall be named +* Parameter name: the name to set (const string literal) +* +* Sets a name for EventGroup objects for display in Tracealyzer. +******************************************************************************/ +void vTraceSetEventGroupName(void* object, const char* name) +{ + prvTraceSetObjectName(TRACE_CLASS_EVENTGROUP, TRACE_GET_OBJECT_NUMBER(EVENTGROUP, object), name); +} +#endif /* (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) */ + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) +/******************************************************************************* +* vTraceSetStreamBufferName(void* object, const char* name) +* +* Parameter object: pointer to the StreamBuffer that shall be named +* Parameter name: the name to set (const string literal) +* +* Sets a name for StreamBuffer objects for display in Tracealyzer. +******************************************************************************/ +void vTraceSetStreamBufferName(void* object, const char* name) +{ + prvTraceSetObjectName(TRACE_CLASS_STREAMBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, object), name); +} + +/******************************************************************************* +* vTraceSetMessageBufferName(void* object, const char* name) +* +* Parameter object: pointer to the MessageBuffer that shall be named +* Parameter name: the name to set (const string literal) +* +* Sets a name for MessageBuffer objects for display in Tracealyzer. +******************************************************************************/ +void vTraceSetMessageBufferName(void* object, const char* name) +{ + prvTraceSetObjectName(TRACE_CLASS_MESSAGEBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, object), name); +} +#endif /* (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) */ + +#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) */ + +void* prvTraceGetCurrentTaskHandle() +{ + return xTaskGetCurrentTaskHandle(); +} + +/****************************************************************************** +* vTraceEnable(int startOption) - snapshot mode +* +* Initializes and optionally starts the trace, depending on the start option. +* To use the trace recorder, the startup must call vTraceEnable before any RTOS +* calls are made (including "create" calls). Three start options are provided: +* +* TRC_START: Starts the tracing directly. In snapshot mode this allows for +* starting the trace at any point in your code, assuming vTraceEnable(TRC_INIT) +* has been called in the startup. +* Can also be used for streaming without Tracealyzer control, e.g. to a local +* flash file system (assuming such a "stream port", see trcStreamingPort.h). +* +* TRC_INIT: Initializes the trace recorder, but does not start the tracing. +* In snapshot mode, this must be followed by a vTraceEnable(TRC_START) sometime +* later. +* +* Usage examples, in snapshot mode: +* +* Snapshot trace, from startup: +* <board init> +* vTraceEnable(TRC_START); +* <RTOS init> +* +* Snapshot trace, from a later point: +* <board init> +* vTraceEnable(TRC_INIT); +* <RTOS init> +* ... +* vTraceEnable(TRC_START); // e.g., in task context, at some relevant event +* +* +* Note: See other implementation of vTraceEnable in trcStreamingRecorder.c +******************************************************************************/ +void vTraceEnable(int startOption) +{ + prvTraceInitTraceData(); + + if (startOption == TRC_START) + { + vTraceStart(); + } + else if (startOption == TRC_START_AWAIT_HOST) + { + prvTraceError("vTraceEnable(TRC_START_AWAIT_HOST) not allowed in Snapshot mode"); + } + else if (startOption != TRC_INIT) + { + prvTraceError("Unexpected argument to vTraceEnable (snapshot mode)"); + } + +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) + /* Creates the TzCtrl task - reports unsed stack */ + if (HandleTzCtrl == NULL) + { +#if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1) + HandleTzCtrl = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl); +#else /* defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1) */ + xTaskCreate(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl); +#endif /* defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1) */ + } + +#endif /* defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ +} + +/******************************************************************************* +* TzCtrl +* +* Task for sending the trace data from the internal buffer to the stream +* interface (assuming TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) and for +* receiving commands from Tracealyzer. Also does some diagnostics. +******************************************************************************/ +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) +static portTASK_FUNCTION(TzCtrl, pvParameters) +{ + (void)pvParameters; + + while (1) + { + if (xTraceIsRecordingEnabled()) + { + prvReportStackUsage(); + } + + vTaskDelay(TRC_CFG_CTRL_TASK_DELAY); + } +} +#endif + +/* Initialization of the object property table */ +void vTraceInitObjectPropertyTable() +{ + RecorderDataPtr->ObjectPropertyTable.NumberOfObjectClasses = TRACE_NCLASSES; + RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[0] = TRC_CFG_NQUEUE; + RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[1] = TRC_CFG_NSEMAPHORE; + RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = TRC_CFG_NMUTEX; + RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = TRC_CFG_NTASK; + RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = TRC_CFG_NISR; + RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = TRC_CFG_NTIMER; + RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = TRC_CFG_NEVENTGROUP; + RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[7] = TRC_CFG_NSTREAMBUFFER; + RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[8] = TRC_CFG_NMESSAGEBUFFER; + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = TRC_CFG_NAME_LEN_QUEUE; + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = TRC_CFG_NAME_LEN_SEMAPHORE; + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = TRC_CFG_NAME_LEN_MUTEX; + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = TRC_CFG_NAME_LEN_TASK; + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = TRC_CFG_NAME_LEN_ISR; + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = TRC_CFG_NAME_LEN_TIMER; + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = TRC_CFG_NAME_LEN_EVENTGROUP; + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[7] = TRC_CFG_NAME_LEN_STREAMBUFFER; + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[8] = TRC_CFG_NAME_LEN_MESSAGEBUFFER; + 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.TotalPropertyBytesPerClass[5] = PropertyTableSizeTimer; + RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[6] = PropertyTableSizeEventGroup; + RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[7] = PropertyTableSizeStreamBuffer; + RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[8] = PropertyTableSizeMessageBuffer; + 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.StartIndexOfClass[5] = StartIndexTimer; + RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[6] = StartIndexEventGroup; + RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[7] = StartIndexStreamBuffer; + RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[8] = StartIndexMessageBuffer; + RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE; +} + +/* Initialization of the handle mechanism, see e.g, prvTraceGetObjectHandle */ +void vTraceInitObjectHandleStack() +{ + objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0; + objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = (TRC_CFG_NQUEUE); + objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE); + objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX); + objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK); + objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR); + objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER); + objectHandleStacks.indexOfNextAvailableHandle[7] = objectHandleStacks.lowestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP); + objectHandleStacks.indexOfNextAvailableHandle[8] = objectHandleStacks.lowestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER); + + objectHandleStacks.highestIndexOfClass[0] = (TRC_CFG_NQUEUE) - 1; + objectHandleStacks.highestIndexOfClass[1] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) - 1; + objectHandleStacks.highestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) - 1; + objectHandleStacks.highestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) - 1; + objectHandleStacks.highestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) - 1; + objectHandleStacks.highestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) - 1; + objectHandleStacks.highestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) - 1; + objectHandleStacks.highestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) - 1; + objectHandleStacks.highestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) + (TRC_CFG_NMESSAGEBUFFER) - 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 TRC_CFG_NTASK in trcSnapshotConfig.h"; + case TRACE_CLASS_ISR: + return "Not enough ISR handles - increase TRC_CFG_NISR in trcSnapshotConfig.h"; + case TRACE_CLASS_SEMAPHORE: + return "Not enough SEMAPHORE handles - increase TRC_CFG_NSEMAPHORE in trcSnapshotConfig.h"; + case TRACE_CLASS_MUTEX: + return "Not enough MUTEX handles - increase TRC_CFG_NMUTEX in trcSnapshotConfig.h"; + case TRACE_CLASS_QUEUE: + return "Not enough QUEUE handles - increase TRC_CFG_NQUEUE in trcSnapshotConfig.h"; + case TRACE_CLASS_TIMER: + return "Not enough TIMER handles - increase TRC_CFG_NTIMER in trcSnapshotConfig.h"; + case TRACE_CLASS_EVENTGROUP: + return "Not enough EVENTGROUP handles - increase TRC_CFG_NEVENTGROUP in trcSnapshotConfig.h"; + case TRACE_CLASS_STREAMBUFFER: + return "Not enough STREAMBUFFER handles - increase TRC_CFG_NSTREAMBUFFER in trcSnapshotConfig.h"; + case TRACE_CLASS_MESSAGEBUFFER: + return "Not enough MESSAGEBUFFER handles - increase TRC_CFG_NMESSAGEBUFFER in trcSnapshotConfig.h"; + default: + return "pszTraceGetErrorHandles: Invalid objectclass!"; + } +} + +/******************************************************************************* + * prvTraceIsSchedulerSuspended + * + * Returns true if the RTOS scheduler currently is disabled, thus preventing any + * task-switches from occurring. Only called from vTraceStoreISREnd. + ******************************************************************************/ +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) +unsigned char prvTraceIsSchedulerSuspended(void) +{ + /* Assumed to be available in FreeRTOS. According to the FreeRTOS docs, + INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in + FreeRTOSConfig.h for this function to be available. */ + + return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED; +} +#endif + +#endif /* Snapshot mode */ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c index 9eec9d2ed..a2513b08a 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c @@ -1,3105 +1,3074 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcSnapshotRecorder.c
- *
- * The generic core of the trace recorder's snapshot mode.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#include "trcRecorder.h"
-
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
-
-#if (TRC_USE_TRACEALYZER_RECORDER == 1)
-
-#include <string.h>
-#include <stdarg.h>
-#include <stdint.h>
-
-#if ((TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR) || (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR))
- #error "CUSTOM timestamping mode is not (yet) supported in snapshot mode!"
-#endif
-
-/* DO NOT CHANGE */
-#define TRACE_MINOR_VERSION 5
-#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
-static traceHandle isrstack[TRC_CFG_MAX_ISR_NESTING];
-int32_t isPendingContextSwitch = 0;
-#endif /* (TRC_CFG_INCLUDE_ISR_TRACING == 1) */
-
-#if !defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1
-static int readyEventsEnabled = 1;
-#endif /*!defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1*/
-
-/*******************************************************************************
- * 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;
-
-uint32_t trace_disable_timestamp = 0;
-
-static uint32_t last_timestamp = 0;
-
-/* Flag that shows if inside a critical section of the recorder */
-volatile int recorder_busy = 0;
-
-/* Holds the value set by vTraceSetFrequency */
-uint32_t timestampFrequency = 0;
-
-/* The last error message of the recorder. NULL if no error message. */
-const char* traceErrorMessage = NULL;
-
-int8_t nISRactive = 0;
-
-traceHandle handle_of_last_logged_task = 0;
-
-/* Called when the recorder is stopped, set by vTraceSetStopHook. */
-TRACE_STOP_HOOK vTraceStopHookPtr = (TRACE_STOP_HOOK)0;
-
-uint16_t CurrentFilterMask = 0xFFFF;
-
-uint16_t CurrentFilterGroup = FilterGroup0;
-
-extern int8_t nISRactive;
-
-extern traceHandle handle_of_last_logged_task;
-
-/*************** Private Functions *******************************************/
-static void prvStrncpy(char* dst, const char* src, uint32_t maxLength);
-static uint8_t prvTraceGetObjectState(uint8_t objectclass, traceHandle id);
-static void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength);
-static void* prvTraceNextFreeEventBufferSlot(void);
-static uint16_t prvTraceGetDTS(uint16_t param_maxDTS);
-static traceString prvTraceOpenSymbol(const char* name, traceString userEventChannel);
-static void prvTraceUpdateCounters(void);
-
-void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_size);
-
-#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
-static void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nEntries);
-#endif
-
-static traceString prvTraceCreateSymbolTableEntry(const char* name,
- uint8_t crc6,
- uint8_t len,
- traceString channel);
-
-static traceString prvTraceLookupSymbolTableEntry(const char* name,
- uint8_t crc6,
- uint8_t len,
- traceString channel);
-
-
-#if (TRC_CFG_INCLUDE_ISR_TRACING == 0)
-/* ISR tracing is turned off */
-void prvTraceIncreaseISRActive(void);
-void prvTraceDecreaseISRActive(void);
-#endif /*(TRC_CFG_INCLUDE_ISR_TRACING == 0)*/
-
-#if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1)
-static uint8_t prvTraceGet8BitHandle(traceHandle handle);
-#else
-#define prvTraceGet8BitHandle(x) ((uint8_t)x)
-#endif
-
-
-#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)
-static uint32_t heapMemUsage = 0;
-#endif
-
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-static uint32_t prvTraceGetParam(uint32_t, uint32_t);
-#endif
-
-/*******************************************************************************
- * prvTraceInitTraceData
- *
- * 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
- * using a static declaration.
- ******************************************************************************/
-static void prvTraceInitTraceData(void);
-
-/*******************************************************************************
- * prvTracePortGetTimeStamp
- *
- * Returns the current time based on the HWTC macros which provide a hardware
- * isolation layer towards the hardware timer/counter.
- *
- * The HWTC macros and prvTracePortGetTimeStamp is the main porting issue
- * or the trace recorder library. Typically you should not need to change
- * the code of prvTracePortGetTimeStamp if using the HWTC macros.
- *
- ******************************************************************************/
-void prvTracePortGetTimeStamp(uint32_t *puiTimestamp);
-
-static void prvTraceTaskInstanceFinish(int8_t direct);
-
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))
-static void vTracePrintF_Helper(traceString eventLabel, const char* formatStr, va_list vl);
-
-#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)
-static void vTraceUBData_Helper(traceUBChannel channelPair, va_list vl);
-static void prvTraceUBHelper1(traceUBChannel channel, traceString eventLabel, traceString formatLabel, va_list vl);
-static void prvTraceUBHelper2(traceUBChannel channel, uint32_t* data, uint32_t noOfSlots);
-#endif /*(TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)*/
-#endif /* ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) */
-
-/********* Public Functions **************************************************/
-
-uint16_t uiIndexOfObject(traceHandle objecthandle, uint8_t objectclass);
-
-/*******************************************************************************
- * prvTraceError
- *
- * Called by various parts in the recorder. Stops the recorder and stores a
- * pointer to an error message, which is printed by the monitor task.
- ******************************************************************************/
-void prvTraceError(const char* msg);
-
-/******************************************************************************
-* vTraceEnable(int startOption) - snapshot mode
-*
-* Initializes and optionally starts the trace, depending on the start option.
-* To use the trace recorder, the startup must call vTraceEnable before any RTOS
-* calls are made (including "create" calls). Three start options are provided:
-*
-* TRC_START: Starts the tracing directly. In snapshot mode this allows for
-* starting the trace at any point in your code, assuming vTraceEnable(TRC_INIT)
-* has been called in the startup.
-* Can also be used for streaming without Tracealyzer control, e.g. to a local
-* flash file system (assuming such a "stream port", see trcStreamingPort.h).
-*
-* TRC_INIT: Initializes the trace recorder, but does not start the tracing.
-* In snapshot mode, this must be followed by a vTraceEnable(TRC_START) sometime
-* later.
-*
-* Usage examples, in snapshot mode:
-*
-* Snapshot trace, from startup:
-* <board init>
-* vTraceEnable(TRC_START);
-* <RTOS init>
-*
-* Snapshot trace, from a later point:
-* <board init>
-* vTraceEnable(TRC_INIT);
-* <RTOS init>
-* ...
-* vTraceEnable(TRC_START); // e.g., in task context, at some relevant event
-*
-*
-* Note: See other implementation of vTraceEnable in trcStreamingRecorder.c
-******************************************************************************/
-void vTraceEnable(int startOption)
-{
- prvTraceInitTraceData();
-
- if (startOption == TRC_START)
- {
- vTraceStart();
- }
- else if (startOption == TRC_START_AWAIT_HOST)
- {
- prvTraceError("vTraceEnable(TRC_START_AWAIT_HOST) not allowed in Snapshot mode");
- }
- else if (startOption != TRC_INIT)
- {
- prvTraceError("Unexpected argument to vTraceEnable (snapshot mode)");
- }
-}
-
-/*******************************************************************************
- * vTraceSetRecorderDataBuffer
- *
- * If custom allocation is used, this function must be called so the recorder
- * library knows where to save the trace data.
- ******************************************************************************/
-#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM)
-void vTraceSetRecorderDataBuffer(void* pRecorderData)
-{
- TRACE_ASSERT(pRecorderData != NULL, "vTraceSetRecorderDataBuffer, pRecorderData == NULL", TRC_UNUSED);
- RecorderDataPtr = pRecorderData;
-}
-#endif
-
-/*******************************************************************************
- * vTraceSetStopHook
- *
- * Sets a function to be called when the recorder is stopped. This can be used
- * to save the trace to a file system, if available. This is only implemented
- * for snapshot mode.
- ******************************************************************************/
-void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction)
-{
- vTraceStopHookPtr = stopHookFunction;
-}
-
-/*******************************************************************************
- * vTraceClear
- *
- * Resets the recorder. Only necessary if a restart is desired - this is not
- * needed in the startup initialization.
- ******************************************************************************/
-void vTraceClear(void)
-{
- TRACE_ALLOC_CRITICAL_SECTION();
- trcCRITICAL_SECTION_BEGIN();
- RecorderDataPtr->absTimeLastEventSecond = 0;
- RecorderDataPtr->absTimeLastEvent = 0;
- RecorderDataPtr->nextFreeIndex = 0;
- RecorderDataPtr->numEvents = 0;
- RecorderDataPtr->bufferIsFull = 0;
- traceErrorMessage = NULL;
- RecorderDataPtr->internalErrorOccured = 0;
- (void)memset(RecorderDataPtr->eventData, 0, RecorderDataPtr->maxEvents * 4);
- handle_of_last_logged_task = 0;
- trcCRITICAL_SECTION_END();
-}
-
-/*******************************************************************************
- * uiTraceStart
- *
- * Starts the recorder. The recorder will not be started if an error has been
- * indicated using prvTraceError, e.g. if any of the Nx constants in trcConfig.h
- * has a too small value (TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc).
- *
- * Returns 1 if the recorder was started successfully.
- * Returns 0 if the recorder start was prevented due to a previous internal
- * error. In that case, check xTraceGetLastError to get the error message.
- * Any error message is also presented when opening a trace file.
- *
- * This function is obsolete, but has been saved for backwards compatibility.
- * We recommend using vTraceEnable instead.
- ******************************************************************************/
-uint32_t uiTraceStart(void)
-{
- traceHandle handle;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- handle = 0;
-
- if (RecorderDataPtr == NULL)
- {
- TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized. Use vTraceEnable() instead!", 0);
- return 0;
- }
-
- if (RecorderDataPtr->recorderActive == 1)
- return 1; /* Already running */
-
- if (traceErrorMessage == NULL)
- {
- trcCRITICAL_SECTION_BEGIN();
- RecorderDataPtr->recorderActive = 1;
-
- handle = TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK());
- if (handle == 0)
- {
- /* This occurs if the scheduler is not yet started.
- This creates a dummy "(startup)" task entry internally in the
- recorder */
- handle = prvTraceGetObjectHandle(TRACE_CLASS_TASK);
- prvTraceSetObjectName(TRACE_CLASS_TASK, handle, "(startup)");
-
- prvTraceSetPriorityProperty(TRACE_CLASS_TASK, handle, 0);
- }
-
- prvTraceStoreTaskswitch(handle); /* Register the currently running task */
- trcCRITICAL_SECTION_END();
- }
-
- return RecorderDataPtr->recorderActive;
-}
-
-/*******************************************************************************
- * vTraceStart
- *
- * Starts the recorder. The recorder will not be started if an error has been
- * indicated using prvTraceError, e.g. if any of the Nx constants in trcConfig.h
- * has a too small value (TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc).
- *
- * This function is obsolete, but has been saved for backwards compatibility.
- * We recommend using vTraceEnable instead.
- ******************************************************************************/
-void vTraceStart(void)
-{
- (void)uiTraceStart();
-}
-
-/*******************************************************************************
- * vTraceStop
- *
- * Stops the recorder. The recording can be resumed by calling vTraceStart.
- * This does not reset the recorder. Use vTraceClear if that is desired.
- ******************************************************************************/
-void vTraceStop(void)
-{
- if (RecorderDataPtr != NULL)
- {
- RecorderDataPtr->recorderActive = 0;
- }
-
- if (vTraceStopHookPtr != (TRACE_STOP_HOOK)0)
- {
- (*vTraceStopHookPtr)(); /* An application call-back function. */
- }
-}
-
-/*******************************************************************************
-* xTraceIsRecordingEnabled
-* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0.
-******************************************************************************/
-int xTraceIsRecordingEnabled(void)
-{
- if (RecorderDataPtr != NULL)
- {
- return (int)RecorderDataPtr->recorderActive;
- }
- else
- {
- return 0;
- }
-}
-
-/*******************************************************************************
- * xTraceGetLastError
- *
- * Gives the last error message, if any. NULL if no error message is stored.
- * Any error message is also presented when opening a trace file.
- ******************************************************************************/
-const char* xTraceGetLastError(void)
-{
- return traceErrorMessage;
-}
-
-/*******************************************************************************
-* vTraceClearError
-*
-* Removes any previous error message generated by recorder calling prvTraceError.
-* By calling this function, it may be possible to start/restart the trace
-* despite errors in the recorder, but there is no guarantee that the trace
-* recorder will work correctly in that case, depending on the type of error.
-******************************************************************************/
-void vTraceClearError(void)
-{
- traceErrorMessage = NULL;
- if (RecorderDataPtr != NULL)
- {
- RecorderDataPtr->internalErrorOccured = 0;
- }
-}
-
-/*******************************************************************************
- * xTraceGetTraceBuffer
- *
- * Returns a pointer to the recorder data structure. Use this together with
- * uiTraceGetTraceBufferSize if you wish to implement an own store/upload
- * solution, e.g., in case a debugger connection is not available for uploading
- * the data.
- ******************************************************************************/
-void* xTraceGetTraceBuffer(void)
-{
- return RecorderDataPtr;
-}
-
-/*******************************************************************************
- * uiTraceGetTraceBufferSize
- *
- * Gets the size of the recorder data structure. For use together with
- * vTraceGetTraceBuffer if you wish to implement an own store/upload solution,
- * e.g., in case a debugger connection is not available for uploading the data.
- ******************************************************************************/
-uint32_t uiTraceGetTraceBufferSize(void)
-{
- return sizeof(RecorderDataType);
-}
-
-/******************************************************************************
- * prvTraceTaskInstanceFinish
- *
- * Private common function for the vTraceTaskInstanceFinishXXX functions.
- *****************************************************************************/
-static void prvTraceTaskInstanceFinish(int8_t direct)
-{
- TaskInstanceStatusEvent* tis;
- uint8_t dts45;
-
- TRACE_ALLOC_CRITICAL_SECTION();
-
- trcCRITICAL_SECTION_BEGIN();
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- {
- dts45 = (uint8_t)prvTraceGetDTS(0xFF);
- tis = (TaskInstanceStatusEvent*) prvTraceNextFreeEventBufferSlot();
- if (tis != NULL)
- {
- if (direct == 0)
- tis->type = TASK_INSTANCE_FINISHED_NEXT_KSE;
- else
- tis->type = TASK_INSTANCE_FINISHED_DIRECT;
-
- tis->dts = dts45;
- prvTraceUpdateCounters();
- }
- }
- trcCRITICAL_SECTION_END();
-}
-
-/******************************************************************************
- * vTraceInstanceFinishedNext(void)
- *
- * Marks the current task instance as finished on the next kernel call.
- *
- * If that kernel call is blocking, the instance ends after the blocking event
- * and the corresponding return event is then the start of the next instance.
- * If the kernel call is not blocking, the viewer instead splits the current
- * fragment right before the kernel call, which makes this call the first event
- * of the next instance.
- *
- * See also TRC_CFG_USE_IMPLICIT_IFE_RULES in trcConfig.h
- *
- * Example:
- *
- * while(1)
- * {
- * xQueueReceive(CommandQueue, &command, timeoutDuration);
- * processCommand(command);
- * vTraceInstanceFinishedNext();
- * }
- *****************************************************************************/
-void vTraceInstanceFinishedNext(void)
-{
- prvTraceTaskInstanceFinish(0);
-}
-
-/******************************************************************************
- * vTraceInstanceFinishedNow(void)
- *
- * Marks the current task instance as finished at this very instant.
- * This makes the viewer to splits the current fragment at this point and begin
- * a new actor instance.
- *
- * See also TRC_CFG_USE_IMPLICIT_IFE_RULES in trcConfig.h
- *
- * Example:
- *
- * This example will generate two instances for each loop iteration.
- * The first instance ends at vTraceInstanceFinishedNow(), while the second
- * instance ends at the next xQueueReceive call.
- *
- * while (1)
- * {
- * xQueueReceive(CommandQueue, &command, timeoutDuration);
- * ProcessCommand(command);
- * vTraceInstanceFinishedNow();
- * DoSometingElse();
- * vTraceInstanceFinishedNext();
- * }
- *****************************************************************************/
-void vTraceInstanceFinishedNow(void)
-{
- prvTraceTaskInstanceFinish(1);
-}
-
-/*******************************************************************************
- * Interrupt recording functions
- ******************************************************************************/
-
-#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
-
-/*******************************************************************************
- * xTraceSetISRProperties
- *
- * Stores a name and priority level for an Interrupt Service Routine, to allow
- * for better visualization. Returns a traceHandle used by vTraceStoreISRBegin.
- *
- * Example:
- * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt
- * ...
- * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1);
- * ...
- * void ISR_handler()
- * {
- * vTraceStoreISRBegin(Timer1Handle);
- * ...
- * vTraceStoreISREnd(0);
- * }
- ******************************************************************************/
- traceHandle xTraceSetISRProperties(const char* name, uint8_t priority)
-{
- static traceHandle handle = 0;
- TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0);
- TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "xTraceSetISRProperties: Invalid value for handle", 0);
- TRACE_ASSERT(name != NULL, "xTraceSetISRProperties: name == NULL", 0);
-
- handle++;
-
- prvTraceSetObjectName(TRACE_CLASS_ISR, handle, name);
- prvTraceSetPriorityProperty(TRACE_CLASS_ISR, handle, priority);
-
- return handle;
-}
-
-/*******************************************************************************
- * vTraceStoreISRBegin
- *
- * Registers the beginning of an Interrupt Service Routine, using a traceHandle
- * provided by xTraceSetISRProperties.
- *
- * Example:
- * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt
- * ...
- * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1);
- * ...
- * void ISR_handler()
- * {
- * vTraceStoreISRBegin(Timer1Handle);
- * ...
- * vTraceStoreISREnd(0);
- * }
- ******************************************************************************/
-void vTraceStoreISRBegin(traceHandle handle)
-{
- TRACE_ALLOC_CRITICAL_SECTION();
-
- if (recorder_busy)
- {
- /*************************************************************************
- * This occurs if an ISR calls a trace function, preempting a previous
- * trace call that is being processed in a different ISR or task.
- * If this occurs, there is probably a problem in the definition of the
- * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and
- * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt
- * and any other ISRs that calls the trace recorder directly or via
- * traced kernel functions. The ARM port disables all interrupts using the
- * PRIMASK register to avoid this issue.
- *************************************************************************/
- prvTraceError("vTraceStoreISRBegin - recorder busy! See code comment.");
- return;
- }
- trcCRITICAL_SECTION_BEGIN();
-
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- {
- uint16_t dts4;
-
- TRACE_ASSERT(handle != 0, "vTraceStoreISRBegin: Invalid ISR handle (NULL)", TRC_UNUSED);
- TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid ISR handle (> NISR)", TRC_UNUSED);
-
- dts4 = (uint16_t)prvTraceGetDTS(0xFFFF);
-
- if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
- {
- if (nISRactive < TRC_CFG_MAX_ISR_NESTING)
- {
- TSEvent* ts;
- uint8_t hnd8 = prvTraceGet8BitHandle(handle);
- isrstack[nISRactive] = handle;
- nISRactive++;
- ts = (TSEvent*)prvTraceNextFreeEventBufferSlot();
- if (ts != NULL)
- {
- ts->type = TS_ISR_BEGIN;
- ts->dts = dts4;
- ts->objHandle = hnd8;
- prvTraceUpdateCounters();
- }
- }
- else
- {
- /* This should not occur unless something is very wrong */
- prvTraceError("Too many nested interrupts!");
- }
- }
- }
- trcCRITICAL_SECTION_END();
-}
-
-/*******************************************************************************
- * vTraceStoreISREnd
- *
- * Registers the end of an Interrupt Service Routine.
- *
- * The parameter pendingISR indicates if the interrupt has requested a
- * task-switch (= 1), e.g., by signaling a semaphore. Otherwise (= 0) the
- * interrupt is assumed to return to the previous context.
- *
- * Example:
- * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
- * traceHandle traceHandleIsrTimer1 = 0; // The ID set by the recorder
- * ...
- * traceHandleIsrTimer1 = xTraceSetISRProperties("ISRTimer1", PRIO_OF_ISR_TIMER1);
- * ...
- * void ISR_handler()
- * {
- * vTraceStoreISRBegin(traceHandleIsrTimer1);
- * ...
- * vTraceStoreISREnd(0);
- * }
- ******************************************************************************/
-void vTraceStoreISREnd(int pendingISR)
-{
- TSEvent* ts;
- uint16_t dts5;
- uint8_t hnd8 = 0, type = 0;
-
- TRACE_ALLOC_CRITICAL_SECTION();
-
- if (! RecorderDataPtr->recorderActive || ! handle_of_last_logged_task)
- {
- return;
- }
-
- if (recorder_busy)
- {
- /*************************************************************************
- * This occurs if an ISR calls a trace function, preempting a previous
- * trace call that is being processed in a different ISR or task.
- * If this occurs, there is probably a problem in the definition of the
- * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and
- * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt
- * and any other ISRs that calls the trace recorder directly or via
- * traced kernel functions. The ARM port disables all interrupts using the
- * PRIMASK register to avoid this issue.
- *************************************************************************/
- prvTraceError("vTraceStoreISREnd - recorder busy! See code comment.");
- return;
- }
-
- if (nISRactive == 0)
- {
- prvTraceError("Unmatched call to vTraceStoreISREnd (nISRactive == 0, expected > 0)");
- return;
- }
-
- trcCRITICAL_SECTION_BEGIN();
- isPendingContextSwitch |= pendingISR; /* Is there a pending context switch right now? */
- nISRactive--;
- if (nISRactive > 0)
- {
- /* Return to another ISR */
- type = TS_ISR_RESUME;
- hnd8 = prvTraceGet8BitHandle(isrstack[nISRactive - 1]); /* isrstack[nISRactive] is the handle of the ISR we're currently exiting. isrstack[nISRactive - 1] is the handle of the ISR that was executing previously. */
- }
- else if ((isPendingContextSwitch == 0) || (prvTraceIsSchedulerSuspended()))
- {
- /* Return to interrupted task, if no context switch will occur in between. */
- type = TS_TASK_RESUME;
- hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task);
- }
-
- if (type != 0)
- {
- dts5 = (uint16_t)prvTraceGetDTS(0xFFFF);
- ts = (TSEvent*)prvTraceNextFreeEventBufferSlot();
- if (ts != NULL)
- {
- ts->type = type;
- ts->objHandle = hnd8;
- ts->dts = dts5;
- prvTraceUpdateCounters();
- }
- }
-
- trcCRITICAL_SECTION_END();
-}
-
-#else
-
-/* ISR tracing is turned off */
-void prvTraceIncreaseISRActive(void)
-{
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- nISRactive++;
-}
-
-void prvTraceDecreaseISRActive(void)
-{
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- nISRactive--;
-}
-#endif /* (TRC_CFG_INCLUDE_ISR_TRACING == 1)*/
-
-
-/********************************************************************************/
-/* User Event functions */
-/********************************************************************************/
-
-#define MAX_ARG_SIZE (4+32)
-
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))
-static uint8_t writeInt8(void * buffer, uint8_t i, uint8_t value)
-{
- TRACE_ASSERT(buffer != NULL, "writeInt8: buffer == NULL", 0);
-
- if (i >= MAX_ARG_SIZE)
- {
- return 255;
- }
-
- ((uint8_t*)buffer)[i] = value;
-
- if (i + 1 > MAX_ARG_SIZE)
- {
- return 255;
- }
-
- return ((uint8_t) (i + 1));
-}
-#endif
-
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))
-static uint8_t writeInt16(void * buffer, uint8_t i, uint16_t value)
-{
- TRACE_ASSERT(buffer != NULL, "writeInt16: buffer == NULL", 0);
-
- /* Align to multiple of 2 */
- while ((i % 2) != 0)
- {
- if (i >= MAX_ARG_SIZE)
- {
- return 255;
- }
-
- ((uint8_t*)buffer)[i] = 0;
- i++;
- }
-
- if (i + 2 > MAX_ARG_SIZE)
- {
- return 255;
- }
-
- ((uint16_t*)buffer)[i/2] = value;
-
- return ((uint8_t) (i + 2));
-}
-#endif
-
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))
-static uint8_t writeInt32(void * buffer, uint8_t i, uint32_t value)
-{
- TRACE_ASSERT(buffer != NULL, "writeInt32: buffer == NULL", 0);
-
- /* A 32 bit value should begin at an even 4-byte address */
- while ((i % 4) != 0)
- {
- if (i >= MAX_ARG_SIZE)
- {
- return 255;
- }
-
- ((uint8_t*)buffer)[i] = 0;
- i++;
- }
-
- if (i + 4 > MAX_ARG_SIZE)
- {
- return 255;
- }
-
- ((uint32_t*)buffer)[i/4] = value;
-
- return ((uint8_t) (i + 4));
-}
-#endif
-
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_INCLUDE_FLOAT_SUPPORT))
-static uint8_t writeFloat(void * buffer, uint8_t i, float value)
-{
- TRACE_ASSERT(buffer != NULL, "writeFloat: buffer == NULL", 0);
-
- /* A 32 bit value should begin at an even 4-byte address */
- while ((i % 4) != 0)
- {
- if (i >= MAX_ARG_SIZE)
- {
- return 255;
- }
-
- ((uint8_t*)buffer)[i] = 0;
- i++;
- }
-
- if (i + 4 > MAX_ARG_SIZE)
- {
- return 255;
- }
-
- ((float*)buffer)[i/4] = value;
-
- return i + 4;
-}
-#endif
-
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_INCLUDE_FLOAT_SUPPORT))
-static uint8_t writeDouble(void * buffer, uint8_t i, double value)
-{
- uint32_t * dest;
- uint32_t * src = (uint32_t*)&value;
-
- TRACE_ASSERT(buffer != NULL, "writeDouble: buffer == NULL", 0);
-
- /* The double is written as two 32 bit values, and should begin at an even
- 4-byte address (to avoid having to align with 8 byte) */
- while (i % 4 != 0)
- {
- if (i >= MAX_ARG_SIZE)
- {
- return 255;
- }
-
- ((uint8_t*)buffer)[i] = 0;
- i++;
- }
-
- if (i + 8 > MAX_ARG_SIZE)
- {
- return 255;
- }
-
- dest = &(((uint32_t *)buffer)[i/4]);
-
- dest[0] = src[0];
- dest[1] = src[1];
-
- return i + 8;
-}
-#endif
-
-/*******************************************************************************
- * prvTraceUserEventFormat
- *
- * Parses the format string and stores the arguments in the buffer.
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))
-static uint8_t prvTraceUserEventFormat(const char* formatStr, va_list vl, uint8_t* buffer, uint8_t byteOffset)
-{
- uint16_t formatStrIndex = 0;
- uint8_t argCounter = 0;
- uint8_t i = byteOffset;
-
- while (formatStr[formatStrIndex] != '\0')
- {
- if (formatStr[formatStrIndex] == '%')
- {
- argCounter++;
-
- if (argCounter > 15)
- {
- prvTraceError("vTracePrintF - Too many arguments, max 15 allowed!");
- return 0;
- }
-
- formatStrIndex++;
-
- while ((formatStr[formatStrIndex] >= '0' && formatStr[formatStrIndex] <= '9') || formatStr[formatStrIndex] == '#' || formatStr[formatStrIndex] == '.')
- formatStrIndex++;
-
- if (formatStr[formatStrIndex] != '\0')
- {
- switch (formatStr[formatStrIndex])
- {
- case 'd': i = writeInt32( buffer,
- i,
- (uint32_t)va_arg(vl, uint32_t));
- break;
- case 'x':
- case 'X':
- case 'u': i = writeInt32( buffer,
- i,
- (uint32_t)va_arg(vl, uint32_t));
- break;
- case 's': i = writeInt16( buffer,
- i,
- xTraceRegisterString((char*)va_arg(vl, char*)));
- break;
-
-#if (TRC_CFG_INCLUDE_FLOAT_SUPPORT)
- /* Yes, "double" as type also in the float
- case. This since "float" is promoted into "double"
- by the va_arg stuff. */
- case 'f': i = writeFloat( buffer,
- i,
- (float)va_arg(vl, double));
- break;
-#else
- /* No support for floats, but attempt to store a float user event
- avoid a possible crash due to float reference. Instead store the
- data on uint_32 format (will not be displayed anyway). This is just
- to keep va_arg and i consistent. */
-
- case 'f': i = writeInt32( buffer,
- i,
- (uint32_t)va_arg(vl, double));
- break;
-#endif
- case 'l':
- formatStrIndex++;
- switch (formatStr[formatStrIndex])
- {
-#if (TRC_CFG_INCLUDE_FLOAT_SUPPORT)
- case 'f': i = writeDouble(buffer,
- i,
- (double)va_arg(vl, double));
- break;
-#else
- /* No support for floats, but attempt to store a float user event
- avoid a possible crash due to float reference. Instead store the
- data on uint_32 format (will not be displayed anyway). This is just
- to keep va_arg and i consistent. */
- case 'f': i = writeInt32( buffer, /* In this case, the value will not be shown anyway */
- i,
- (uint32_t)va_arg(vl, double));
-
- i = writeInt32( buffer, /* Do it twice, to write in total 8 bytes */
- i,
- (uint32_t)va_arg(vl, double));
- break;
-#endif
-
- }
- break;
- case 'h':
- formatStrIndex++;
- switch (formatStr[formatStrIndex])
- {
- case 'd': i = writeInt16( buffer,
- i,
- (uint16_t)va_arg(vl, uint32_t));
- break;
- case 'u': i = writeInt16( buffer,
- i,
- (uint16_t)va_arg(vl, uint32_t));
- break;
- }
- break;
- case 'b':
- formatStrIndex++;
- switch (formatStr[formatStrIndex])
- {
- case 'd': i = writeInt8( buffer,
- i,
- (uint8_t)va_arg(vl, uint32_t));
- break;
-
- case 'u': i = writeInt8( buffer,
- i,
- (uint8_t)va_arg(vl, uint32_t));
- break;
- }
- break;
- }
- }
- else
- break;
- }
- formatStrIndex++;
- if (i == 255)
- {
- prvTraceError("vTracePrintF - Too large arguments, max 32 byte allowed!");
- return 0;
- }
- }
- return (uint8_t)(i+3)/4;
-}
-#endif
-
-/*******************************************************************************
- * prvTraceClearChannelBuffer
- *
- * Clears a number of items in the channel buffer, starting from nextSlotToWrite.
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1))
-static void prvTraceClearChannelBuffer(uint32_t count)
-{
- uint32_t slots;
-
- TRACE_ASSERT((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) >= count,
- "prvTraceClearChannelBuffer: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);
-
- /* Check if we're close to the end of the buffer */
- if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE))
- {
- slots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */
- (void)memset(&RecorderDataPtr->userEventBuffer.channelBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite], 0, slots);
- (void)memset(&RecorderDataPtr->userEventBuffer.channelBuffer[0], 0, (count - slots));
- }
- else
- (void)memset(&RecorderDataPtr->userEventBuffer.channelBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite], 0, count);
-}
-#endif
-
-/*******************************************************************************
- * prvTraceCopyToDataBuffer
- *
- * Copies a number of items to the data buffer, starting from nextSlotToWrite.
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1))
-static void prvTraceCopyToDataBuffer(uint32_t* data, uint32_t count)
-{
- uint32_t slots;
-
- TRACE_ASSERT(data != NULL,
- "prvTraceCopyToDataBuffer: data == NULL.", TRC_UNUSED);
- TRACE_ASSERT(count <= (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE),
- "prvTraceCopyToDataBuffer: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);
- /* Check if we're close to the end of the buffer */
- if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE))
- {
- slots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */
- (void)memcpy(&RecorderDataPtr->userEventBuffer.dataBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite * 4], data, slots * 4);
- (void)memcpy(&RecorderDataPtr->userEventBuffer.dataBuffer[0], data + slots, (count - slots) * 4);
- }
- else
- {
- (void)memcpy(&RecorderDataPtr->userEventBuffer.dataBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite * 4], data, count * 4);
- }
-}
-#endif
-
-/*******************************************************************************
- * prvTraceUBHelper1
- *
- * Calls on prvTraceUserEventFormat() to do the actual formatting, then goes on
- * to the next helper function.
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1))
-static void prvTraceUBHelper1(traceUBChannel channel, traceString eventLabel, traceString formatLabel, va_list vl)
-{
- uint32_t data[(3 + MAX_ARG_SIZE) / 4];
- uint8_t byteOffset = 4; /* Need room for timestamp */
- uint8_t noOfSlots;
-
- if (channel == 0)
- {
- /* We are dealing with an unknown channel format pair */
- byteOffset = (uint8_t)(byteOffset + 4); /* Also need room for channel and format */
- ((uint16_t*)data)[2] = eventLabel;
- ((uint16_t*)data)[3] = formatLabel;
- }
-
- noOfSlots = prvTraceUserEventFormat((char*)&(RecorderDataPtr->SymbolTable.symbytes[formatLabel+4]), vl, (uint8_t*)data, byteOffset);
-
- prvTraceUBHelper2(channel, data, noOfSlots);
-}
-#endif
-
-/*******************************************************************************
- * prvTraceUBHelper2
- *
- * This function simply copies the data buffer to the actual user event buffer.
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1))
-static void prvTraceUBHelper2(traceUBChannel channel, uint32_t* data, uint32_t noOfSlots)
-{
- static uint32_t old_timestamp = 0;
- uint32_t old_nextSlotToWrite = 0;
-
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ASSERT((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) >= noOfSlots, "prvTraceUBHelper2: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED);
-
- trcCRITICAL_SECTION_BEGIN();
- /* Store the timestamp */
- prvTracePortGetTimeStamp(data);
-
- if (*data < old_timestamp)
- {
- RecorderDataPtr->userEventBuffer.wraparoundCounter++;
- }
-
- old_timestamp = *data;
-
- /* Start by erasing any information in the channel buffer */
- prvTraceClearChannelBuffer(noOfSlots);
-
- prvTraceCopyToDataBuffer(data, noOfSlots); /* Will wrap around the data if necessary */
-
- old_nextSlotToWrite = RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Save the index that we want to write the channel data at when we're done */
- RecorderDataPtr->userEventBuffer.nextSlotToWrite = (RecorderDataPtr->userEventBuffer.nextSlotToWrite + noOfSlots) % (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE); /* Make sure we never end up outside the buffer */
-
- /* Write to the channel buffer to indicate that this user event is ready to be used */
- if (channel != 0)
- {
- RecorderDataPtr->userEventBuffer.channelBuffer[old_nextSlotToWrite] = channel;
- }
- else
- {
- /* 0xFF indicates that this is not a normal channel id */
- RecorderDataPtr->userEventBuffer.channelBuffer[old_nextSlotToWrite] = (traceUBChannel)0xFF;
- }
- trcCRITICAL_SECTION_END();
-}
-#endif
-
-/*******************************************************************************
- * xTraceRegisterUBChannel
- *
- * Registers a channel for Separated User Events, i.e., those stored in the
- * separate user event buffer.
- *
- * Note: Only available if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is enabled in
- * trcSnapshotConfig.h
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1))
-traceUBChannel xTraceRegisterUBChannel(traceString channel, traceString formatStr)
-{
- uint8_t i;
- traceUBChannel retVal = 0;
-
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ASSERT(formatStr != 0, "xTraceRegisterChannelFormat: formatStr == 0", (traceUBChannel)0);
-
- trcCRITICAL_SECTION_BEGIN();
- for (i = 1; i <= (TRC_CFG_UB_CHANNELS); i++) /* Size of the channels buffer is TRC_CFG_UB_CHANNELS + 1. Index 0 is unused. */
- {
- if(RecorderDataPtr->userEventBuffer.channels[i].name == 0 && RecorderDataPtr->userEventBuffer.channels[i].defaultFormat == 0)
- {
- /* Found empty slot */
- RecorderDataPtr->userEventBuffer.channels[i].name = channel;
- RecorderDataPtr->userEventBuffer.channels[i].defaultFormat = formatStr;
- retVal = (traceUBChannel)i;
- break;
- }
-
- if (RecorderDataPtr->userEventBuffer.channels[i].name == channel && RecorderDataPtr->userEventBuffer.channels[i].defaultFormat == formatStr)
- {
- /* Found a match */
- retVal = (traceUBChannel)i;
- break;
- }
- }
- trcCRITICAL_SECTION_END();
-
- return retVal;
-}
-#endif
-
-/******************************************************************************
- * vTraceUBData
- *
- * Slightly faster version of vTracePrintF() due to no lookups.
- *
- * Note: This is only available if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is
- * enabled in trcSnapshotConfig.h
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1))
-void vTraceUBData(traceUBChannel channelPair, ...)
-{
- va_list vl;
-
- TRACE_ASSERT(channelPair != 0, "vTraceUBData: Not a valid traceUBChannel!", TRC_UNUSED);
-
- va_start(vl, channelPair);
- vTraceUBData_Helper(channelPair, vl);
- va_end(vl);
-}
-#endif
-
-/* Extracts the channel name and format string from the traceUBChannel, then calls prvTraceUBHelper1. */
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1))
-void vTraceUBData_Helper(traceUBChannel channelPair, va_list vl)
-{
- traceString channel;
- traceString formatStr;
-
- TRACE_ASSERT(channelPair != 0, "vTraceUBData_Helper: channelPair == 0", TRC_UNUSED);
- TRACE_ASSERT(channelPair <= (TRC_CFG_UB_CHANNELS), "vTraceUBData_Helper: ", TRC_UNUSED);
-
- channel = RecorderDataPtr->userEventBuffer.channels[channelPair].name;
- formatStr = RecorderDataPtr->userEventBuffer.channels[channelPair].defaultFormat;
-
- prvTraceUBHelper1(channelPair, channel, formatStr, vl);
-}
-#endif
-
-/******************************************************************************
- * vTraceUBEvent
- *
- * Slightly faster version of ... due to no lookups.
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1))
-void vTraceUBEvent(traceUBChannel channelPair)
-{
- uint32_t data[(3 + MAX_ARG_SIZE) / 4];
-
- TRACE_ASSERT(channelPair != 0, "vTraceUBEvent: channelPair == 0", TRC_UNUSED);
- TRACE_ASSERT(channelPair <= (TRC_CFG_UB_CHANNELS), "vTraceUBEvent: ", TRC_UNUSED);
-
- prvTraceUBHelper2(channelPair, data, 1); /* Only need one slot for timestamp */
-}
-#endif
-
-/******************************************************************************
- * vTracePrintF
- *
- * Generates User Event with formatted text and data, similar to a "printf".
- * It is very fast compared to a normal "printf" since this function only
- * stores the arguments. The actual formatting is done
- * on the host PC when the trace is displayed in the viewer tool.
- *
- * User Event labels are created using xTraceRegisterString.
- * Example:
- *
- * traceString adc_uechannel = xTraceRegisterString("ADC User Events");
- * ...
- * vTracePrintF(adc_uechannel,
- * "ADC channel %d: %lf volts",
- * ch, (double)adc_reading/(double)scale);
- *
- * This can be combined into one line, if desired, but this is slower:
- *
- * vTracePrintF(xTraceRegisterString("ADC User Events"),
- * "ADC channel %d: %lf volts",
- * ch, (double)adc_reading/(double)scale);
- *
- * Calling xTraceRegisterString multiple times will not create duplicate entries, but
- * it is of course faster to just do it once, and then keep the handle for later
- * use. If you don't have any data arguments, only a text label/string, it is
- * better to use vTracePrint - it is faster.
- *
- * Format specifiers supported:
- * %d - 32 bit signed integer
- * %u - 32 bit unsigned integer
- * %f - 32 bit float
- * %s - string (is copied to the recorder symbol table)
- * %hd - 16 bit signed integer
- * %hu - 16 bit unsigned integer
- * %bd - 8 bit signed integer
- * %bu - 8 bit unsigned integer
- * %lf - double-precision float (Note! See below...)
- *
- * Up to 15 data arguments are allowed, with a total size of maximum 32 byte.
- * In case this is exceeded, the user event is changed into an error message.
- *
- * The data is stored in trace buffer, and is packed to allow storing multiple
- * smaller data entries in the same 4-byte record, e.g., four 8-bit values.
- * A string requires two bytes, as the symbol table is limited to 64K. Storing
- * a double (%lf) uses two records, so this is quite costly. Use float (%f)
- * unless the higher precision is really necessary.
- *
- * Note that the double-precision float (%lf) assumes a 64 bit double
- * representation. This does not seem to be the case on e.g. PIC24 and PIC32.
- * Before using a %lf argument on a 16-bit MCU, please verify that
- * "sizeof(double)" actually gives 8 as expected. If not, use %f instead.
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))
-void vTracePrintF(traceString eventLabel, const char* formatStr, ...)
-{
- va_list vl;
-
- va_start(vl, formatStr);
- vTracePrintF_Helper(eventLabel, formatStr, vl);
- va_end(vl);
-}
-#endif
-
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))
-void vTracePrintF_Helper(traceString eventLabel, const char* formatStr, va_list vl)
-{
-#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 0)
- uint32_t noOfSlots;
- UserEvent* ue1;
- uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ASSERT(formatStr != NULL, "vTracePrintF_Helper: formatStr == NULL", TRC_UNUSED);
-
- trcCRITICAL_SECTION_BEGIN();
-
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- {
- /* First, write the "primary" user event entry in the local buffer, but
- let the event type be "EVENT_BEING_WRITTEN" for now...*/
-
- ue1 = (UserEvent*)(&tempDataBuffer[0]);
-
- ue1->type = EVENT_BEING_WRITTEN; /* Update this as the last step */
-
- noOfSlots = prvTraceUserEventFormat(formatStr, vl, (uint8_t*)tempDataBuffer, 4);
-
- /* Store the format string, with a reference to the channel symbol */
- ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel);
-
- ue1->dts = (uint8_t)prvTraceGetDTS(0xFF);
-
- /* prvTraceGetDTS might stop the recorder in some cases... */
- if (RecorderDataPtr->recorderActive)
- {
-
- /* If the data does not fit in the remaining main buffer, wrap around to
- 0 if allowed, otherwise stop the recorder and quit). */
- if (RecorderDataPtr->nextFreeIndex + noOfSlots > RecorderDataPtr->maxEvents)
- {
- #if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
- (void)memset(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],
- 0,
- (RecorderDataPtr->maxEvents - RecorderDataPtr->nextFreeIndex)*4);
- RecorderDataPtr->nextFreeIndex = 0;
- RecorderDataPtr->bufferIsFull = 1;
- #else
-
- /* Stop recorder, since the event data will not fit in the
- buffer and not circular buffer in this case... */
- vTraceStop();
- #endif
- }
-
- /* Check if recorder has been stopped (i.e., vTraceStop above) */
- if (RecorderDataPtr->recorderActive)
- {
- /* Check that the buffer to be overwritten does not contain any user
- events that would be partially overwritten. If so, they must be "killed"
- by replacing the user event and following data with NULL events (i.e.,
- using a memset to zero).*/
- #if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
- prvCheckDataToBeOverwrittenForMultiEntryEvents((uint8_t)noOfSlots);
- #endif
- /* Copy the local buffer to the main buffer */
- (void)memcpy(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4],
- tempDataBuffer,
- noOfSlots * 4);
-
- /* Update the event type, i.e., number of data entries following the
- main USER_EVENT entry (Note: important that this is after the memcpy,
- but within the critical section!)*/
- RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4] =
- (uint8_t) ( USER_EVENT + noOfSlots - 1 );
-
- /* Update the main buffer event index (already checked that it fits in
- the buffer, so no need to check for wrapping)*/
-
- RecorderDataPtr->nextFreeIndex += noOfSlots;
- RecorderDataPtr->numEvents += noOfSlots;
-
- if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE))
- {
- #if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
- /* We have reached the end, but this is a ring buffer. Start from the beginning again. */
- RecorderDataPtr->bufferIsFull = 1;
- RecorderDataPtr->nextFreeIndex = 0;
- #else
- /* We have reached the end so we stop. */
- vTraceStop();
- #endif
- }
- }
-
- #if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
- /* Make sure the next entry is cleared correctly */
- prvCheckDataToBeOverwrittenForMultiEntryEvents(1);
- #endif
-
- }
- }
- trcCRITICAL_SECTION_END();
-
-#elif (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)
- /* Use the separate user event buffer */
- traceString formatLabel;
- traceUBChannel channel;
-
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- {
- formatLabel = xTraceRegisterString(formatStr);
-
- channel = xTraceRegisterUBChannel(eventLabel, formatLabel);
-
- prvTraceUBHelper1(channel, eventLabel, formatLabel, vl);
- }
-#endif
-}
-#endif
-
-/******************************************************************************
- * vTracePrint
- *
- * Basic user event
- *
- * Generates a User Event with a text label. The label is created/looked up
- * in the symbol table using xTraceRegisterString.
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))
-void vTracePrint(traceString chn, const char* str)
-{
-#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 0)
- UserEvent* ue;
- uint8_t dts1;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- trcCRITICAL_SECTION_BEGIN();
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- {
- dts1 = (uint8_t)prvTraceGetDTS(0xFF);
- ue = (UserEvent*) prvTraceNextFreeEventBufferSlot();
- if (ue != NULL)
- {
- ue->dts = dts1;
- ue->type = USER_EVENT;
- ue->payload = prvTraceOpenSymbol(str, chn);
- prvTraceUpdateCounters();
- }
- }
- trcCRITICAL_SECTION_END();
-
-#elif (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)
- traceUBChannel channel;
- uint32_t noOfSlots = 1;
- uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4];
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- {
- traceString trcStr = prvTraceOpenSymbol(str, chn);
- channel = xTraceRegisterUBChannel(chn, trcStr);
-
- if (channel == 0)
- {
- /* We are dealing with an unknown channel format pair */
- noOfSlots++; /* Also need room for channel and format */
- ((uint16_t*)tempDataBuffer)[2] = chn;
- ((uint16_t*)tempDataBuffer)[3] = trcStr;
- }
-
- prvTraceUBHelper2(channel, tempDataBuffer, noOfSlots);
- }
-#endif
-}
-#endif
-
-/*******************************************************************************
- * xTraceRegisterString
- *
- * Register strings in the recorder, e.g. for names of user event channels.
- *
- * Example:
- * myEventHandle = xTraceRegisterString("MyUserEvent");
- * ...
- * vTracePrintF(myEventHandle, "My value is: %d", myValue);
- ******************************************************************************/
-#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1))
-traceString xTraceRegisterString(const char* label)
-{
- TRACE_ASSERT(label != NULL, "xTraceRegisterString: label == NULL", (traceString)0);
- TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0);
- return prvTraceOpenSymbol(label, 0);
-}
-#endif
-
-
-#if ((!defined TRC_CFG_INCLUDE_READY_EVENTS) || (TRC_CFG_INCLUDE_READY_EVENTS == 1))
-
-void prvTraceSetReadyEventsEnabled(int status)
-{
- readyEventsEnabled = status;
-}
-
-/*******************************************************************************
- * prvTraceStoreTaskReady
- *
- * This function stores a ready state for the task handle sent in as parameter.
- ******************************************************************************/
-void prvTraceStoreTaskReady(traceHandle handle)
-{
- uint16_t dts3;
- TREvent* tr;
- uint8_t hnd8;
-
- TRACE_ALLOC_CRITICAL_SECTION();
-
- if (handle == 0)
- {
- /* On FreeRTOS v7.3.0, this occurs when creating tasks due to a bad
- placement of the trace macro. In that case, the events are ignored. */
- return;
- }
-
- if (! readyEventsEnabled)
- {
- /* When creating tasks, ready events are also created. If creating
- a "hidden" (not traced) task, we must therefore disable recording
- of ready events to avoid an undesired ready event... */
- return;
- }
-
- TRACE_ASSERT(handle <= (TRC_CFG_NTASK), "prvTraceStoreTaskReady: Invalid value for handle", TRC_UNUSED);
-
- if (recorder_busy)
- {
- /*************************************************************************
- * This occurs if an ISR calls a trace function, preempting a previous
- * trace call that is being processed in a different ISR or task.
- * If this occurs, there is probably a problem in the definition of the
- * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and
- * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt
- * and any other ISRs that calls the trace recorder directly or via
- * traced kernel functions. The ARM port disables all interrupts using the
- * PRIMASK register to avoid this issue.
- *************************************************************************/
- prvTraceError("Recorder busy - high priority ISR using syscall? (1)");
- return;
- }
-
- trcCRITICAL_SECTION_BEGIN();
- if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */
- {
- dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
- hnd8 = prvTraceGet8BitHandle(handle);
- tr = (TREvent*)prvTraceNextFreeEventBufferSlot();
- if (tr != NULL)
- {
- tr->type = DIV_TASK_READY;
- tr->dts = dts3;
- tr->objHandle = hnd8;
- prvTraceUpdateCounters();
- }
- }
- trcCRITICAL_SECTION_END();
-}
-#endif
-
-/*******************************************************************************
- * prvTraceStoreLowPower
- *
- * This function stores a low power state.
- ******************************************************************************/
-void prvTraceStoreLowPower(uint32_t flag)
-{
- uint16_t dts;
- LPEvent* lp;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ASSERT(flag <= 1, "prvTraceStoreLowPower: Invalid flag value", TRC_UNUSED);
-
- if (recorder_busy)
- {
- /*************************************************************************
- * This occurs if an ISR calls a trace function, preempting a previous
- * trace call that is being processed in a different ISR or task.
- * If this occurs, there is probably a problem in the definition of the
- * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and
- * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt
- * and any other ISRs that calls the trace recorder directly or via
- * traced kernel functions. The ARM port disables all interrupts using the
- * PRIMASK register to avoid this issue.
- *************************************************************************/
- prvTraceError("Recorder busy - high priority ISR using syscall? (1)");
- return;
- }
-
- trcCRITICAL_SECTION_BEGIN();
- if (RecorderDataPtr->recorderActive)
- {
- dts = (uint16_t)prvTraceGetDTS(0xFFFF);
- lp = (LPEvent*)prvTraceNextFreeEventBufferSlot();
- if (lp != NULL)
- {
- lp->type = (uint8_t) (LOW_POWER_BEGIN + ( uint8_t ) flag); /* BEGIN or END depending on flag */
- lp->dts = dts;
- prvTraceUpdateCounters();
- }
- }
- trcCRITICAL_SECTION_END();
-}
-
-/*******************************************************************************
- * vTraceStoreMemMangEvent
- *
- * This function stores malloc and free events. Each call requires two records,
- * for size and address respectively. The event code parameter (ecode) is applied
- * to the first record (size) and the following address record gets event
- * code "ecode + 1", so make sure this is respected in the event code table.
- * Note: On "free" calls, the signed_size parameter should be negative.
- ******************************************************************************/
-#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1)
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_size)
-{
- uint8_t dts1;
- MemEventSize * ms;
- MemEventAddr * ma;
- uint16_t size_low;
- uint16_t addr_low;
- uint8_t addr_high;
- uint32_t size;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- if (RecorderDataPtr == NULL)
- {
- /* Occurs in vTraceInitTraceData, if using dynamic allocation. */
- return;
- }
-
- if (signed_size < 0)
- size = (uint32_t)(- signed_size);
- else
- size = (uint32_t)(signed_size);
-
- trcCRITICAL_SECTION_BEGIN();
-
- heapMemUsage = heapMemUsage + (uint32_t)signed_size;
-
- if (RecorderDataPtr->recorderActive)
- {
- dts1 = (uint8_t)prvTraceGetDTS(0xFF);
- size_low = (uint16_t)prvTraceGetParam(0xFFFF, size);
- ms = (MemEventSize *)prvTraceNextFreeEventBufferSlot();
-
- if (ms != NULL)
- {
- ms->dts = dts1;
- ms->type = NULL_EVENT; /* Updated when all events are written */
- ms->size = size_low;
- prvTraceUpdateCounters();
-
- /* Storing a second record with address (signals "failed" if null) */
- #if (TRC_CFG_HEAP_SIZE_BELOW_16M)
- /* If the heap address range is within 16 MB, i.e., the upper 8 bits
- of addresses are constant, this optimization avoids storing an extra
- event record by ignoring the upper 8 bit of the address */
- addr_low = address & 0xFFFF;
- addr_high = (address >> 16) & 0xFF;
- #else
- /* The whole 32 bit address is stored using a second event record
- for the upper 16 bit */
- addr_low = (uint16_t)prvTraceGetParam(0xFFFF, address);
- addr_high = 0;
- #endif
-
- ma = (MemEventAddr *) prvTraceNextFreeEventBufferSlot();
- if (ma != NULL)
- {
- ma->addr_low = addr_low;
- ma->addr_high = addr_high;
- ma->type = (uint8_t) (ecode + 1); /* Note this! */
- ms->type = (uint8_t) ecode;
- prvTraceUpdateCounters();
- RecorderDataPtr->heapMemUsage = heapMemUsage;
- }
- }
- }
- trcCRITICAL_SECTION_END();
-}
-#endif /* TRC_CFG_SCHEDULING_ONLY */
-#endif
-
-/*******************************************************************************
- * prvTraceStoreKernelCall
- *
- * This is the main integration point for storing kernel calls, and
- * is called by the hooks in trcKernelHooks.h (see trcKernelPort.h for event codes).
- ******************************************************************************/
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-void prvTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber)
-{
- KernelCall * kse;
- uint16_t dts1;
- uint8_t hnd8;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ASSERT(ecode < 0xFF, "prvTraceStoreKernelCall: ecode >= 0xFF", TRC_UNUSED);
- TRACE_ASSERT(objectClass < TRACE_NCLASSES, "prvTraceStoreKernelCall: objectClass >= TRACE_NCLASSES", TRC_UNUSED);
- TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "prvTraceStoreKernelCall: Invalid value for objectNumber", TRC_UNUSED);
-
- if (recorder_busy)
- {
- /*************************************************************************
- * This occurs if an ISR calls a trace function, preempting a previous
- * trace call that is being processed in a different ISR or task.
- * If this occurs, there is probably a problem in the definition of the
- * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and
- * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt
- * and any other ISRs that calls the trace recorder directly or via
- * traced kernel functions. The ARM port disables all interrupts using the
- * PRIMASK register to avoid this issue.
- *************************************************************************/
- prvTraceError("Recorder busy - high priority ISR using syscall? (2)");
- return;
- }
-
- if (handle_of_last_logged_task == 0)
- {
- return;
- }
-
- trcCRITICAL_SECTION_BEGIN();
- if (RecorderDataPtr->recorderActive)
- {
- dts1 = (uint16_t)prvTraceGetDTS(0xFFFF);
- hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber);
- kse = (KernelCall*) prvTraceNextFreeEventBufferSlot();
- if (kse != NULL)
- {
- kse->dts = dts1;
- kse->type = (uint8_t)ecode;
- kse->objHandle = hnd8;
- prvTraceUpdateCounters();
- }
- }
- trcCRITICAL_SECTION_END();
-}
-#endif /* TRC_CFG_SCHEDULING_ONLY */
-
-/*******************************************************************************
- * prvTraceStoreKernelCallWithParam
- *
- * Used for storing kernel calls with a handle and a numeric parameter. If the
- * numeric parameter does not fit in one byte, and extra XPS event is inserted
- * before the kernel call event containing the three upper bytes.
- ******************************************************************************/
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-void prvTraceStoreKernelCallWithParam(uint32_t evtcode,
- traceObjectClass objectClass,
- uint32_t objectNumber,
- uint32_t param)
-{
- KernelCallWithParamAndHandle * kse;
- uint8_t dts2;
- uint8_t hnd8;
- uint8_t p8;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ASSERT(evtcode < 0xFF, "prvTraceStoreKernelCallWithParam: evtcode >= 0xFF", TRC_UNUSED);
- TRACE_ASSERT(objectClass < TRACE_NCLASSES, "prvTraceStoreKernelCallWithParam: objectClass >= TRACE_NCLASSES", TRC_UNUSED);
- TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "prvTraceStoreKernelCallWithParam: Invalid value for objectNumber", TRC_UNUSED);
-
- if (recorder_busy)
- {
- /*************************************************************************
- * This occurs if an ISR calls a trace function, preempting a previous
- * trace call that is being processed in a different ISR or task.
- * If this occurs, there is probably a problem in the definition of the
- * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and
- * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt
- * and any other ISRs that calls the trace recorder directly or via
- * traced kernel functions. The ARM port disables all interrupts using the
- * PRIMASK register to avoid this issue.
- *************************************************************************/
- prvTraceError("Recorder busy - high priority ISR using syscall? (3)");
- return;
- }
-
- trcCRITICAL_SECTION_BEGIN();
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- {
- dts2 = (uint8_t)prvTraceGetDTS(0xFF);
- p8 = (uint8_t) prvTraceGetParam(0xFF, param);
- hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber);
- kse = (KernelCallWithParamAndHandle*) prvTraceNextFreeEventBufferSlot();
- if (kse != NULL)
- {
- kse->dts = dts2;
- kse->type = (uint8_t)evtcode;
- kse->objHandle = hnd8;
- kse->param = p8;
- prvTraceUpdateCounters();
- }
- }
- trcCRITICAL_SECTION_END();
-}
-#endif /* TRC_CFG_SCHEDULING_ONLY */
-
-
-/*******************************************************************************
- * prvTraceGetParam
- *
- * Used for storing extra bytes for kernel calls with numeric parameters.
- *
- * May only be called within a critical section!
- ******************************************************************************/
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-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*) prvTraceNextFreeEventBufferSlot();
- if (xps != NULL)
- {
- xps->type = DIV_XPS;
- xps->xps_8 = (uint8_t)((param & (0xFF00 & ~param_max)) >> 8);
- xps->xps_16 = (uint16_t)((param & (0xFFFF0000 & ~param_max)) >> 16);
- prvTraceUpdateCounters();
- }
-
- return param & param_max;
- }
-}
-#endif
-
-/*******************************************************************************
- * prvTraceStoreKernelCallWithNumericParamOnly
- *
- * Used for storing kernel calls with numeric parameters only. This is
- * only used for traceTASK_DELAY and traceDELAY_UNTIL at the moment.
- ******************************************************************************/
-#if (TRC_CFG_SCHEDULING_ONLY == 0)
-void prvTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param)
-{
- KernelCallWithParam16 * kse;
- uint8_t dts6;
- uint16_t restParam;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- restParam = 0;
-
- TRACE_ASSERT(evtcode < 0xFF, "prvTraceStoreKernelCallWithNumericParamOnly: Invalid value for evtcode", TRC_UNUSED);
-
- if (recorder_busy)
- {
- /*************************************************************************
- * This occurs if an ISR calls a trace function, preempting a previous
- * trace call that is being processed in a different ISR or task.
- * If this occurs, there is probably a problem in the definition of the
- * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and
- * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt
- * and any other ISRs that calls the trace recorder directly or via
- * traced kernel functions. The ARM port disables all interrupts using the
- * PRIMASK register to avoid this issue.
- *************************************************************************/
- prvTraceError("Recorder busy - high priority ISR using syscall? (4)");
- return;
- }
-
- trcCRITICAL_SECTION_BEGIN();
- if (RecorderDataPtr->recorderActive && handle_of_last_logged_task)
- {
- dts6 = (uint8_t)prvTraceGetDTS(0xFF);
- restParam = (uint16_t)prvTraceGetParam(0xFFFF, param);
- kse = (KernelCallWithParam16*) prvTraceNextFreeEventBufferSlot();
- if (kse != NULL)
- {
- kse->dts = dts6;
- kse->type = (uint8_t)evtcode;
- kse->param = restParam;
- prvTraceUpdateCounters();
- }
- }
- trcCRITICAL_SECTION_END();
-}
-#endif /* TRC_CFG_SCHEDULING_ONLY */
-
-/*******************************************************************************
- * prvTraceStoreTaskswitch
- * Called by the scheduler from the SWITCHED_OUT hook, and by uiTraceStart.
- * At this point interrupts are assumed to be disabled!
- ******************************************************************************/
-void prvTraceStoreTaskswitch(traceHandle task_handle)
-{
- uint16_t dts3;
- TSEvent* ts;
- uint8_t hnd8;
-#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
- extern int32_t isPendingContextSwitch;
-#endif
- trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY();
-
- TRACE_ASSERT(task_handle <= (TRC_CFG_NTASK),
- "prvTraceStoreTaskswitch: Invalid value for task_handle", TRC_UNUSED);
-
- trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY();
-
- if ((task_handle != handle_of_last_logged_task) && (RecorderDataPtr->recorderActive))
- {
-#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
- isPendingContextSwitch = 0;
-#endif
-
- dts3 = (uint16_t)prvTraceGetDTS(0xFFFF);
- handle_of_last_logged_task = task_handle;
- hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task);
- ts = (TSEvent*)prvTraceNextFreeEventBufferSlot();
-
- if (ts != NULL)
- {
- if (prvTraceGetObjectState(TRACE_CLASS_TASK,
- handle_of_last_logged_task) == TASK_STATE_INSTANCE_ACTIVE)
- {
- ts->type = TS_TASK_RESUME;
- }
- else
- {
- ts->type = TS_TASK_BEGIN;
- }
-
- ts->dts = dts3;
- ts->objHandle = hnd8;
-
- prvTraceSetObjectState(TRACE_CLASS_TASK,
- handle_of_last_logged_task,
- TASK_STATE_INSTANCE_ACTIVE);
-
- prvTraceUpdateCounters();
- }
- }
-
- trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY();
-}
-
-/*******************************************************************************
- * prvTraceStoreObjectNameOnCloseEvent
- *
- * Updates the symbol table with the name of this object from the dynamic
- * objects table and stores a "close" event, holding the mapping between handle
- * and name (a symbol table handle). The stored name-handle mapping is thus the
- * "old" one, valid up until this point.
- ******************************************************************************/
-void prvTraceStoreObjectNameOnCloseEvent(uint8_t evtcode, traceHandle handle,
- traceObjectClass objectclass)
-{
- ObjCloseNameEvent * ce;
- const char * name;
- traceString idx;
-
- TRACE_ASSERT(objectclass < TRACE_NCLASSES,
- "prvTraceStoreObjectNameOnCloseEvent: objectclass >= TRACE_NCLASSES", TRC_UNUSED);
- TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
- "prvTraceStoreObjectNameOnCloseEvent: Invalid value for handle", TRC_UNUSED);
-
- if (RecorderDataPtr->recorderActive)
- {
- uint8_t hnd8 = prvTraceGet8BitHandle(handle);
- name = TRACE_PROPERTY_NAME_GET(objectclass, handle);
- idx = prvTraceOpenSymbol(name, 0);
-
- // Interrupt disable not necessary, already done in trcHooks.h macro
- ce = (ObjCloseNameEvent*) prvTraceNextFreeEventBufferSlot();
- if (ce != NULL)
- {
- ce->type = (uint8_t) evtcode;
- ce->objHandle = hnd8;
- ce->symbolIndex = idx;
- prvTraceUpdateCounters();
- }
- }
-}
-
-void prvTraceStoreObjectPropertiesOnCloseEvent(uint8_t evtcode, traceHandle handle,
- traceObjectClass objectclass)
-{
- ObjClosePropEvent * pe;
-
- TRACE_ASSERT(objectclass < TRACE_NCLASSES,
- "prvTraceStoreObjectPropertiesOnCloseEvent: objectclass >= TRACE_NCLASSES", TRC_UNUSED);
- TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
- "prvTraceStoreObjectPropertiesOnCloseEvent: Invalid value for handle", TRC_UNUSED);
-
- if (RecorderDataPtr->recorderActive)
- {
- // Interrupt disable not necessary, already done in trcHooks.h macro
- pe = (ObjClosePropEvent*) prvTraceNextFreeEventBufferSlot();
- if (pe != NULL)
- {
- if (objectclass == TRACE_CLASS_TASK)
- {
- pe->arg1 = TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle);
- }
- else
- {
- pe->arg1 = TRACE_PROPERTY_OBJECT_STATE(objectclass, handle);
- }
- pe->type = evtcode;
- prvTraceUpdateCounters();
- }
- }
-}
-
-void prvTraceSetPriorityProperty(uint8_t objectclass, traceHandle id, uint8_t value)
-{
- TRACE_ASSERT(objectclass < TRACE_NCLASSES,
- "prvTraceSetPriorityProperty: objectclass >= TRACE_NCLASSES", TRC_UNUSED);
- TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
- "prvTraceSetPriorityProperty: Invalid value for id", TRC_UNUSED);
-
- TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id) = value;
-}
-
-uint8_t prvTraceGetPriorityProperty(uint8_t objectclass, traceHandle id)
-{
- TRACE_ASSERT(objectclass < TRACE_NCLASSES,
- "prvTraceGetPriorityProperty: objectclass >= TRACE_NCLASSES", 0);
- TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
- "prvTraceGetPriorityProperty: Invalid value for id", 0);
-
- return TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id);
-}
-
-void prvTraceSetObjectState(uint8_t objectclass, traceHandle id, uint8_t value)
-{
- TRACE_ASSERT(objectclass < TRACE_NCLASSES,
- "prvTraceSetObjectState: objectclass >= TRACE_NCLASSES", TRC_UNUSED);
- TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
- "prvTraceSetObjectState: Invalid value for id", TRC_UNUSED);
-
- TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value;
-}
-
-uint8_t prvTraceGetObjectState(uint8_t objectclass, traceHandle id)
-{
- TRACE_ASSERT(objectclass < TRACE_NCLASSES,
- "prvTraceGetObjectState: objectclass >= TRACE_NCLASSES", 0);
- TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
- "prvTraceGetObjectState: Invalid value for id", 0);
-
- return TRACE_PROPERTY_OBJECT_STATE(objectclass, id);
-}
-
-void prvTraceSetTaskInstanceFinished(traceHandle handle)
-{
- TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_TASK],
- "prvTraceSetTaskInstanceFinished: Invalid value for handle", TRC_UNUSED);
-
-#if (TRC_CFG_USE_IMPLICIT_IFE_RULES == 1)
- TRACE_PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle) = 0;
-#endif
-}
-
-/*******************************************************************************
- * Static data initializations
- ******************************************************************************/
-
-/* A set of stacks that keeps track of available object handles for each class.
-The stacks are empty initially, meaning that allocation of new handles will be
-based on a counter (for each object class). Any delete operation will
-return the handle to the corresponding stack, for reuse on the next allocate.*/
-objectHandleStackType objectHandleStacks = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } };
-
-/* Initial TRC_HWTC_COUNT value, for detecting if the time-stamping source is
-enabled. If using the OS periodic timer for time-stamping, this might not
-have been configured on the earliest events during the startup. */
-uint32_t init_hwtc_count;
-
-/*******************************************************************************
- * RecorderData
- *
- * The main data structure in snapshot mode, when using the default static memory
- * allocation (TRC_RECORDER_BUFFER_ALLOCATION_STATIC). The recorder uses a pointer
- * RecorderDataPtr to access the data, to also allow for dynamic or custom data
- * allocation (see TRC_CFG_RECORDER_BUFFER_ALLOCATION).
- ******************************************************************************/
-#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC)
-RecorderDataType RecorderData;
-#endif
-
-/*******************************************************************************
- * RecorderDataPtr
- *
- * Pointer to the main data structure, when in snapshot mode.
- ******************************************************************************/
-RecorderDataType* RecorderDataPtr = NULL;
-
-/* This version of the function dynamically allocates the trace data */
-void prvTraceInitTraceData()
-{
-
- if (RecorderDataPtr == NULL)
- {
-#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC)
- RecorderDataPtr = &RecorderData;
-#elif (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC)
- RecorderDataPtr = (RecorderDataType*)TRACE_MALLOC(sizeof(RecorderDataType));
- if (! RecorderDataPtr)
- {
- prvTraceError("Failed allocating recorder buffer!");
- return;
- }
-#elif (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM)
- if (! RecorderDataPtr)
- {
- prvTraceError("Recorder data pointer not set! Use vTraceSetRecorderDataBuffer().");
- return;
- }
-#endif
- }
- else
- {
- if (RecorderDataPtr->startmarker0 == 1)
- {
- /* Already initialized */
- return;
- }
- }
-
- init_hwtc_count = TRC_HWTC_COUNT;
-
- (void)memset(RecorderDataPtr, 0, sizeof(RecorderDataType));
-
- RecorderDataPtr->version = TRACE_KERNEL_VERSION;
- RecorderDataPtr->minor_version = TRACE_MINOR_VERSION;
- RecorderDataPtr->irq_priority_order = TRC_IRQ_PRIORITY_ORDER;
- RecorderDataPtr->filesize = sizeof(RecorderDataType);
- RecorderDataPtr->maxEvents = (TRC_CFG_EVENT_BUFFER_SIZE);
- RecorderDataPtr->debugMarker0 = (int32_t) 0xF0F0F0F0;
- RecorderDataPtr->isUsing16bitHandles = TRC_CFG_USE_16BIT_OBJECT_HANDLES;
- RecorderDataPtr->isrTailchainingThreshold = TRC_CFG_ISR_TAILCHAINING_THRESHOLD;
-
- /* This function is kernel specific */
- vTraceInitObjectPropertyTable();
-
- RecorderDataPtr->debugMarker1 = (int32_t)0xF1F1F1F1;
- RecorderDataPtr->SymbolTable.symTableSize = (TRC_CFG_SYMBOL_TABLE_SIZE);
- RecorderDataPtr->SymbolTable.nextFreeSymbolIndex = 1;
-#if (TRC_CFG_INCLUDE_FLOAT_SUPPORT == 1)
- RecorderDataPtr->exampleFloatEncoding = 1.0f; /* otherwise already zero */
-#endif
- RecorderDataPtr->debugMarker2 = (int32_t)0xF2F2F2F2;
- prvStrncpy(RecorderDataPtr->systemInfo, "Trace Recorder Demo", 80);
- RecorderDataPtr->debugMarker3 = (int32_t)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 TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER
- RecorderDataPtr->userEventBuffer.bufferID = 1;
- RecorderDataPtr->userEventBuffer.version = 0;
- RecorderDataPtr->userEventBuffer.numberOfSlots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE);
- RecorderDataPtr->userEventBuffer.numberOfChannels = (TRC_CFG_UB_CHANNELS) + 1;
-#endif
-
- /* Kernel specific initialization of the objectHandleStacks variable */
- vTraceInitObjectHandleStack();
-
-
- /* Finally, the 12-byte "start markers" are initialized, allowing for
- Tracealyzer to find the trace data in a larger RAM dump.
-
- The start and end markers must be unique, but without proper precautions there
- might be a risk of accidental duplicates of the start/end markers, e.g., due to
- compiler optimizations.
-
- The below initialization of the start marker is therefore made in reverse order
- and the fields are volatile to ensure this assignment order. This to avoid any
- chance of accidental duplicates of this elsewhere in memory.
-
- Moreover, the fields are set byte-by-byte to avoid endian issues.*/
-
- RecorderDataPtr->startmarker11 = 0xF4;
- RecorderDataPtr->startmarker10 = 0xF3;
- RecorderDataPtr->startmarker9 = 0xF2;
- RecorderDataPtr->startmarker8 = 0xF1;
- RecorderDataPtr->startmarker7 = 0x74;
- RecorderDataPtr->startmarker6 = 0x73;
- RecorderDataPtr->startmarker5 = 0x72;
- RecorderDataPtr->startmarker4 = 0x71;
- RecorderDataPtr->startmarker3 = 0x04;
- RecorderDataPtr->startmarker2 = 0x03;
- RecorderDataPtr->startmarker1 = 0x02;
- RecorderDataPtr->startmarker0 = 0x01;
-
- if (traceErrorMessage != NULL)
- {
- // An error was detected before vTraceEnable was called, make sure this is stored in the trace data.
- prvStrncpy(RecorderDataPtr->systemInfo, traceErrorMessage, 80);
- RecorderDataPtr->internalErrorOccured = 1;
- vTraceStop();
- }
-
-
-
-#ifdef TRC_PORT_SPECIFIC_INIT
- TRC_PORT_SPECIFIC_INIT();
-#endif
-}
-
-
-void* prvTraceNextFreeEventBufferSlot(void)
-{
- if (! RecorderDataPtr->recorderActive)
- {
- /* If an XTS or XPS event prior to the main event has filled the buffer
- before saving the main event, and store mode is "stop when full". */
- return NULL;
- }
-
- if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE))
- {
- prvTraceError("Attempt to index outside event buffer!");
- return NULL;
- }
- return (void*)(&RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex*4]);
-}
-
-uint16_t uiIndexOfObject(traceHandle objecthandle, uint8_t objectclass)
-{
- 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]))
- {
- return (uint16_t)(RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[objectclass] +
- (RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[objectclass] * (objecthandle-1)));
- }
-
- prvTraceError("Object table lookup with invalid object handle or object class!");
- return 0;
-}
-
-traceHandle prvTraceGetObjectHandle(traceObjectClass objectclass)
-{
- traceHandle handle;
- static int indexOfHandle;
-
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0);
-
- TRACE_ASSERT(objectclass < TRACE_NCLASSES,
- "prvTraceGetObjectHandle: Invalid value for objectclass", (traceHandle)0);
-
- trcCRITICAL_SECTION_BEGIN();
- indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass];
- if (objectHandleStacks.objectHandles[indexOfHandle] == 0)
- {
- /* Zero is used to indicate a never before used handle, i.e.,
- new slots in the handle stack. The handle slot needs to
- be initialized here (starts at 1). */
- objectHandleStacks.objectHandles[indexOfHandle] =
- (traceHandle)(1 + indexOfHandle -
- objectHandleStacks.lowestIndexOfClass[objectclass]);
- }
-
- handle = objectHandleStacks.objectHandles[indexOfHandle];
-
- if (objectHandleStacks.indexOfNextAvailableHandle[objectclass]
- > objectHandleStacks.highestIndexOfClass[objectclass])
- {
- prvTraceError(pszTraceGetErrorNotEnoughHandles(objectclass));
- handle = 0;
- }
- else
- {
- int hndCount;
- objectHandleStacks.indexOfNextAvailableHandle[objectclass]++;
-
- hndCount = objectHandleStacks.indexOfNextAvailableHandle[objectclass] -
- objectHandleStacks.lowestIndexOfClass[objectclass];
-
- if (hndCount >
- objectHandleStacks.handleCountWaterMarksOfClass[objectclass])
- {
- objectHandleStacks.handleCountWaterMarksOfClass[objectclass] =
- (traceHandle)hndCount;
- }
- }
- trcCRITICAL_SECTION_END();
-
- return handle;
-}
-
-void prvTraceFreeObjectHandle(traceObjectClass objectclass, traceHandle handle)
-{
- int indexOfHandle;
-
- TRACE_ASSERT(objectclass < TRACE_NCLASSES,
- "prvTraceFreeObjectHandle: Invalid value for objectclass", TRC_UNUSED);
- TRACE_ASSERT(handle > 0 && handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass],
- "prvTraceFreeObjectHandle: Invalid value for handle", TRC_UNUSED);
-
- /* Check that there is room to push the handle on the stack */
- if ((objectHandleStacks.indexOfNextAvailableHandle[objectclass] - 1) <
- objectHandleStacks.lowestIndexOfClass[objectclass])
- {
- /* Error */
- prvTraceError("Attempt to free more handles than allocated!");
- }
- else
- {
- objectHandleStacks.indexOfNextAvailableHandle[objectclass]--;
- indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass];
- objectHandleStacks.objectHandles[indexOfHandle] = handle;
- }
-}
-
-/*******************************************************************************
- * prvMarkObjectAsUsed
- *
- * Sets an "is used flag" on object creation, using the first byte of the name
- * field. This allows for counting the number of used Object Table slots, even
- * if no names have been set.
- ******************************************************************************/
-void prvMarkObjectAsUsed(traceObjectClass objectclass, traceHandle handle)
-{
- uint16_t idx = uiIndexOfObject(handle, objectclass);
- RecorderDataPtr->ObjectPropertyTable.objbytes[idx] = 1;
-}
-
-/*******************************************************************************
- * prvStrncpy
- *
- * Private string copy function, to improve portability between compilers.
- ******************************************************************************/
-static void prvStrncpy(char* dst, const char* src, uint32_t maxLength)
-{
- uint32_t i;
- for (i = 0; i < maxLength; i++)
- {
- dst[i] = src[i];
- if (src[i] == 0)
- break;
- }
-}
-
-/*******************************************************************************
- * prvTraceSetObjectName
- *
- * Registers the names of queues, semaphores and other kernel objects in the
- * recorder's Object Property Table, at the given handle and object class.
- ******************************************************************************/
-void prvTraceSetObjectName(traceObjectClass objectclass,
- traceHandle handle,
- const char* name)
-{
- static uint16_t idx;
-
- TRACE_ASSERT(name != NULL, "prvTraceSetObjectName: name == NULL", TRC_UNUSED);
-
- if (objectclass >= TRACE_NCLASSES)
- {
- prvTraceError("Illegal object class in prvTraceSetObjectName");
- return;
- }
-
- if (handle == 0)
- {
- prvTraceError("Illegal handle (0) in prvTraceSetObjectName.");
- return;
- }
-
- if (handle > RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass])
- {
- /* ERROR */
- prvTraceError(pszTraceGetErrorNotEnoughHandles(objectclass));
- }
- else
- {
- idx = uiIndexOfObject(handle, objectclass);
-
- if (traceErrorMessage == NULL)
- {
- prvStrncpy((char*)&(RecorderDataPtr->ObjectPropertyTable.objbytes[idx]),
- name,
- RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ objectclass ]);
- }
- }
-}
-
-traceString prvTraceOpenSymbol(const char* name, traceString userEventChannel)
-{
- uint16_t result;
- uint8_t len;
- uint8_t crc;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- len = 0;
- crc = 0;
-
- TRACE_ASSERT(name != NULL, "prvTraceOpenSymbol: name == NULL", (traceString)0);
-
- prvTraceGetChecksum(name, &crc, &len);
-
- trcCRITICAL_SECTION_BEGIN();
- result = prvTraceLookupSymbolTableEntry(name, crc, len, userEventChannel);
- if (!result)
- {
- result = prvTraceCreateSymbolTableEntry(name, crc, len, userEventChannel);
- }
- trcCRITICAL_SECTION_END();
-
- return result;
-}
-
-
-/******************************************************************************
-* vTraceSetFrequency
-*
-* Registers the clock rate of the time source for the event timestamping.
-* This is normally not required, but if the default value (TRC_HWTC_FREQ_HZ)
-* should be incorrect for your setup, you can override it using this function.
-*
-* Must be called prior to vTraceEnable, and the time source is assumed to
-* have a fixed clock frequency after the startup.
-*
-* Note that, in snapshot mode, the value is divided by the TRC_HWTC_DIVISOR.
-* This is a software "prescaler" that is also applied on the timestamps.
-*****************************************************************************/
-void vTraceSetFrequency(uint32_t frequency)
-{
- timestampFrequency = frequency;
-}
-
-/*******************************************************************************
- * Supporting functions
- ******************************************************************************/
-
-/*******************************************************************************
- * prvTraceError
- *
- * Called by various parts in the recorder. Stops the recorder and stores a
- * pointer to an error message, which is printed by the monitor task.
- * If you are not using the monitor task, you may use xTraceGetLastError()
- * from your application to check if the recorder is OK.
- *
- * Note: If a recorder error is registered before vTraceStart is called, the
- * trace start will be aborted. This can occur if any of the Nxxxx constants
- * (e.g., TRC_CFG_NTASK) in trcConfig.h is too small.
- ******************************************************************************/
-void prvTraceError(const char* msg)
-{
- /* Stop the recorder */
- if (RecorderDataPtr != NULL)
- {
- vTraceStop();
- }
-
- /* If first error only... */
- if (traceErrorMessage == NULL)
- {
- traceErrorMessage = (char*)(intptr_t) msg;
- if (RecorderDataPtr != NULL)
- {
- prvStrncpy(RecorderDataPtr->systemInfo, traceErrorMessage, 80);
- RecorderDataPtr->internalErrorOccured = 1;
- }
- }
-}
-
-void vTraceSetFilterMask(uint16_t filterMask)
-{
- CurrentFilterMask = filterMask;
-}
-
-void vTraceSetFilterGroup(uint16_t filterGroup)
-{
- CurrentFilterGroup = filterGroup;
-}
-
-/******************************************************************************
- * prvCheckDataToBeOverwrittenForMultiEntryEvents
- *
- * This checks if the next event to be overwritten is a multi-entry user event,
- * i.e., a USER_EVENT followed by data entries.
- * Such data entries do not have an event code at byte 0, as other events.
- * All 4 bytes are user data, so the first byte of such data events must
- * not be interpreted as type field. The number of data entries following
- * a USER_EVENT is given in the event code of the USER_EVENT.
- * Therefore, when overwriting a USER_EVENT (when using in ring-buffer mode)
- * any data entries following must be replaced with NULL events (code 0).
- *
- * This is assumed to execute within a critical section...
- *****************************************************************************/
-
-#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
-void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nofEntriesToCheck)
-{
- /* Generic "int" type is desired - should be 16 bit variable on 16 bit HW */
- unsigned int i = 0;
- unsigned int e = 0;
-
- TRACE_ASSERT(nofEntriesToCheck != 0,
- "prvCheckDataToBeOverwrittenForMultiEntryEvents: nofEntriesToCheck == 0", TRC_UNUSED);
-
- while (i < nofEntriesToCheck)
- {
- e = RecorderDataPtr->nextFreeIndex + i;
- if ((RecorderDataPtr->eventData[e*4] > USER_EVENT) &&
- (RecorderDataPtr->eventData[e*4] < USER_EVENT + 16))
- {
- uint8_t nDataEvents = (uint8_t)(RecorderDataPtr->eventData[e*4] - USER_EVENT);
- if ((e + nDataEvents) < RecorderDataPtr->maxEvents)
- {
- (void)memset(& RecorderDataPtr->eventData[e*4], 0, (size_t) (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++;
- }
-}
-#endif
-
-/*******************************************************************************
- * prvTraceUpdateCounters
- *
- * Updates the index of the event buffer.
- ******************************************************************************/
-void prvTraceUpdateCounters(void)
-{
- if (RecorderDataPtr->recorderActive == 0)
- {
- return;
- }
-
- RecorderDataPtr->numEvents++;
-
- RecorderDataPtr->nextFreeIndex++;
-
- if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE))
- {
-#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
- RecorderDataPtr->bufferIsFull = 1;
- RecorderDataPtr->nextFreeIndex = 0;
-#else
- vTraceStop();
-#endif
- }
-
-#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER)
- prvCheckDataToBeOverwrittenForMultiEntryEvents(1);
-#endif
-}
-
-/******************************************************************************
- * prvTraceGetDTS
- *
- * Returns a differential timestamp (DTS), i.e., the time since
- * last event, and creates an XTS event if the DTS does not fit in the
- * number of bits given. The XTS event holds the MSB bytes of the DTS.
- *
- * The parameter param_maxDTS should be 0xFF for 8-bit dts or 0xFFFF for
- * events with 16-bit dts fields.
- *****************************************************************************/
-uint16_t prvTraceGetDTS(uint16_t param_maxDTS)
-{
- static uint32_t old_timestamp = 0;
- XTSEvent* xts = 0;
- uint32_t dts = 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 (timestampFrequency != 0)
- {
- /* If to override default TRC_HWTC_FREQ_HZ value with value set by vTraceSetFrequency */
- RecorderDataPtr->frequency = timestampFrequency / (TRC_HWTC_DIVISOR);
- }
- else if (init_hwtc_count != (TRC_HWTC_COUNT))
- {
- /* If using default value and timer has been started.
- Note: If the default frequency value set here would be incorrect, e.g.,
- if the timer has actually not been configured yet, override this
- with vTraceSetFrequency.
- */
- RecorderDataPtr->frequency = (TRC_HWTC_FREQ_HZ) / (TRC_HWTC_DIVISOR);
- }
- /* If no override (vTraceSetFrequency) and timer inactive -> no action */
- }
-
- /**************************************************************************
- * The below statements read the timestamp from the timer port module.
- * If necessary, whole seconds are extracted using division while the rest
- * comes from the modulo operation.
- **************************************************************************/
-
- prvTracePortGetTimeStamp(×tamp);
-
- /***************************************************************************
- * Since dts is unsigned the result will be correct even if timestamp has
- * wrapped around.
- ***************************************************************************/
- dts = timestamp - old_timestamp;
- old_timestamp = timestamp;
-
- if (RecorderDataPtr->frequency > 0)
- {
- /* Check if dts > 1 second */
- if (dts > RecorderDataPtr->frequency)
- {
- /* More than 1 second has passed */
- RecorderDataPtr->absTimeLastEventSecond += dts / RecorderDataPtr->frequency;
- /* The part that is not an entire second is added to absTimeLastEvent */
- RecorderDataPtr->absTimeLastEvent += dts % RecorderDataPtr->frequency;
- }
- else
- {
- RecorderDataPtr->absTimeLastEvent += dts;
- }
-
- /* Check if absTimeLastEvent >= 1 second */
- if (RecorderDataPtr->absTimeLastEvent >= RecorderDataPtr->frequency)
- {
- /* RecorderDataPtr->absTimeLastEvent is more than or equal to 1 second, but always less than 2 seconds */
- RecorderDataPtr->absTimeLastEventSecond++;
- RecorderDataPtr->absTimeLastEvent -= RecorderDataPtr->frequency;
- /* RecorderDataPtr->absTimeLastEvent is now less than 1 second */
- }
- }
- else
- {
- /* Special case if the recorder has not yet started (frequency may be uninitialized, i.e., zero) */
- RecorderDataPtr->absTimeLastEvent = timestamp;
- }
-
- /* If the dts (time since last event) does not fit in event->dts (only 8 or 16 bits) */
- if (dts > param_maxDTS)
- {
- /* Create an XTS event (eXtended TimeStamp) containing the higher dts bits*/
- xts = (XTSEvent*) prvTraceNextFreeEventBufferSlot();
-
- if (xts != NULL)
- {
- if (param_maxDTS == 0xFFFF)
- {
- xts->type = XTS16;
- xts->xts_16 = (uint16_t)((dts / 0x10000) & 0xFFFF);
- xts->xts_8 = 0;
- }
- else if (param_maxDTS == 0xFF)
- {
- xts->type = XTS8;
- xts->xts_16 = (uint16_t)((dts / 0x100) & 0xFFFF);
- xts->xts_8 = (uint8_t)((dts / 0x1000000) & 0xFF);
- }
- else
- {
- prvTraceError("Bad param_maxDTS in prvTraceGetDTS");
- }
- prvTraceUpdateCounters();
- }
- }
-
- return (uint16_t)dts & param_maxDTS;
-}
-
-/*******************************************************************************
- * prvTraceLookupSymbolTableEntry
- *
- * Find an entry in the symbol table, return 0 if not present.
- *
- * The strings are stored in a byte pool, with four bytes of "meta-data" for
- * every string.
- * byte 0-1: index of next entry with same checksum (for fast lookup).
- * byte 2-3: reference to a symbol table entry, a label for vTracePrintF
- * format strings only (the handle of the destination channel).
- * byte 4..(4 + length): the string (object name or user event label), with
- * zero-termination
- ******************************************************************************/
-traceString prvTraceLookupSymbolTableEntry(const char* name,
- uint8_t crc6,
- uint8_t len,
- traceString chn)
-{
- uint16_t i = RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ];
-
- TRACE_ASSERT(name != NULL, "prvTraceLookupSymbolTableEntry: name == NULL", (traceString)0);
- TRACE_ASSERT(len != 0, "prvTraceLookupSymbolTableEntry: len == 0", (traceString)0);
-
- while (i != 0)
- {
- if (RecorderDataPtr->SymbolTable.symbytes[i + 2] == (chn & 0x00FF))
- {
- if (RecorderDataPtr->SymbolTable.symbytes[i + 3] == (chn / 0x100))
- {
- if (RecorderDataPtr->SymbolTable.symbytes[i + 4 + len] == '\0')
- {
- if (strncmp((char*)(& RecorderDataPtr->SymbolTable.symbytes[i + 4]), name, len) == 0)
- {
- break; /* found */
- }
- }
- }
- }
- i = (uint16_t)(RecorderDataPtr->SymbolTable.symbytes[i] + (RecorderDataPtr->SymbolTable.symbytes[i + 1] * 0x100));
- }
- return i;
-}
-
-/*******************************************************************************
- * prvTraceCreateSymbolTableEntry
- *
- * Creates an entry in the symbol table, independent if it exists already.
- *
- * The strings are stored in a byte pool, with four bytes of "meta-data" for
- * every string.
- * byte 0-1: index of next entry with same checksum (for fast lookup).
- * byte 2-3: reference to a symbol table entry, a label for vTracePrintF
- * format strings only (the handle of the destination channel).
- * byte 4..(4 + length): the string (object name or user event label), with
- * zero-termination
- ******************************************************************************/
-uint16_t prvTraceCreateSymbolTableEntry(const char* name,
- uint8_t crc6,
- uint8_t len,
- traceString channel)
-{
- 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 >= (TRC_CFG_SYMBOL_TABLE_SIZE))
- {
- prvTraceError("Symbol table full. Increase TRC_CFG_SYMBOL_TABLE_SIZE in trcConfig.h");
- ret = 0;
- }
- else
- {
-
- RecorderDataPtr->SymbolTable.symbytes
- [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex] =
- (uint8_t)(RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ] & 0x00FF);
-
- RecorderDataPtr->SymbolTable.symbytes
- [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 1] =
- (uint8_t)(RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ] / 0x100);
-
- RecorderDataPtr->SymbolTable.symbytes
- [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 2] =
- (uint8_t)(channel & 0x00FF);
-
- RecorderDataPtr->SymbolTable.symbytes
- [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 3] =
- (uint8_t)(channel / 0x100);
-
- /* set name (bytes 4...4+len-1) */
- prvStrncpy((char*)&(RecorderDataPtr->SymbolTable.symbytes
- [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 4]), name, len);
-
- /* Set zero termination (at offset 4+len) */
- RecorderDataPtr->SymbolTable.symbytes
- [RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 4 + len] = '\0';
-
- /* store index of entry (for return value, and as head of LL[crc6]) */
- RecorderDataPtr->SymbolTable.latestEntryOfChecksum
- [ crc6 ] = (uint16_t)RecorderDataPtr->SymbolTable.nextFreeSymbolIndex;
-
- RecorderDataPtr->SymbolTable.nextFreeSymbolIndex += (uint32_t) (len + 5);
-
- ret = (uint16_t)(RecorderDataPtr->SymbolTable.nextFreeSymbolIndex - (uint8_t)(len + 5));
- }
-
- return ret;
-}
-
-
-/*******************************************************************************
- * prvTraceGetChecksum
- *
- * Calculates a simple 6-bit checksum from a string, used to index the string
- * for fast symbol table lookup.
- ******************************************************************************/
-void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength)
-{
- unsigned char c;
- int length = 1; /* Should be 1 to account for '\0' */
- int crc = 0;
-
- TRACE_ASSERT(pname != NULL, "prvTraceGetChecksum: pname == NULL", TRC_UNUSED);
- TRACE_ASSERT(pcrc != NULL, "prvTraceGetChecksum: pcrc == NULL", TRC_UNUSED);
- TRACE_ASSERT(plength != NULL, "prvTraceGetChecksum: plength == NULL", TRC_UNUSED);
-
- if (pname != (const char *) 0)
- {
- for (; (c = (unsigned char) *pname++) != '\0';)
- {
- crc += c;
- length++;
- }
- }
- *pcrc = (uint8_t)(crc & 0x3F);
- *plength = (uint8_t)length;
-}
-
-#if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1)
-
-static void prvTraceStoreXID(traceHandle handle);
-
-/******************************************************************************
- * prvTraceStoreXID
- *
- * Stores an XID (eXtended IDentifier) event.
- * This is used if an object/task handle is larger than 255.
- * The parameter "handle" is the full (16 bit) handle, assumed to be 256 or
- * larger. Handles below 256 should not use this function.
- *
- * NOTE: this function MUST be called from within a critical section.
- *****************************************************************************/
-static void prvTraceStoreXID(traceHandle handle)
-{
- XPSEvent* xid;
-
- TRACE_ASSERT(handle >= 256, "prvTraceStoreXID: Handle < 256", TRC_UNUSED);
-
- xid = (XPSEvent*)prvTraceNextFreeEventBufferSlot();
-
- if (xid != NULL)
- {
- xid->type = XID;
-
- /* This function is (only) used when traceHandle is 16 bit... */
- xid->xps_16 = handle;
-
- prvTraceUpdateCounters();
- }
-}
-
-static uint8_t prvTraceGet8BitHandle(traceHandle handle)
-{
- if (handle > 255)
- {
- prvTraceStoreXID(handle);
- /* The full handle (16 bit) is stored in the XID event.
- This code (255) is used instead of zero (which is an error code).*/
- return 255;
- }
- return (uint8_t)(handle & 0xFF);
-}
-#endif /*(TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1)*/
-
-
-/* If using DWT timestamping (default on ARM Cortex-M3, M4 and M7), make sure the DWT unit is initialized. */
-#ifndef TRC_CFG_ARM_CM_USE_SYSTICK
-#if ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) && (defined (__CORTEX_M) && (__CORTEX_M >= 0x03)))
-void prvTraceInitCortexM()
-{
- /* Ensure that the DWT registers are unlocked and can be modified. */
- TRC_REG_ITM_LOCKACCESS = TRC_ITM_LOCKACCESS_UNLOCK;
-
- /* Make sure DWT is enabled, if supported */
- TRC_REG_DEMCR |= TRC_DEMCR_TRCENA;
-
- do{
- /* Verify that DWT is supported */
- if (TRC_REG_DEMCR == 0)
- {
- /* This function is called on Cortex-M3, M4 and M7 devices to initialize
- the DWT unit, assumed present. The DWT cycle counter is used for timestamping.
-
- If the below error is produced, the DWT unit does not seem to be available.
-
- In that case, define the macro TRC_CFG_ARM_CM_USE_SYSTICK in your build
- to use SysTick timestamping instead, or define your own timestamping by
- setting TRC_CFG_HARDWARE_PORT to TRC_HARDWARE_PORT_APPLICATION_DEFINED
- and make the necessary definitions, as explained in trcHardwarePort.h.*/
-
- prvTraceError("DWT unit not available, see code comment.");
- break;
- }
-
- /* Verify that DWT_CYCCNT is supported */
- if (TRC_REG_DWT_CTRL & TRC_DWT_CTRL_NOCYCCNT)
- {
- /* This function is called on Cortex-M3, M4 and M7 devices to initialize
- the DWT unit, assumed present. The DWT cycle counter is used for timestamping.
-
- If the below error is produced, the cycle counter does not seem to be available.
-
- In that case, define the macro TRC_CFG_ARM_CM_USE_SYSTICK in your build
- to use SysTick timestamping instead, or define your own timestamping by
- setting TRC_CFG_HARDWARE_PORT to TRC_HARDWARE_PORT_APPLICATION_DEFINED
- and make the necessary definitions, as explained in trcHardwarePort.h.*/
-
- prvTraceError("DWT_CYCCNT not available, see code comment.");
- break;
- }
-
- /* Reset the cycle counter */
- TRC_REG_DWT_CYCCNT = 0;
-
- /* Enable the cycle counter */
- TRC_REG_DWT_CTRL |= TRC_DWT_CTRL_CYCCNTENA;
-
- }while(0); /* breaks above jump here */
-}
-#endif
-#endif
-
-/******************************************************************************
- * prvTracePortGetTimeStamp
- *
- * Returns the current time based on the HWTC macros which provide a hardware
- * isolation layer towards the hardware timer/counter.
- *
- * The HWTC macros and prvTracePortGetTimeStamp is the main porting issue
- * or the trace recorder library. Typically you should not need to change
- * the code of prvTracePortGetTimeStamp if using the HWTC macros.
- *
- ******************************************************************************/
-void prvTracePortGetTimeStamp(uint32_t *pTimestamp)
-{
- static uint32_t last_hwtc_count = 0;
- uint32_t hwtc_count = 0;
-
-#if TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR
- /* systick based timer */
- static uint32_t last_traceTickCount = 0;
- uint32_t traceTickCount = 0;
-#else /*TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR*/
- /* Free running timer */
- static uint32_t last_hwtc_rest = 0;
- uint32_t diff = 0;
- uint32_t diff_scaled = 0;
-#endif /*TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR*/
-
- if (trace_disable_timestamp == 1)
- {
- if (pTimestamp)
- *pTimestamp = last_timestamp;
- return;
- }
-
- /* Retrieve TRC_HWTC_COUNT only once since the same value should be used all throughout this function. */
-#if (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_INCR)
- /* Get the increasing tick count */
- hwtc_count = (TRC_HWTC_COUNT);
-#elif (TRC_HWTC_TYPE == TRC_OS_TIMER_DECR || TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_DECR)
- /* Convert decreasing tick count into increasing tick count */
- hwtc_count = (TRC_HWTC_PERIOD) - (TRC_HWTC_COUNT);
-#else
- #error "TRC_HWTC_TYPE has unexpected value"
-#endif
-
-#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win32)
- /* The Win32 port uses ulGetRunTimeCounterValue for timestamping, which in turn
- uses QueryPerformanceCounter. That function is not always reliable when used over
- multiple threads. We must therefore handle rare cases where the timestamp is less
- than the previous. In practice, this should "never" roll over since the
- performance counter is 64 bit wide. */
-
- if (last_hwtc_count > hwtc_count)
- {
- hwtc_count = last_hwtc_count;
- }
-#endif
-
-#if (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)
- /* Timestamping is based on a timer that wraps at TRC_HWTC_PERIOD */
- 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. */
- last_timestamp = traceTickCount * ((TRC_HWTC_PERIOD) / (TRC_HWTC_DIVISOR));
- /* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / TRC_HWTC_DIVISOR. */
- last_timestamp += (hwtc_count + traceTickCount * ((TRC_HWTC_PERIOD) % (TRC_HWTC_DIVISOR))) / (TRC_HWTC_DIVISOR);
- }
- /* Store the previous value */
- last_traceTickCount = traceTickCount;
-
-#else /*(TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)*/
-
- /* Timestamping is based on a free running timer */
- /* This part handles free running clocks that can be scaled down to avoid too large DTS values.
- Without this, the scaled timestamp will incorrectly wrap at (2^32 / TRC_HWTC_DIVISOR) ticks.
- The scaled timestamp returned from this function is supposed to go from 0 -> 2^32, which in real time would represent (0 -> 2^32 * TRC_HWTC_DIVISOR) ticks. */
-
- /* First we see how long time has passed since the last timestamp call, and we also add the ticks that was lost when we scaled down the last time. */
- diff = (hwtc_count - last_hwtc_count) + last_hwtc_rest;
-
- /* Scale down the diff */
- diff_scaled = diff / (TRC_HWTC_DIVISOR);
-
- /* Find out how many ticks were lost when scaling down, so we can add them the next time */
- last_hwtc_rest = diff % (TRC_HWTC_DIVISOR);
-
- /* We increase the scaled timestamp by the scaled amount */
- last_timestamp += diff_scaled;
-#endif /*(TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)*/
-
- /* Is anyone interested in the results? */
- if (pTimestamp)
- *pTimestamp = last_timestamp;
-
- /* Store the previous value */
- last_hwtc_count = hwtc_count;
-}
-
-#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
-
-#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)*/
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcSnapshotRecorder.c + * + * The generic core of the trace recorder's snapshot mode. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#include "trcRecorder.h" + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#include <string.h> +#include <stdarg.h> +#include <stdint.h> + +#if ((TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR) || (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR)) + #error "CUSTOM timestamping mode is not (yet) supported in snapshot mode!" +#endif + +/* DO NOT CHANGE */ +#define TRACE_MINOR_VERSION 5 +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) +static traceHandle isrstack[TRC_CFG_MAX_ISR_NESTING]; +int32_t isPendingContextSwitch = 0; +#endif /* (TRC_CFG_INCLUDE_ISR_TRACING == 1) */ + +#if !defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1 +static int readyEventsEnabled = 1; +#endif /*!defined TRC_CFG_INCLUDE_READY_EVENTS || TRC_CFG_INCLUDE_READY_EVENTS == 1*/ + +/******************************************************************************* + * 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; + +uint32_t trace_disable_timestamp = 0; + +static uint32_t last_timestamp = 0; + +/* Indicates if we are currently performing a context switch or just running application code */ +volatile uint32_t uiTraceSystemState = TRC_STATE_IN_STARTUP; + +/* Flag that shows if inside a critical section of the recorder */ +volatile int recorder_busy = 0; + +/* Holds the value set by vTraceSetFrequency */ +uint32_t timestampFrequency = 0; + +/* The last error message of the recorder. NULL if no error message. */ +const char* traceErrorMessage = NULL; + +int8_t nISRactive = 0; + +traceHandle handle_of_last_logged_task = 0; + +/* Called when the recorder is stopped, set by vTraceSetStopHook. */ +TRACE_STOP_HOOK vTraceStopHookPtr = (TRACE_STOP_HOOK)0; + +uint16_t CurrentFilterMask = 0xFFFF; + +uint16_t CurrentFilterGroup = FilterGroup0; + +extern int8_t nISRactive; + +extern traceHandle handle_of_last_logged_task; + +/*************** Private Functions *******************************************/ +static void prvStrncpy(char* dst, const char* src, uint32_t maxLength); +static uint8_t prvTraceGetObjectState(uint8_t objectclass, traceHandle id); +static void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength); +static void* prvTraceNextFreeEventBufferSlot(void); +static uint16_t prvTraceGetDTS(uint16_t param_maxDTS); +static traceString prvTraceOpenSymbol(const char* name, traceString userEventChannel); +static void prvTraceUpdateCounters(void); + +void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_size); + +#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER) +static void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nEntries); +#endif + +static traceString prvTraceCreateSymbolTableEntry(const char* name, + uint8_t crc6, + uint8_t len, + traceString channel); + +static traceString prvTraceLookupSymbolTableEntry(const char* name, + uint8_t crc6, + uint8_t len, + traceString channel); + + +#if (TRC_CFG_INCLUDE_ISR_TRACING == 0) +/* ISR tracing is turned off */ +void prvTraceIncreaseISRActive(void); +void prvTraceDecreaseISRActive(void); +#endif /*(TRC_CFG_INCLUDE_ISR_TRACING == 0)*/ + +#if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) +static uint8_t prvTraceGet8BitHandle(traceHandle handle); +#else +#define prvTraceGet8BitHandle(x) ((uint8_t)x) +#endif + + +#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) +static uint32_t heapMemUsage = 0; +#endif + +#if (TRC_CFG_SCHEDULING_ONLY == 0) +static uint32_t prvTraceGetParam(uint32_t, uint32_t); +#endif + +/******************************************************************************* + * prvTracePortGetTimeStamp + * + * Returns the current time based on the HWTC macros which provide a hardware + * isolation layer towards the hardware timer/counter. + * + * The HWTC macros and prvTracePortGetTimeStamp is the main porting issue + * or the trace recorder library. Typically you should not need to change + * the code of prvTracePortGetTimeStamp if using the HWTC macros. + * + ******************************************************************************/ +void prvTracePortGetTimeStamp(uint32_t *puiTimestamp); + +static void prvTraceTaskInstanceFinish(int8_t direct); + +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) +static void vTraceUBData_Helper(traceUBChannel channelPair, va_list vl); +static void prvTraceUBHelper1(traceUBChannel channel, traceString eventLabel, traceString formatLabel, va_list vl); +static void prvTraceUBHelper2(traceUBChannel channel, uint32_t* data, uint32_t noOfSlots); +#endif /* (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) */ +#endif /* ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) */ + +/********* Public Functions **************************************************/ + +uint16_t uiIndexOfObject(traceHandle objecthandle, uint8_t objectclass); + +/******************************************************************************* + * prvTraceError + * + * Called by various parts in the recorder. Stops the recorder and stores a + * pointer to an error message, which is printed by the monitor task. + ******************************************************************************/ +void prvTraceError(const char* msg); + +/******************************************************************************* + * vTraceSetRecorderDataBuffer + * + * If custom allocation is used, this function must be called so the recorder + * library knows where to save the trace data. + ******************************************************************************/ +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) +void vTraceSetRecorderDataBuffer(void* pRecorderData) +{ + TRACE_ASSERT(pRecorderData != NULL, "vTraceSetRecorderDataBuffer, pRecorderData == NULL", TRC_UNUSED); + RecorderDataPtr = pRecorderData; +} +#endif + +/******************************************************************************* + * vTraceSetStopHook + * + * Sets a function to be called when the recorder is stopped. This can be used + * to save the trace to a file system, if available. This is only implemented + * for snapshot mode. + ******************************************************************************/ +void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction) +{ + vTraceStopHookPtr = stopHookFunction; +} + +/******************************************************************************* + * vTraceClear + * + * Resets the recorder. Only necessary if a restart is desired - this is not + * needed in the startup initialization. + ******************************************************************************/ +void vTraceClear(void) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + trcCRITICAL_SECTION_BEGIN(); + RecorderDataPtr->absTimeLastEventSecond = 0; + RecorderDataPtr->absTimeLastEvent = 0; + RecorderDataPtr->nextFreeIndex = 0; + RecorderDataPtr->numEvents = 0; + RecorderDataPtr->bufferIsFull = 0; + traceErrorMessage = NULL; + RecorderDataPtr->internalErrorOccured = 0; + (void)memset(RecorderDataPtr->eventData, 0, RecorderDataPtr->maxEvents * 4); + handle_of_last_logged_task = 0; + trcCRITICAL_SECTION_END(); +} + +/******************************************************************************* + * uiTraceStart + * + * Starts the recorder. The recorder will not be started if an error has been + * indicated using prvTraceError, e.g. if any of the Nx constants in trcConfig.h + * has a too small value (TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc). + * + * Returns 1 if the recorder was started successfully. + * Returns 0 if the recorder start was prevented due to a previous internal + * error. In that case, check xTraceGetLastError to get the error message. + * Any error message is also presented when opening a trace file. + * + * This function is obsolete, but has been saved for backwards compatibility. + * We recommend using vTraceEnable instead. + ******************************************************************************/ +uint32_t uiTraceStart(void) +{ + traceHandle handle; + TRACE_ALLOC_CRITICAL_SECTION(); + + handle = 0; + + if (RecorderDataPtr == NULL) + { + TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized. Use vTraceEnable() instead!", 0); + return 0; + } + + if (RecorderDataPtr->recorderActive == 1) + return 1; /* Already running */ + + if (traceErrorMessage == NULL) + { + trcCRITICAL_SECTION_BEGIN(); + RecorderDataPtr->recorderActive = 1; + + handle = TRACE_GET_TASK_NUMBER(TRACE_GET_CURRENT_TASK()); + if (handle == 0) + { + /* This occurs if the scheduler is not yet started. + This creates a dummy "(startup)" task entry internally in the + recorder */ + handle = prvTraceGetObjectHandle(TRACE_CLASS_TASK); + prvTraceSetObjectName(TRACE_CLASS_TASK, handle, "(startup)"); + + prvTraceSetPriorityProperty(TRACE_CLASS_TASK, handle, 0); + } + + prvTraceStoreTaskswitch(handle); /* Register the currently running task */ + trcCRITICAL_SECTION_END(); + } + + return RecorderDataPtr->recorderActive; +} + +/******************************************************************************* + * vTraceStart + * + * Starts the recorder. The recorder will not be started if an error has been + * indicated using prvTraceError, e.g. if any of the Nx constants in trcConfig.h + * has a too small value (TRC_CFG_NTASK, TRC_CFG_NQUEUE, etc). + * + * This function is obsolete, but has been saved for backwards compatibility. + * We recommend using vTraceEnable instead. + ******************************************************************************/ +void vTraceStart(void) +{ + (void)uiTraceStart(); +} + +/******************************************************************************* + * vTraceStop + * + * Stops the recorder. The recording can be resumed by calling vTraceStart. + * This does not reset the recorder. Use vTraceClear if that is desired. + ******************************************************************************/ +void vTraceStop(void) +{ + if (RecorderDataPtr != NULL) + { + RecorderDataPtr->recorderActive = 0; + } + + if (vTraceStopHookPtr != (TRACE_STOP_HOOK)0) + { + (*vTraceStopHookPtr)(); /* An application call-back function. */ + } +} + +/******************************************************************************* +* xTraceIsRecordingEnabled +* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0. +******************************************************************************/ +int xTraceIsRecordingEnabled(void) +{ + if (RecorderDataPtr != NULL) + { + return (int)RecorderDataPtr->recorderActive; + } + else + { + return 0; + } +} + +/******************************************************************************* + * xTraceGetLastError + * + * Gives the last error message, if any. NULL if no error message is stored. + * Any error message is also presented when opening a trace file. + ******************************************************************************/ +const char* xTraceGetLastError(void) +{ + return traceErrorMessage; +} + +/******************************************************************************* +* vTraceClearError +* +* Removes any previous error message generated by recorder calling prvTraceError. +* By calling this function, it may be possible to start/restart the trace +* despite errors in the recorder, but there is no guarantee that the trace +* recorder will work correctly in that case, depending on the type of error. +******************************************************************************/ +void vTraceClearError(void) +{ + traceErrorMessage = NULL; + if (RecorderDataPtr != NULL) + { + RecorderDataPtr->internalErrorOccured = 0; + } +} + +/******************************************************************************* + * xTraceGetTraceBuffer + * + * Returns a pointer to the recorder data structure. Use this together with + * uiTraceGetTraceBufferSize if you wish to implement an own store/upload + * solution, e.g., in case a debugger connection is not available for uploading + * the data. + ******************************************************************************/ +void* xTraceGetTraceBuffer(void) +{ + return RecorderDataPtr; +} + +/******************************************************************************* + * uiTraceGetTraceBufferSize + * + * Gets the size of the recorder data structure. For use together with + * vTraceGetTraceBuffer if you wish to implement an own store/upload solution, + * e.g., in case a debugger connection is not available for uploading the data. + ******************************************************************************/ +uint32_t uiTraceGetTraceBufferSize(void) +{ + return sizeof(RecorderDataType); +} + +/****************************************************************************** + * prvTraceTaskInstanceFinish + * + * Private common function for the vTraceTaskInstanceFinishXXX functions. + *****************************************************************************/ +static void prvTraceTaskInstanceFinish(int8_t direct) +{ + TaskInstanceStatusEvent* tis; + uint8_t dts45; + + TRACE_ALLOC_CRITICAL_SECTION(); + + trcCRITICAL_SECTION_BEGIN(); + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + { + dts45 = (uint8_t)prvTraceGetDTS(0xFF); + tis = (TaskInstanceStatusEvent*) prvTraceNextFreeEventBufferSlot(); + if (tis != NULL) + { + if (direct == 0) + tis->type = TASK_INSTANCE_FINISHED_NEXT_KSE; + else + tis->type = TASK_INSTANCE_FINISHED_DIRECT; + + tis->dts = dts45; + prvTraceUpdateCounters(); + } + } + trcCRITICAL_SECTION_END(); +} + +/****************************************************************************** + * vTraceInstanceFinishedNext(void) + * + * Marks the current task instance as finished on the next kernel call. + * + * If that kernel call is blocking, the instance ends after the blocking event + * and the corresponding return event is then the start of the next instance. + * If the kernel call is not blocking, the viewer instead splits the current + * fragment right before the kernel call, which makes this call the first event + * of the next instance. + * + * See also TRC_CFG_USE_IMPLICIT_IFE_RULES in trcConfig.h + * + * Example: + * + * while(1) + * { + * xQueueReceive(CommandQueue, &command, timeoutDuration); + * processCommand(command); + * vTraceInstanceFinishedNext(); + * } + *****************************************************************************/ +void vTraceInstanceFinishedNext(void) +{ + prvTraceTaskInstanceFinish(0); +} + +/****************************************************************************** + * vTraceInstanceFinishedNow(void) + * + * Marks the current task instance as finished at this very instant. + * This makes the viewer to splits the current fragment at this point and begin + * a new actor instance. + * + * See also TRC_CFG_USE_IMPLICIT_IFE_RULES in trcConfig.h + * + * Example: + * + * This example will generate two instances for each loop iteration. + * The first instance ends at vTraceInstanceFinishedNow(), while the second + * instance ends at the next xQueueReceive call. + * + * while (1) + * { + * xQueueReceive(CommandQueue, &command, timeoutDuration); + * ProcessCommand(command); + * vTraceInstanceFinishedNow(); + * DoSometingElse(); + * vTraceInstanceFinishedNext(); + * } + *****************************************************************************/ +void vTraceInstanceFinishedNow(void) +{ + prvTraceTaskInstanceFinish(1); +} + +/******************************************************************************* + * Interrupt recording functions + ******************************************************************************/ + +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) + +/******************************************************************************* + * xTraceSetISRProperties + * + * Stores a name and priority level for an Interrupt Service Routine, to allow + * for better visualization. Returns a traceHandle used by vTraceStoreISRBegin. + * + * Example: + * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt + * ... + * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1); + * ... + * void ISR_handler() + * { + * vTraceStoreISRBegin(Timer1Handle); + * ... + * vTraceStoreISREnd(0); + * } + ******************************************************************************/ + traceHandle xTraceSetISRProperties(const char* name, uint8_t priority) +{ + static traceHandle handle = 0; + TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0); + TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "xTraceSetISRProperties: Invalid value for handle", 0); + TRACE_ASSERT(name != NULL, "xTraceSetISRProperties: name == NULL", 0); + + handle++; + + prvTraceSetObjectName(TRACE_CLASS_ISR, handle, name); + prvTraceSetPriorityProperty(TRACE_CLASS_ISR, handle, priority); + + return handle; +} + +/******************************************************************************* + * vTraceStoreISRBegin + * + * Registers the beginning of an Interrupt Service Routine, using a traceHandle + * provided by xTraceSetISRProperties. + * + * Example: + * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt + * ... + * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1); + * ... + * void ISR_handler() + * { + * vTraceStoreISRBegin(Timer1Handle); + * ... + * vTraceStoreISREnd(0); + * } + ******************************************************************************/ +void vTraceStoreISRBegin(traceHandle handle) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + if (recorder_busy) + { + /************************************************************************* + * This occurs if an ISR calls a trace function, preempting a previous + * trace call that is being processed in a different ISR or task. + * If this occurs, there is probably a problem in the definition of the + * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and + * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt + * and any other ISRs that calls the trace recorder directly or via + * traced kernel functions. The ARM port disables all interrupts using the + * PRIMASK register to avoid this issue. + *************************************************************************/ + prvTraceError("vTraceStoreISRBegin - recorder busy! See code comment."); + return; + } + trcCRITICAL_SECTION_BEGIN(); + + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + { + uint16_t dts4; + + TRACE_ASSERT(handle != 0, "vTraceStoreISRBegin: Invalid ISR handle (NULL)", TRC_UNUSED); + TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_ISR], "vTraceStoreISRBegin: Invalid ISR handle (> NISR)", TRC_UNUSED); + + dts4 = (uint16_t)prvTraceGetDTS(0xFFFF); + + if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ + { + if (nISRactive < TRC_CFG_MAX_ISR_NESTING) + { + TSEvent* ts; + uint8_t hnd8 = prvTraceGet8BitHandle(handle); + isrstack[nISRactive] = handle; + nISRactive++; + ts = (TSEvent*)prvTraceNextFreeEventBufferSlot(); + if (ts != NULL) + { + ts->type = TS_ISR_BEGIN; + ts->dts = dts4; + ts->objHandle = hnd8; + prvTraceUpdateCounters(); + } + } + else + { + /* This should not occur unless something is very wrong */ + prvTraceError("Too many nested interrupts!"); + } + } + } + trcCRITICAL_SECTION_END(); +} + +/******************************************************************************* + * vTraceStoreISREnd + * + * Registers the end of an Interrupt Service Routine. + * + * The parameter pendingISR indicates if the interrupt has requested a + * task-switch (= 1), e.g., by signaling a semaphore. Otherwise (= 0) the + * interrupt is assumed to return to the previous context. + * + * Example: + * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt + * traceHandle traceHandleIsrTimer1 = 0; // The ID set by the recorder + * ... + * traceHandleIsrTimer1 = xTraceSetISRProperties("ISRTimer1", PRIO_OF_ISR_TIMER1); + * ... + * void ISR_handler() + * { + * vTraceStoreISRBegin(traceHandleIsrTimer1); + * ... + * vTraceStoreISREnd(0); + * } + ******************************************************************************/ +void vTraceStoreISREnd(int pendingISR) +{ + TSEvent* ts; + uint16_t dts5; + uint8_t hnd8 = 0, type = 0; + + TRACE_ALLOC_CRITICAL_SECTION(); + + if (! RecorderDataPtr->recorderActive || ! handle_of_last_logged_task) + { + return; + } + + if (recorder_busy) + { + /************************************************************************* + * This occurs if an ISR calls a trace function, preempting a previous + * trace call that is being processed in a different ISR or task. + * If this occurs, there is probably a problem in the definition of the + * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and + * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt + * and any other ISRs that calls the trace recorder directly or via + * traced kernel functions. The ARM port disables all interrupts using the + * PRIMASK register to avoid this issue. + *************************************************************************/ + prvTraceError("vTraceStoreISREnd - recorder busy! See code comment."); + return; + } + + if (nISRactive == 0) + { + prvTraceError("Unmatched call to vTraceStoreISREnd (nISRactive == 0, expected > 0)"); + return; + } + + trcCRITICAL_SECTION_BEGIN(); + isPendingContextSwitch |= pendingISR; /* Is there a pending context switch right now? */ + nISRactive--; + if (nISRactive > 0) + { + /* Return to another ISR */ + type = TS_ISR_RESUME; + hnd8 = prvTraceGet8BitHandle(isrstack[nISRactive - 1]); /* isrstack[nISRactive] is the handle of the ISR we're currently exiting. isrstack[nISRactive - 1] is the handle of the ISR that was executing previously. */ + } + else if ((isPendingContextSwitch == 0) || (prvTraceIsSchedulerSuspended())) + { + /* Return to interrupted task, if no context switch will occur in between. */ + type = TS_TASK_RESUME; + hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task); + } + + if (type != 0) + { + dts5 = (uint16_t)prvTraceGetDTS(0xFFFF); + ts = (TSEvent*)prvTraceNextFreeEventBufferSlot(); + if (ts != NULL) + { + ts->type = type; + ts->objHandle = hnd8; + ts->dts = dts5; + prvTraceUpdateCounters(); + } + } + + trcCRITICAL_SECTION_END(); +} + +#else + +/* ISR tracing is turned off */ +void prvTraceIncreaseISRActive(void) +{ + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + nISRactive++; +} + +void prvTraceDecreaseISRActive(void) +{ + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + nISRactive--; +} +#endif /* (TRC_CFG_INCLUDE_ISR_TRACING == 1)*/ + + +/********************************************************************************/ +/* User Event functions */ +/********************************************************************************/ + +#define MAX_ARG_SIZE (4+32) + +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +static uint8_t writeInt8(void * buffer, uint8_t i, uint8_t value) +{ + TRACE_ASSERT(buffer != NULL, "writeInt8: buffer == NULL", 0); + + if (i >= MAX_ARG_SIZE) + { + return 255; + } + + ((uint8_t*)buffer)[i] = value; + + if (i + 1 > MAX_ARG_SIZE) + { + return 255; + } + + return ((uint8_t) (i + 1)); +} +#endif + +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +static uint8_t writeInt16(void * buffer, uint8_t i, uint16_t value) +{ + TRACE_ASSERT(buffer != NULL, "writeInt16: buffer == NULL", 0); + + /* Align to multiple of 2 */ + while ((i % 2) != 0) + { + if (i >= MAX_ARG_SIZE) + { + return 255; + } + + ((uint8_t*)buffer)[i] = 0; + i++; + } + + if (i + 2 > MAX_ARG_SIZE) + { + return 255; + } + + ((uint16_t*)buffer)[i/2] = value; + + return ((uint8_t) (i + 2)); +} +#endif + +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +static uint8_t writeInt32(void * buffer, uint8_t i, uint32_t value) +{ + TRACE_ASSERT(buffer != NULL, "writeInt32: buffer == NULL", 0); + + /* A 32 bit value should begin at an even 4-byte address */ + while ((i % 4) != 0) + { + if (i >= MAX_ARG_SIZE) + { + return 255; + } + + ((uint8_t*)buffer)[i] = 0; + i++; + } + + if (i + 4 > MAX_ARG_SIZE) + { + return 255; + } + + ((uint32_t*)buffer)[i/4] = value; + + return ((uint8_t) (i + 4)); +} +#endif + +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_INCLUDE_FLOAT_SUPPORT)) +static uint8_t writeFloat(void * buffer, uint8_t i, float value) +{ + TRACE_ASSERT(buffer != NULL, "writeFloat: buffer == NULL", 0); + + /* A 32 bit value should begin at an even 4-byte address */ + while ((i % 4) != 0) + { + if (i >= MAX_ARG_SIZE) + { + return 255; + } + + ((uint8_t*)buffer)[i] = 0; + i++; + } + + if (i + 4 > MAX_ARG_SIZE) + { + return 255; + } + + ((float*)buffer)[i/4] = value; + + return i + 4; +} +#endif + +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_INCLUDE_FLOAT_SUPPORT)) +static uint8_t writeDouble(void * buffer, uint8_t i, double value) +{ + uint32_t * dest; + uint32_t * src = (uint32_t*)&value; + + TRACE_ASSERT(buffer != NULL, "writeDouble: buffer == NULL", 0); + + /* The double is written as two 32 bit values, and should begin at an even + 4-byte address (to avoid having to align with 8 byte) */ + while (i % 4 != 0) + { + if (i >= MAX_ARG_SIZE) + { + return 255; + } + + ((uint8_t*)buffer)[i] = 0; + i++; + } + + if (i + 8 > MAX_ARG_SIZE) + { + return 255; + } + + dest = &(((uint32_t *)buffer)[i/4]); + + dest[0] = src[0]; + dest[1] = src[1]; + + return i + 8; +} +#endif + +/******************************************************************************* + * prvTraceUserEventFormat + * + * Parses the format string and stores the arguments in the buffer. + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +static uint8_t prvTraceUserEventFormat(const char* formatStr, va_list vl, uint8_t* buffer, uint8_t byteOffset) +{ + uint16_t formatStrIndex = 0; + uint8_t argCounter = 0; + uint8_t i = byteOffset; + + while (formatStr[formatStrIndex] != '\0') + { + if (formatStr[formatStrIndex] == '%') + { + if (formatStr[formatStrIndex + 1] == '%') + { + formatStrIndex += 2; + continue; + } + + /* We found a possible argument */ + argCounter++; + + formatStrIndex++; + + while ((formatStr[formatStrIndex] >= '0' && formatStr[formatStrIndex] <= '9') || formatStr[formatStrIndex] == '#' || formatStr[formatStrIndex] == '.') + formatStrIndex++; + + /* This check is necessary to avoid moving past end of string. */ + if (formatStr[formatStrIndex] != '\0') + { + switch (formatStr[formatStrIndex]) + { + case 'd': + i = writeInt32( buffer, + i, + (uint32_t)va_arg(vl, uint32_t)); + break; + case 'x': + case 'X': + case 'u': + i = writeInt32( buffer, + i, + (uint32_t)va_arg(vl, uint32_t)); + break; + case 's': + i = writeInt16( buffer, + i, + xTraceRegisterString((char*)va_arg(vl, char*))); + break; + +#if (TRC_CFG_INCLUDE_FLOAT_SUPPORT) + /* Yes, "double" as type also in the float + case. This since "float" is promoted into "double" + by the va_arg stuff. */ + case 'f': + i = writeFloat( buffer, + i, + (float)va_arg(vl, double)); + break; +#else + /* No support for floats, but attempt to store a float user event + avoid a possible crash due to float reference. Instead store the + data on uint_32 format (will not be displayed anyway). This is just + to keep va_arg and i consistent. */ + + case 'f': + i = writeInt32( buffer, + i, + (uint32_t)va_arg(vl, double)); + break; +#endif + case 'l': + formatStrIndex++; + switch (formatStr[formatStrIndex]) + { +#if (TRC_CFG_INCLUDE_FLOAT_SUPPORT) + case 'f': i = writeDouble(buffer, + i, + (double)va_arg(vl, double)); + break; +#else + /* No support for floats, but attempt to store a float user event + avoid a possible crash due to float reference. Instead store the + data on uint_32 format (will not be displayed anyway). This is just + to keep va_arg and i consistent. */ + case 'f': + i = writeInt32( buffer, /* In this case, the value will not be shown anyway */ + i, + (uint32_t)va_arg(vl, double)); + + i = writeInt32( buffer, /* Do it twice, to write in total 8 bytes */ + i, + (uint32_t)va_arg(vl, double)); + break; +#endif + } + break; + case 'h': + formatStrIndex++; + switch (formatStr[formatStrIndex]) + { + case 'd': + i = writeInt16( buffer, + i, + (uint16_t)va_arg(vl, uint32_t)); + break; + case 'u': + i = writeInt16( buffer, + i, + (uint16_t)va_arg(vl, uint32_t)); + break; + } + break; + case 'b': + formatStrIndex++; + switch (formatStr[formatStrIndex]) + { + case 'd': + i = writeInt8( buffer, + i, + (uint8_t)va_arg(vl, uint32_t)); + break; + case 'u': + i = writeInt8( buffer, + i, + (uint8_t)va_arg(vl, uint32_t)); + break; + } + break; + default: + /* False alarm: this wasn't a valid format specifier */ + argCounter--; + break; + } + + if (argCounter > 15) + { + prvTraceError("vTracePrintF - Too many arguments, max 15 allowed!"); + return 0; + } + } + else + break; + } + formatStrIndex++; + if (i == 255) + { + prvTraceError("vTracePrintF - Too large arguments, max 32 byte allowed!"); + return 0; + } + } + return (uint8_t)(i+3)/4; +} +#endif + +/******************************************************************************* + * prvTraceClearChannelBuffer + * + * Clears a number of items in the channel buffer, starting from nextSlotToWrite. + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)) +static void prvTraceClearChannelBuffer(uint32_t count) +{ + uint32_t slots; + + TRACE_ASSERT((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) >= count, + "prvTraceClearChannelBuffer: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED); + + /* Check if we're close to the end of the buffer */ + if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE)) + { + slots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */ + (void)memset(&RecorderDataPtr->userEventBuffer.channelBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite], 0, slots); + (void)memset(&RecorderDataPtr->userEventBuffer.channelBuffer[0], 0, (count - slots)); + } + else + (void)memset(&RecorderDataPtr->userEventBuffer.channelBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite], 0, count); +} +#endif + +/******************************************************************************* + * prvTraceCopyToDataBuffer + * + * Copies a number of items to the data buffer, starting from nextSlotToWrite. + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)) +static void prvTraceCopyToDataBuffer(uint32_t* data, uint32_t count) +{ + uint32_t slots; + + TRACE_ASSERT(data != NULL, + "prvTraceCopyToDataBuffer: data == NULL.", TRC_UNUSED); + TRACE_ASSERT(count <= (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE), + "prvTraceCopyToDataBuffer: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED); + /* Check if we're close to the end of the buffer */ + if (RecorderDataPtr->userEventBuffer.nextSlotToWrite + count > (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE)) + { + slots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) - RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Number of slots before end of buffer */ + (void)memcpy(&RecorderDataPtr->userEventBuffer.dataBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite * 4], data, slots * 4); + (void)memcpy(&RecorderDataPtr->userEventBuffer.dataBuffer[0], data + slots, (count - slots) * 4); + } + else + { + (void)memcpy(&RecorderDataPtr->userEventBuffer.dataBuffer[RecorderDataPtr->userEventBuffer.nextSlotToWrite * 4], data, count * 4); + } +} +#endif + +/******************************************************************************* + * prvTraceUBHelper1 + * + * Calls on prvTraceUserEventFormat() to do the actual formatting, then goes on + * to the next helper function. + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)) +static void prvTraceUBHelper1(traceUBChannel channel, traceString eventLabel, traceString formatLabel, va_list vl) +{ + uint32_t data[(3 + MAX_ARG_SIZE) / 4]; + uint8_t byteOffset = 4; /* Need room for timestamp */ + uint8_t noOfSlots; + + if (channel == 0) + { + /* We are dealing with an unknown channel format pair */ + byteOffset = (uint8_t)(byteOffset + 4); /* Also need room for channel and format */ + ((uint16_t*)data)[2] = eventLabel; + ((uint16_t*)data)[3] = formatLabel; + } + + noOfSlots = prvTraceUserEventFormat((char*)&(RecorderDataPtr->SymbolTable.symbytes[formatLabel+4]), vl, (uint8_t*)data, byteOffset); + + prvTraceUBHelper2(channel, data, noOfSlots); +} +#endif + +/******************************************************************************* + * prvTraceUBHelper2 + * + * This function simply copies the data buffer to the actual user event buffer. + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)) +static void prvTraceUBHelper2(traceUBChannel channel, uint32_t* data, uint32_t noOfSlots) +{ + static uint32_t old_timestamp = 0; + uint32_t old_nextSlotToWrite = 0; + + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ASSERT((TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE) >= noOfSlots, "prvTraceUBHelper2: TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE is too small to handle this event.", TRC_UNUSED); + + trcCRITICAL_SECTION_BEGIN(); + /* Store the timestamp */ + prvTracePortGetTimeStamp(data); + + if (*data < old_timestamp) + { + RecorderDataPtr->userEventBuffer.wraparoundCounter++; + } + + old_timestamp = *data; + + /* Start by erasing any information in the channel buffer */ + prvTraceClearChannelBuffer(noOfSlots); + + prvTraceCopyToDataBuffer(data, noOfSlots); /* Will wrap around the data if necessary */ + + old_nextSlotToWrite = RecorderDataPtr->userEventBuffer.nextSlotToWrite; /* Save the index that we want to write the channel data at when we're done */ + RecorderDataPtr->userEventBuffer.nextSlotToWrite = (RecorderDataPtr->userEventBuffer.nextSlotToWrite + noOfSlots) % (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE); /* Make sure we never end up outside the buffer */ + + /* Write to the channel buffer to indicate that this user event is ready to be used */ + if (channel != 0) + { + RecorderDataPtr->userEventBuffer.channelBuffer[old_nextSlotToWrite] = channel; + } + else + { + /* 0xFF indicates that this is not a normal channel id */ + RecorderDataPtr->userEventBuffer.channelBuffer[old_nextSlotToWrite] = (traceUBChannel)0xFF; + } + trcCRITICAL_SECTION_END(); +} +#endif + +/******************************************************************************* + * xTraceRegisterUBChannel + * + * Registers a channel for Separated User Events, i.e., those stored in the + * separate user event buffer. + * + * Note: Only available if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is enabled in + * trcSnapshotConfig.h + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)) +traceUBChannel xTraceRegisterUBChannel(traceString channel, traceString formatStr) +{ + uint8_t i; + traceUBChannel retVal = 0; + + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ASSERT(formatStr != 0, "xTraceRegisterChannelFormat: formatStr == 0", (traceUBChannel)0); + + trcCRITICAL_SECTION_BEGIN(); + for (i = 1; i <= (TRC_CFG_UB_CHANNELS); i++) /* Size of the channels buffer is TRC_CFG_UB_CHANNELS + 1. Index 0 is unused. */ + { + if(RecorderDataPtr->userEventBuffer.channels[i].name == 0 && RecorderDataPtr->userEventBuffer.channels[i].defaultFormat == 0) + { + /* Found empty slot */ + RecorderDataPtr->userEventBuffer.channels[i].name = channel; + RecorderDataPtr->userEventBuffer.channels[i].defaultFormat = formatStr; + retVal = (traceUBChannel)i; + break; + } + + if (RecorderDataPtr->userEventBuffer.channels[i].name == channel && RecorderDataPtr->userEventBuffer.channels[i].defaultFormat == formatStr) + { + /* Found a match */ + retVal = (traceUBChannel)i; + break; + } + } + trcCRITICAL_SECTION_END(); + + return retVal; +} +#endif + +/****************************************************************************** + * vTraceUBData + * + * Slightly faster version of vTracePrintF() due to no lookups. + * + * Note: This is only available if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is + * enabled in trcSnapshotConfig.h + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)) +void vTraceUBData(traceUBChannel channelPair, ...) +{ + va_list vl; + + TRACE_ASSERT(channelPair != 0, "vTraceUBData: Not a valid traceUBChannel!", TRC_UNUSED); + + va_start(vl, channelPair); + vTraceUBData_Helper(channelPair, vl); + va_end(vl); +} +#endif + +/* Extracts the channel name and format string from the traceUBChannel, then calls prvTraceUBHelper1. */ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)) +void vTraceUBData_Helper(traceUBChannel channelPair, va_list vl) +{ + traceString channel; + traceString formatStr; + + TRACE_ASSERT(channelPair != 0, "vTraceUBData_Helper: channelPair == 0", TRC_UNUSED); + TRACE_ASSERT(channelPair <= (TRC_CFG_UB_CHANNELS), "vTraceUBData_Helper: ", TRC_UNUSED); + + channel = RecorderDataPtr->userEventBuffer.channels[channelPair].name; + formatStr = RecorderDataPtr->userEventBuffer.channels[channelPair].defaultFormat; + + prvTraceUBHelper1(channelPair, channel, formatStr, vl); +} +#endif + +/****************************************************************************** + * vTraceUBEvent + * + * Slightly faster version of ... due to no lookups. + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1)) +void vTraceUBEvent(traceUBChannel channelPair) +{ + uint32_t data[(3 + MAX_ARG_SIZE) / 4]; + + TRACE_ASSERT(channelPair != 0, "vTraceUBEvent: channelPair == 0", TRC_UNUSED); + TRACE_ASSERT(channelPair <= (TRC_CFG_UB_CHANNELS), "vTraceUBEvent: ", TRC_UNUSED); + + prvTraceUBHelper2(channelPair, data, 1); /* Only need one slot for timestamp */ +} +#endif + +/****************************************************************************** + * vTracePrintF + * + * Generates User Event with formatted text and data, similar to a "printf". + * It is very fast compared to a normal "printf" since this function only + * stores the arguments. The actual formatting is done + * on the host PC when the trace is displayed in the viewer tool. + * + * User Event labels are created using xTraceRegisterString. + * Example: + * + * traceString adc_uechannel = xTraceRegisterString("ADC User Events"); + * ... + * vTracePrintF(adc_uechannel, + * "ADC channel %d: %lf volts", + * ch, (double)adc_reading/(double)scale); + * + * This can be combined into one line, if desired, but this is slower: + * + * vTracePrintF(xTraceRegisterString("ADC User Events"), + * "ADC channel %d: %lf volts", + * ch, (double)adc_reading/(double)scale); + * + * Calling xTraceRegisterString multiple times will not create duplicate entries, but + * it is of course faster to just do it once, and then keep the handle for later + * use. If you don't have any data arguments, only a text label/string, it is + * better to use vTracePrint - it is faster. + * + * Format specifiers supported: + * %d - 32 bit signed integer + * %u - 32 bit unsigned integer + * %f - 32 bit float + * %s - string (is copied to the recorder symbol table) + * %hd - 16 bit signed integer + * %hu - 16 bit unsigned integer + * %bd - 8 bit signed integer + * %bu - 8 bit unsigned integer + * %lf - double-precision float (Note! See below...) + * + * Up to 15 data arguments are allowed, with a total size of maximum 32 byte. + * In case this is exceeded, the user event is changed into an error message. + * + * The data is stored in trace buffer, and is packed to allow storing multiple + * smaller data entries in the same 4-byte record, e.g., four 8-bit values. + * A string requires two bytes, as the symbol table is limited to 64K. Storing + * a double (%lf) uses two records, so this is quite costly. Use float (%f) + * unless the higher precision is really necessary. + * + * Note that the double-precision float (%lf) assumes a 64 bit double + * representation. This does not seem to be the case on e.g. PIC24 and PIC32. + * Before using a %lf argument on a 16-bit MCU, please verify that + * "sizeof(double)" actually gives 8 as expected. If not, use %f instead. + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +void vTracePrintF(traceString eventLabel, const char* formatStr, ...) +{ + va_list vl; + + va_start(vl, formatStr); + vTraceVPrintF(eventLabel, formatStr, vl); + va_end(vl); +} +#endif + +/****************************************************************************** + * vTraceVPrintF + * + * vTracePrintF variant that accepts a va_list. + * See vTracePrintF documentation for further details. + * + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +void vTraceVPrintF(traceString eventLabel, const char* formatStr, va_list vl) +{ +#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 0) + uint32_t noOfSlots; + UserEvent* ue1; + uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4]; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ASSERT(formatStr != NULL, "vTraceVPrintF: formatStr == NULL", TRC_UNUSED); + + trcCRITICAL_SECTION_BEGIN(); + + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + { + /* First, write the "primary" user event entry in the local buffer, but + let the event type be "EVENT_BEING_WRITTEN" for now...*/ + + ue1 = (UserEvent*)(&tempDataBuffer[0]); + + ue1->type = EVENT_BEING_WRITTEN; /* Update this as the last step */ + + noOfSlots = prvTraceUserEventFormat(formatStr, vl, (uint8_t*)tempDataBuffer, 4); + + /* Store the format string, with a reference to the channel symbol */ + ue1->payload = prvTraceOpenSymbol(formatStr, eventLabel); + + ue1->dts = (uint8_t)prvTraceGetDTS(0xFF); + + /* prvTraceGetDTS might stop the recorder in some cases... */ + if (RecorderDataPtr->recorderActive) + { + + /* If the data does not fit in the remaining main buffer, wrap around to + 0 if allowed, otherwise stop the recorder and quit). */ + if (RecorderDataPtr->nextFreeIndex + noOfSlots > RecorderDataPtr->maxEvents) + { + #if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER) + (void)memset(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4], + 0, + (RecorderDataPtr->maxEvents - RecorderDataPtr->nextFreeIndex)*4); + RecorderDataPtr->nextFreeIndex = 0; + RecorderDataPtr->bufferIsFull = 1; + #else + + /* Stop recorder, since the event data will not fit in the + buffer and not circular buffer in this case... */ + vTraceStop(); + #endif + } + + /* Check if recorder has been stopped (i.e., vTraceStop above) */ + if (RecorderDataPtr->recorderActive) + { + /* Check that the buffer to be overwritten does not contain any user + events that would be partially overwritten. If so, they must be "killed" + by replacing the user event and following data with NULL events (i.e., + using a memset to zero).*/ + #if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER) + prvCheckDataToBeOverwrittenForMultiEntryEvents((uint8_t)noOfSlots); + #endif + /* Copy the local buffer to the main buffer */ + (void)memcpy(& RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4], + tempDataBuffer, + noOfSlots * 4); + + /* Update the event type, i.e., number of data entries following the + main USER_EVENT entry (Note: important that this is after the memcpy, + but within the critical section!)*/ + RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex * 4] = + (uint8_t) ( USER_EVENT + noOfSlots - 1 ); + + /* Update the main buffer event index (already checked that it fits in + the buffer, so no need to check for wrapping)*/ + + RecorderDataPtr->nextFreeIndex += noOfSlots; + RecorderDataPtr->numEvents += noOfSlots; + + if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE)) + { + #if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER) + /* We have reached the end, but this is a ring buffer. Start from the beginning again. */ + RecorderDataPtr->bufferIsFull = 1; + RecorderDataPtr->nextFreeIndex = 0; + #else + /* We have reached the end so we stop. */ + vTraceStop(); + #endif + } + } + + #if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER) + /* Make sure the next entry is cleared correctly */ + prvCheckDataToBeOverwrittenForMultiEntryEvents(1); + #endif + + } + } + trcCRITICAL_SECTION_END(); + +#elif (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) + /* Use the separate user event buffer */ + traceString formatLabel; + traceUBChannel channel; + + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + { + formatLabel = xTraceRegisterString(formatStr); + + channel = xTraceRegisterUBChannel(eventLabel, formatLabel); + + prvTraceUBHelper1(channel, eventLabel, formatLabel, vl); + } +#endif +} +#endif + +/****************************************************************************** + * vTracePrint + * + * Basic user event + * + * Generates a User Event with a text label. The label is created/looked up + * in the symbol table using xTraceRegisterString. + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +void vTracePrint(traceString chn, const char* str) +{ +#if (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 0) + UserEvent* ue; + uint8_t dts1; + TRACE_ALLOC_CRITICAL_SECTION(); + + trcCRITICAL_SECTION_BEGIN(); + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + { + dts1 = (uint8_t)prvTraceGetDTS(0xFF); + ue = (UserEvent*) prvTraceNextFreeEventBufferSlot(); + if (ue != NULL) + { + ue->dts = dts1; + ue->type = USER_EVENT; + ue->payload = prvTraceOpenSymbol(str, chn); + prvTraceUpdateCounters(); + } + } + trcCRITICAL_SECTION_END(); + +#elif (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) + traceUBChannel channel; + uint32_t noOfSlots = 1; + uint32_t tempDataBuffer[(3 + MAX_ARG_SIZE) / 4]; + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + { + traceString trcStr = prvTraceOpenSymbol(str, chn); + channel = xTraceRegisterUBChannel(chn, trcStr); + + if (channel == 0) + { + /* We are dealing with an unknown channel format pair */ + noOfSlots++; /* Also need room for channel and format */ + ((uint16_t*)tempDataBuffer)[2] = chn; + ((uint16_t*)tempDataBuffer)[3] = trcStr; + } + + prvTraceUBHelper2(channel, tempDataBuffer, noOfSlots); + } +#endif +} +#endif + +/******************************************************************************* + * xTraceRegisterString + * + * Register strings in the recorder, e.g. for names of user event channels. + * + * Example: + * myEventHandle = xTraceRegisterString("MyUserEvent"); + * ... + * vTracePrintF(myEventHandle, "My value is: %d", myValue); + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +traceString xTraceRegisterString(const char* label) +{ + TRACE_ASSERT(label != NULL, "xTraceRegisterString: label == NULL", (traceString)0); + TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0); + return prvTraceOpenSymbol(label, 0); +} +#endif + + +#if ((!defined TRC_CFG_INCLUDE_READY_EVENTS) || (TRC_CFG_INCLUDE_READY_EVENTS == 1)) + +void prvTraceSetReadyEventsEnabled(int status) +{ + readyEventsEnabled = status; +} + +/******************************************************************************* + * prvTraceStoreTaskReady + * + * This function stores a ready state for the task handle sent in as parameter. + ******************************************************************************/ +void prvTraceStoreTaskReady(traceHandle handle) +{ + uint16_t dts3; + TREvent* tr; + uint8_t hnd8; + + TRACE_ALLOC_CRITICAL_SECTION(); + + if (handle == 0) + { + /* On FreeRTOS v7.3.0, this occurs when creating tasks due to a bad + placement of the trace macro. In that case, the events are ignored. */ + return; + } + + if (! readyEventsEnabled) + { + /* When creating tasks, ready events are also created. If creating + a "hidden" (not traced) task, we must therefore disable recording + of ready events to avoid an undesired ready event... */ + return; + } + + TRACE_ASSERT(handle <= (TRC_CFG_NTASK), "prvTraceStoreTaskReady: Invalid value for handle", TRC_UNUSED); + + if (recorder_busy) + { + /************************************************************************* + * This occurs if an ISR calls a trace function, preempting a previous + * trace call that is being processed in a different ISR or task. + * If this occurs, there is probably a problem in the definition of the + * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and + * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt + * and any other ISRs that calls the trace recorder directly or via + * traced kernel functions. The ARM port disables all interrupts using the + * PRIMASK register to avoid this issue. + *************************************************************************/ + prvTraceError("Recorder busy - high priority ISR using syscall? (1)"); + return; + } + + trcCRITICAL_SECTION_BEGIN(); + if (RecorderDataPtr->recorderActive) /* Need to repeat this check! */ + { + dts3 = (uint16_t)prvTraceGetDTS(0xFFFF); + hnd8 = prvTraceGet8BitHandle(handle); + tr = (TREvent*)prvTraceNextFreeEventBufferSlot(); + if (tr != NULL) + { + tr->type = DIV_TASK_READY; + tr->dts = dts3; + tr->objHandle = hnd8; + prvTraceUpdateCounters(); + } + } + trcCRITICAL_SECTION_END(); +} +#endif + +/******************************************************************************* + * prvTraceStoreLowPower + * + * This function stores a low power state. + ******************************************************************************/ +void prvTraceStoreLowPower(uint32_t flag) +{ + uint16_t dts; + LPEvent* lp; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ASSERT(flag <= 1, "prvTraceStoreLowPower: Invalid flag value", TRC_UNUSED); + + if (recorder_busy) + { + /************************************************************************* + * This occurs if an ISR calls a trace function, preempting a previous + * trace call that is being processed in a different ISR or task. + * If this occurs, there is probably a problem in the definition of the + * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and + * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt + * and any other ISRs that calls the trace recorder directly or via + * traced kernel functions. The ARM port disables all interrupts using the + * PRIMASK register to avoid this issue. + *************************************************************************/ + prvTraceError("Recorder busy - high priority ISR using syscall? (1)"); + return; + } + + trcCRITICAL_SECTION_BEGIN(); + if (RecorderDataPtr->recorderActive) + { + dts = (uint16_t)prvTraceGetDTS(0xFFFF); + lp = (LPEvent*)prvTraceNextFreeEventBufferSlot(); + if (lp != NULL) + { + lp->type = (uint8_t) (LOW_POWER_BEGIN + ( uint8_t ) flag); /* BEGIN or END depending on flag */ + lp->dts = dts; + prvTraceUpdateCounters(); + } + } + trcCRITICAL_SECTION_END(); +} + +/******************************************************************************* + * vTraceStoreMemMangEvent + * + * This function stores malloc and free events. Each call requires two records, + * for size and address respectively. The event code parameter (ecode) is applied + * to the first record (size) and the following address record gets event + * code "ecode + 1", so make sure this is respected in the event code table. + * Note: On "free" calls, the signed_size parameter should be negative. + ******************************************************************************/ +#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) +#if (TRC_CFG_SCHEDULING_ONLY == 0) +void vTraceStoreMemMangEvent(uint32_t ecode, uint32_t address, int32_t signed_size) +{ + uint8_t dts1; + MemEventSize * ms; + MemEventAddr * ma; + uint16_t size_low; + uint16_t addr_low; + uint8_t addr_high; + uint32_t size; + TRACE_ALLOC_CRITICAL_SECTION(); + + if (RecorderDataPtr == NULL) + { + /* Occurs in vTraceInitTraceData, if using dynamic allocation. */ + return; + } + + if (signed_size < 0) + size = (uint32_t)(- signed_size); + else + size = (uint32_t)(signed_size); + + trcCRITICAL_SECTION_BEGIN(); + + /* Only update heapMemUsage if we have a valid address */ + if (address != 0) + heapMemUsage += (uint32_t)signed_size; + + if (RecorderDataPtr->recorderActive) + { + dts1 = (uint8_t)prvTraceGetDTS(0xFF); + size_low = (uint16_t)prvTraceGetParam(0xFFFF, size); + ms = (MemEventSize *)prvTraceNextFreeEventBufferSlot(); + + if (ms != NULL) + { + ms->dts = dts1; + ms->type = NULL_EVENT; /* Updated when all events are written */ + ms->size = size_low; + prvTraceUpdateCounters(); + + /* Storing a second record with address (signals "failed" if null) */ + #if (TRC_CFG_HEAP_SIZE_BELOW_16M) + /* If the heap address range is within 16 MB, i.e., the upper 8 bits + of addresses are constant, this optimization avoids storing an extra + event record by ignoring the upper 8 bit of the address */ + addr_low = address & 0xFFFF; + addr_high = (address >> 16) & 0xFF; + #else + /* The whole 32 bit address is stored using a second event record + for the upper 16 bit */ + addr_low = (uint16_t)prvTraceGetParam(0xFFFF, address); + addr_high = 0; + #endif + + ma = (MemEventAddr *) prvTraceNextFreeEventBufferSlot(); + if (ma != NULL) + { + ma->addr_low = addr_low; + ma->addr_high = addr_high; + ma->type = (uint8_t) (ecode + 1); /* Note this! */ + ms->type = (uint8_t) ecode; + prvTraceUpdateCounters(); + RecorderDataPtr->heapMemUsage = heapMemUsage; + } + } + } + trcCRITICAL_SECTION_END(); +} +#endif /* TRC_CFG_SCHEDULING_ONLY */ +#endif + +/******************************************************************************* + * prvTraceStoreKernelCall + * + * This is the main integration point for storing kernel calls, and + * is called by the hooks in trcKernelHooks.h (see trcKernelPort.h for event codes). + ******************************************************************************/ +#if (TRC_CFG_SCHEDULING_ONLY == 0) +void prvTraceStoreKernelCall(uint32_t ecode, traceObjectClass objectClass, uint32_t objectNumber) +{ + KernelCall * kse; + uint16_t dts1; + uint8_t hnd8; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ASSERT(ecode < 0xFF, "prvTraceStoreKernelCall: ecode >= 0xFF", TRC_UNUSED); + TRACE_ASSERT(objectClass < TRACE_NCLASSES, "prvTraceStoreKernelCall: objectClass >= TRACE_NCLASSES", TRC_UNUSED); + TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "prvTraceStoreKernelCall: Invalid value for objectNumber", TRC_UNUSED); + + if (recorder_busy) + { + /************************************************************************* + * This occurs if an ISR calls a trace function, preempting a previous + * trace call that is being processed in a different ISR or task. + * If this occurs, there is probably a problem in the definition of the + * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and + * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt + * and any other ISRs that calls the trace recorder directly or via + * traced kernel functions. The ARM port disables all interrupts using the + * PRIMASK register to avoid this issue. + *************************************************************************/ + prvTraceError("Recorder busy - high priority ISR using syscall? (2)"); + return; + } + + if (handle_of_last_logged_task == 0) + { + return; + } + + trcCRITICAL_SECTION_BEGIN(); + if (RecorderDataPtr->recorderActive) + { + dts1 = (uint16_t)prvTraceGetDTS(0xFFFF); + hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber); + kse = (KernelCall*) prvTraceNextFreeEventBufferSlot(); + if (kse != NULL) + { + kse->dts = dts1; + kse->type = (uint8_t)ecode; + kse->objHandle = hnd8; + prvTraceUpdateCounters(); + } + } + trcCRITICAL_SECTION_END(); +} +#endif /* TRC_CFG_SCHEDULING_ONLY */ + +/******************************************************************************* + * prvTraceStoreKernelCallWithParam + * + * Used for storing kernel calls with a handle and a numeric parameter. If the + * numeric parameter does not fit in one byte, and extra XPS event is inserted + * before the kernel call event containing the three upper bytes. + ******************************************************************************/ +#if (TRC_CFG_SCHEDULING_ONLY == 0) +void prvTraceStoreKernelCallWithParam(uint32_t evtcode, + traceObjectClass objectClass, + uint32_t objectNumber, + uint32_t param) +{ + KernelCallWithParamAndHandle * kse; + uint8_t dts2; + uint8_t hnd8; + uint8_t p8; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ASSERT(evtcode < 0xFF, "prvTraceStoreKernelCallWithParam: evtcode >= 0xFF", TRC_UNUSED); + TRACE_ASSERT(objectClass < TRACE_NCLASSES, "prvTraceStoreKernelCallWithParam: objectClass >= TRACE_NCLASSES", TRC_UNUSED); + TRACE_ASSERT(objectNumber <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectClass], "prvTraceStoreKernelCallWithParam: Invalid value for objectNumber", TRC_UNUSED); + + if (recorder_busy) + { + /************************************************************************* + * This occurs if an ISR calls a trace function, preempting a previous + * trace call that is being processed in a different ISR or task. + * If this occurs, there is probably a problem in the definition of the + * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and + * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt + * and any other ISRs that calls the trace recorder directly or via + * traced kernel functions. The ARM port disables all interrupts using the + * PRIMASK register to avoid this issue. + *************************************************************************/ + prvTraceError("Recorder busy - high priority ISR using syscall? (3)"); + return; + } + + trcCRITICAL_SECTION_BEGIN(); + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + { + dts2 = (uint8_t)prvTraceGetDTS(0xFF); + p8 = (uint8_t) prvTraceGetParam(0xFF, param); + hnd8 = prvTraceGet8BitHandle((traceHandle)objectNumber); + kse = (KernelCallWithParamAndHandle*) prvTraceNextFreeEventBufferSlot(); + if (kse != NULL) + { + kse->dts = dts2; + kse->type = (uint8_t)evtcode; + kse->objHandle = hnd8; + kse->param = p8; + prvTraceUpdateCounters(); + } + } + trcCRITICAL_SECTION_END(); +} +#endif /* TRC_CFG_SCHEDULING_ONLY */ + + +/******************************************************************************* + * prvTraceGetParam + * + * Used for storing extra bytes for kernel calls with numeric parameters. + * + * May only be called within a critical section! + ******************************************************************************/ +#if (TRC_CFG_SCHEDULING_ONLY == 0) +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*) prvTraceNextFreeEventBufferSlot(); + if (xps != NULL) + { + xps->type = DIV_XPS; + xps->xps_8 = (uint8_t)((param & (0xFF00 & ~param_max)) >> 8); + xps->xps_16 = (uint16_t)((param & (0xFFFF0000 & ~param_max)) >> 16); + prvTraceUpdateCounters(); + } + + return param & param_max; + } +} +#endif + +/******************************************************************************* + * prvTraceStoreKernelCallWithNumericParamOnly + * + * Used for storing kernel calls with numeric parameters only. This is + * only used for traceTASK_DELAY and traceDELAY_UNTIL at the moment. + ******************************************************************************/ +#if (TRC_CFG_SCHEDULING_ONLY == 0) +void prvTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param) +{ + KernelCallWithParam16 * kse; + uint8_t dts6; + uint16_t restParam; + TRACE_ALLOC_CRITICAL_SECTION(); + + restParam = 0; + + TRACE_ASSERT(evtcode < 0xFF, "prvTraceStoreKernelCallWithNumericParamOnly: Invalid value for evtcode", TRC_UNUSED); + + if (recorder_busy) + { + /************************************************************************* + * This occurs if an ISR calls a trace function, preempting a previous + * trace call that is being processed in a different ISR or task. + * If this occurs, there is probably a problem in the definition of the + * recorder's internal critical sections (TRACE_ENTER_CRITICAL_SECTION and + * TRACE_EXIT_CRITICAL_SECTION). They must disable the RTOS tick interrupt + * and any other ISRs that calls the trace recorder directly or via + * traced kernel functions. The ARM port disables all interrupts using the + * PRIMASK register to avoid this issue. + *************************************************************************/ + prvTraceError("Recorder busy - high priority ISR using syscall? (4)"); + return; + } + + trcCRITICAL_SECTION_BEGIN(); + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + { + dts6 = (uint8_t)prvTraceGetDTS(0xFF); + restParam = (uint16_t)prvTraceGetParam(0xFFFF, param); + kse = (KernelCallWithParam16*) prvTraceNextFreeEventBufferSlot(); + if (kse != NULL) + { + kse->dts = dts6; + kse->type = (uint8_t)evtcode; + kse->param = restParam; + prvTraceUpdateCounters(); + } + } + trcCRITICAL_SECTION_END(); +} +#endif /* TRC_CFG_SCHEDULING_ONLY */ + +/******************************************************************************* + * prvTraceStoreTaskswitch + * Called by the scheduler from the SWITCHED_OUT hook, and by uiTraceStart. + * At this point interrupts are assumed to be disabled! + ******************************************************************************/ +void prvTraceStoreTaskswitch(traceHandle task_handle) +{ + uint16_t dts3; + TSEvent* ts; + uint8_t hnd8; +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) + extern int32_t isPendingContextSwitch; +#endif + trcSR_ALLOC_CRITICAL_SECTION_ON_CORTEX_M_ONLY(); + + TRACE_ASSERT(task_handle <= (TRC_CFG_NTASK), + "prvTraceStoreTaskswitch: Invalid value for task_handle", TRC_UNUSED); + + trcCRITICAL_SECTION_BEGIN_ON_CORTEX_M_ONLY(); + + if ((task_handle != handle_of_last_logged_task) && (RecorderDataPtr->recorderActive)) + { +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) + isPendingContextSwitch = 0; +#endif + + dts3 = (uint16_t)prvTraceGetDTS(0xFFFF); + handle_of_last_logged_task = task_handle; + hnd8 = prvTraceGet8BitHandle(handle_of_last_logged_task); + ts = (TSEvent*)prvTraceNextFreeEventBufferSlot(); + + if (ts != NULL) + { + if (prvTraceGetObjectState(TRACE_CLASS_TASK, + handle_of_last_logged_task) == TASK_STATE_INSTANCE_ACTIVE) + { + ts->type = TS_TASK_RESUME; + } + else + { + ts->type = TS_TASK_BEGIN; + } + + ts->dts = dts3; + ts->objHandle = hnd8; + + prvTraceSetObjectState(TRACE_CLASS_TASK, + handle_of_last_logged_task, + TASK_STATE_INSTANCE_ACTIVE); + + prvTraceUpdateCounters(); + } + } + + trcCRITICAL_SECTION_END_ON_CORTEX_M_ONLY(); +} + +/******************************************************************************* + * prvTraceStoreObjectNameOnCloseEvent + * + * Updates the symbol table with the name of this object from the dynamic + * objects table and stores a "close" event, holding the mapping between handle + * and name (a symbol table handle). The stored name-handle mapping is thus the + * "old" one, valid up until this point. + ******************************************************************************/ +void prvTraceStoreObjectNameOnCloseEvent(uint8_t evtcode, traceHandle handle, + traceObjectClass objectclass) +{ + ObjCloseNameEvent * ce; + const char * name; + traceString idx; + + TRACE_ASSERT(objectclass < TRACE_NCLASSES, + "prvTraceStoreObjectNameOnCloseEvent: objectclass >= TRACE_NCLASSES", TRC_UNUSED); + TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], + "prvTraceStoreObjectNameOnCloseEvent: Invalid value for handle", TRC_UNUSED); + + if (RecorderDataPtr->recorderActive) + { + uint8_t hnd8 = prvTraceGet8BitHandle(handle); + name = TRACE_PROPERTY_NAME_GET(objectclass, handle); + idx = prvTraceOpenSymbol(name, 0); + + // Interrupt disable not necessary, already done in trcHooks.h macro + ce = (ObjCloseNameEvent*) prvTraceNextFreeEventBufferSlot(); + if (ce != NULL) + { + ce->type = (uint8_t) evtcode; + ce->objHandle = hnd8; + ce->symbolIndex = idx; + prvTraceUpdateCounters(); + } + } +} + +void prvTraceStoreObjectPropertiesOnCloseEvent(uint8_t evtcode, traceHandle handle, + traceObjectClass objectclass) +{ + ObjClosePropEvent * pe; + + TRACE_ASSERT(objectclass < TRACE_NCLASSES, + "prvTraceStoreObjectPropertiesOnCloseEvent: objectclass >= TRACE_NCLASSES", TRC_UNUSED); + TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], + "prvTraceStoreObjectPropertiesOnCloseEvent: Invalid value for handle", TRC_UNUSED); + + if (RecorderDataPtr->recorderActive) + { + // Interrupt disable not necessary, already done in trcHooks.h macro + pe = (ObjClosePropEvent*) prvTraceNextFreeEventBufferSlot(); + if (pe != NULL) + { + if (objectclass == TRACE_CLASS_TASK) + { + pe->arg1 = TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, handle); + } + else + { + pe->arg1 = TRACE_PROPERTY_OBJECT_STATE(objectclass, handle); + } + pe->type = evtcode; + prvTraceUpdateCounters(); + } + } +} + +void prvTraceSetPriorityProperty(uint8_t objectclass, traceHandle id, uint8_t value) +{ + TRACE_ASSERT(objectclass < TRACE_NCLASSES, + "prvTraceSetPriorityProperty: objectclass >= TRACE_NCLASSES", TRC_UNUSED); + TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], + "prvTraceSetPriorityProperty: Invalid value for id", TRC_UNUSED); + + TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id) = value; +} + +uint8_t prvTraceGetPriorityProperty(uint8_t objectclass, traceHandle id) +{ + TRACE_ASSERT(objectclass < TRACE_NCLASSES, + "prvTraceGetPriorityProperty: objectclass >= TRACE_NCLASSES", 0); + TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], + "prvTraceGetPriorityProperty: Invalid value for id", 0); + + return TRACE_PROPERTY_ACTOR_PRIORITY(objectclass, id); +} + +void prvTraceSetObjectState(uint8_t objectclass, traceHandle id, uint8_t value) +{ + TRACE_ASSERT(objectclass < TRACE_NCLASSES, + "prvTraceSetObjectState: objectclass >= TRACE_NCLASSES", TRC_UNUSED); + TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], + "prvTraceSetObjectState: Invalid value for id", TRC_UNUSED); + + TRACE_PROPERTY_OBJECT_STATE(objectclass, id) = value; +} + +uint8_t prvTraceGetObjectState(uint8_t objectclass, traceHandle id) +{ + TRACE_ASSERT(objectclass < TRACE_NCLASSES, + "prvTraceGetObjectState: objectclass >= TRACE_NCLASSES", 0); + TRACE_ASSERT(id <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], + "prvTraceGetObjectState: Invalid value for id", 0); + + return TRACE_PROPERTY_OBJECT_STATE(objectclass, id); +} + +void prvTraceSetTaskInstanceFinished(traceHandle handle) +{ + TRACE_ASSERT(handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[TRACE_CLASS_TASK], + "prvTraceSetTaskInstanceFinished: Invalid value for handle", TRC_UNUSED); + +#if (TRC_CFG_USE_IMPLICIT_IFE_RULES == 1) + TRACE_PROPERTY_OBJECT_STATE(TRACE_CLASS_TASK, handle) = 0; +#endif +} + +/******************************************************************************* + * Static data initializations + ******************************************************************************/ + +/* A set of stacks that keeps track of available object handles for each class. +The stacks are empty initially, meaning that allocation of new handles will be +based on a counter (for each object class). Any delete operation will +return the handle to the corresponding stack, for reuse on the next allocate.*/ +objectHandleStackType objectHandleStacks = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }; + +/* Initial TRC_HWTC_COUNT value, for detecting if the time-stamping source is +enabled. If using the OS periodic timer for time-stamping, this might not +have been configured on the earliest events during the startup. */ +uint32_t init_hwtc_count; + +/******************************************************************************* + * RecorderData + * + * The main data structure in snapshot mode, when using the default static memory + * allocation (TRC_RECORDER_BUFFER_ALLOCATION_STATIC). The recorder uses a pointer + * RecorderDataPtr to access the data, to also allow for dynamic or custom data + * allocation (see TRC_CFG_RECORDER_BUFFER_ALLOCATION). + ******************************************************************************/ +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC) +RecorderDataType RecorderData; +#endif + +/******************************************************************************* + * RecorderDataPtr + * + * Pointer to the main data structure, when in snapshot mode. + ******************************************************************************/ +RecorderDataType* RecorderDataPtr = NULL; + +/* This version of the function dynamically allocates the trace data */ +void prvTraceInitTraceData() +{ + + if (RecorderDataPtr == NULL) + { +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC) + RecorderDataPtr = &RecorderData; +#elif (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC) + RecorderDataPtr = (RecorderDataType*)TRACE_MALLOC(sizeof(RecorderDataType)); + if (! RecorderDataPtr) + { + prvTraceError("Failed allocating recorder buffer!"); + return; + } +#elif (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) + if (! RecorderDataPtr) + { + prvTraceError("Recorder data pointer not set! Use vTraceSetRecorderDataBuffer()."); + return; + } +#endif + } + else + { + if (RecorderDataPtr->startmarker0 == 1) + { + /* Already initialized */ + return; + } + } + + init_hwtc_count = TRC_HWTC_COUNT; + + (void)memset(RecorderDataPtr, 0, sizeof(RecorderDataType)); + + RecorderDataPtr->version = TRACE_KERNEL_VERSION; + RecorderDataPtr->minor_version = TRACE_MINOR_VERSION; + RecorderDataPtr->irq_priority_order = TRC_IRQ_PRIORITY_ORDER; + RecorderDataPtr->filesize = sizeof(RecorderDataType); + RecorderDataPtr->maxEvents = (TRC_CFG_EVENT_BUFFER_SIZE); + RecorderDataPtr->debugMarker0 = (int32_t) 0xF0F0F0F0; + RecorderDataPtr->isUsing16bitHandles = TRC_CFG_USE_16BIT_OBJECT_HANDLES; + RecorderDataPtr->isrTailchainingThreshold = TRC_CFG_ISR_TAILCHAINING_THRESHOLD; + + /* This function is kernel specific */ + vTraceInitObjectPropertyTable(); + + RecorderDataPtr->debugMarker1 = (int32_t)0xF1F1F1F1; + RecorderDataPtr->SymbolTable.symTableSize = (TRC_CFG_SYMBOL_TABLE_SIZE); + RecorderDataPtr->SymbolTable.nextFreeSymbolIndex = 1; +#if (TRC_CFG_INCLUDE_FLOAT_SUPPORT == 1) + RecorderDataPtr->exampleFloatEncoding = 1.0f; /* otherwise already zero */ +#endif + RecorderDataPtr->debugMarker2 = (int32_t)0xF2F2F2F2; + prvStrncpy(RecorderDataPtr->systemInfo, "Trace Recorder Demo", 80); + RecorderDataPtr->debugMarker3 = (int32_t)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 TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER + RecorderDataPtr->userEventBuffer.bufferID = 1; + RecorderDataPtr->userEventBuffer.version = 0; + RecorderDataPtr->userEventBuffer.numberOfSlots = (TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE); + RecorderDataPtr->userEventBuffer.numberOfChannels = (TRC_CFG_UB_CHANNELS) + 1; +#endif + + /* Kernel specific initialization of the objectHandleStacks variable */ + vTraceInitObjectHandleStack(); + + + /* Finally, the 12-byte "start markers" are initialized, allowing for + Tracealyzer to find the trace data in a larger RAM dump. + + The start and end markers must be unique, but without proper precautions there + might be a risk of accidental duplicates of the start/end markers, e.g., due to + compiler optimizations. + + The below initialization of the start marker is therefore made in reverse order + and the fields are volatile to ensure this assignment order. This to avoid any + chance of accidental duplicates of this elsewhere in memory. + + Moreover, the fields are set byte-by-byte to avoid endian issues.*/ + + RecorderDataPtr->startmarker11 = 0xF4; + RecorderDataPtr->startmarker10 = 0xF3; + RecorderDataPtr->startmarker9 = 0xF2; + RecorderDataPtr->startmarker8 = 0xF1; + RecorderDataPtr->startmarker7 = 0x74; + RecorderDataPtr->startmarker6 = 0x73; + RecorderDataPtr->startmarker5 = 0x72; + RecorderDataPtr->startmarker4 = 0x71; + RecorderDataPtr->startmarker3 = 0x04; + RecorderDataPtr->startmarker2 = 0x03; + RecorderDataPtr->startmarker1 = 0x02; + RecorderDataPtr->startmarker0 = 0x01; + + if (traceErrorMessage != NULL) + { + // An error was detected before vTraceEnable was called, make sure this is stored in the trace data. + prvStrncpy(RecorderDataPtr->systemInfo, traceErrorMessage, 80); + RecorderDataPtr->internalErrorOccured = 1; + vTraceStop(); + } + + + +#ifdef TRC_PORT_SPECIFIC_INIT + TRC_PORT_SPECIFIC_INIT(); +#endif +} + + +void* prvTraceNextFreeEventBufferSlot(void) +{ + if (! RecorderDataPtr->recorderActive) + { + /* If an XTS or XPS event prior to the main event has filled the buffer + before saving the main event, and store mode is "stop when full". */ + return NULL; + } + + if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE)) + { + prvTraceError("Attempt to index outside event buffer!"); + return NULL; + } + return (void*)(&RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex*4]); +} + +uint16_t uiIndexOfObject(traceHandle objecthandle, uint8_t objectclass) +{ + 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])) + { + return (uint16_t)(RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[objectclass] + + (RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[objectclass] * (objecthandle-1))); + } + + prvTraceError("Object table lookup with invalid object handle or object class!"); + return 0; +} + +traceHandle prvTraceGetObjectHandle(traceObjectClass objectclass) +{ + traceHandle handle; + static int indexOfHandle; + + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ASSERT(RecorderDataPtr != NULL, "Recorder not initialized, call vTraceEnable() first!", (traceHandle)0); + + TRACE_ASSERT(objectclass < TRACE_NCLASSES, + "prvTraceGetObjectHandle: Invalid value for objectclass", (traceHandle)0); + + trcCRITICAL_SECTION_BEGIN(); + indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass]; + if (objectHandleStacks.objectHandles[indexOfHandle] == 0) + { + /* Zero is used to indicate a never before used handle, i.e., + new slots in the handle stack. The handle slot needs to + be initialized here (starts at 1). */ + objectHandleStacks.objectHandles[indexOfHandle] = + (traceHandle)(1 + indexOfHandle - + objectHandleStacks.lowestIndexOfClass[objectclass]); + } + + handle = objectHandleStacks.objectHandles[indexOfHandle]; + + if (objectHandleStacks.indexOfNextAvailableHandle[objectclass] + > objectHandleStacks.highestIndexOfClass[objectclass]) + { + prvTraceError(pszTraceGetErrorNotEnoughHandles(objectclass)); + handle = 0; + } + else + { + int hndCount; + objectHandleStacks.indexOfNextAvailableHandle[objectclass]++; + + hndCount = objectHandleStacks.indexOfNextAvailableHandle[objectclass] - + objectHandleStacks.lowestIndexOfClass[objectclass]; + + if (hndCount > + objectHandleStacks.handleCountWaterMarksOfClass[objectclass]) + { + objectHandleStacks.handleCountWaterMarksOfClass[objectclass] = + (traceHandle)hndCount; + } + } + trcCRITICAL_SECTION_END(); + + return handle; +} + +void prvTraceFreeObjectHandle(traceObjectClass objectclass, traceHandle handle) +{ + int indexOfHandle; + + TRACE_ASSERT(objectclass < TRACE_NCLASSES, + "prvTraceFreeObjectHandle: Invalid value for objectclass", TRC_UNUSED); + TRACE_ASSERT(handle > 0 && handle <= RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass], + "prvTraceFreeObjectHandle: Invalid value for handle", TRC_UNUSED); + + /* Check that there is room to push the handle on the stack */ + if ((objectHandleStacks.indexOfNextAvailableHandle[objectclass] - 1) < + objectHandleStacks.lowestIndexOfClass[objectclass]) + { + /* Error */ + prvTraceError("Attempt to free more handles than allocated!"); + } + else + { + objectHandleStacks.indexOfNextAvailableHandle[objectclass]--; + indexOfHandle = objectHandleStacks.indexOfNextAvailableHandle[objectclass]; + objectHandleStacks.objectHandles[indexOfHandle] = handle; + } +} + +/******************************************************************************* + * prvMarkObjectAsUsed + * + * Sets an "is used flag" on object creation, using the first byte of the name + * field. This allows for counting the number of used Object Table slots, even + * if no names have been set. + ******************************************************************************/ +void prvMarkObjectAsUsed(traceObjectClass objectclass, traceHandle handle) +{ + uint16_t idx = uiIndexOfObject(handle, objectclass); + RecorderDataPtr->ObjectPropertyTable.objbytes[idx] = 1; +} + +/******************************************************************************* + * prvStrncpy + * + * Private string copy function, to improve portability between compilers. + ******************************************************************************/ +static void prvStrncpy(char* dst, const char* src, uint32_t maxLength) +{ + uint32_t i; + for (i = 0; i < maxLength; i++) + { + dst[i] = src[i]; + if (src[i] == 0) + break; + } +} + +/******************************************************************************* + * prvTraceSetObjectName + * + * Registers the names of queues, semaphores and other kernel objects in the + * recorder's Object Property Table, at the given handle and object class. + ******************************************************************************/ +void prvTraceSetObjectName(traceObjectClass objectclass, + traceHandle handle, + const char* name) +{ + static uint16_t idx; + + TRACE_ASSERT(name != NULL, "prvTraceSetObjectName: name == NULL", TRC_UNUSED); + + if (objectclass >= TRACE_NCLASSES) + { + prvTraceError("Illegal object class in prvTraceSetObjectName"); + return; + } + + if (handle == 0) + { + prvTraceError("Illegal handle (0) in prvTraceSetObjectName."); + return; + } + + if (handle > RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[objectclass]) + { + /* ERROR */ + prvTraceError(pszTraceGetErrorNotEnoughHandles(objectclass)); + } + else + { + idx = uiIndexOfObject(handle, objectclass); + + if (traceErrorMessage == NULL) + { + prvStrncpy((char*)&(RecorderDataPtr->ObjectPropertyTable.objbytes[idx]), + name, + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ objectclass ]); + } + } +} + +traceString prvTraceOpenSymbol(const char* name, traceString userEventChannel) +{ + uint16_t result; + uint8_t len; + uint8_t crc; + TRACE_ALLOC_CRITICAL_SECTION(); + + len = 0; + crc = 0; + + TRACE_ASSERT(name != NULL, "prvTraceOpenSymbol: name == NULL", (traceString)0); + + prvTraceGetChecksum(name, &crc, &len); + + trcCRITICAL_SECTION_BEGIN(); + result = prvTraceLookupSymbolTableEntry(name, crc, len, userEventChannel); + if (!result) + { + result = prvTraceCreateSymbolTableEntry(name, crc, len, userEventChannel); + } + trcCRITICAL_SECTION_END(); + + return result; +} + + +/****************************************************************************** +* vTraceSetFrequency +* +* Registers the clock rate of the time source for the event timestamping. +* This is normally not required, but if the default value (TRC_HWTC_FREQ_HZ) +* should be incorrect for your setup, you can override it using this function. +* +* Must be called prior to vTraceEnable, and the time source is assumed to +* have a fixed clock frequency after the startup. +* +* Note that, in snapshot mode, the value is divided by the TRC_HWTC_DIVISOR. +* This is a software "prescaler" that is also applied on the timestamps. +*****************************************************************************/ +void vTraceSetFrequency(uint32_t frequency) +{ + timestampFrequency = frequency; +} + +/******************************************************************************* + * Supporting functions + ******************************************************************************/ + +/******************************************************************************* + * prvTraceError + * + * Called by various parts in the recorder. Stops the recorder and stores a + * pointer to an error message, which is printed by the monitor task. + * If you are not using the monitor task, you may use xTraceGetLastError() + * from your application to check if the recorder is OK. + * + * Note: If a recorder error is registered before vTraceStart is called, the + * trace start will be aborted. This can occur if any of the Nxxxx constants + * (e.g., TRC_CFG_NTASK) in trcConfig.h is too small. + ******************************************************************************/ +void prvTraceError(const char* msg) +{ + /* Stop the recorder */ + if (RecorderDataPtr != NULL) + { + vTraceStop(); + } + + /* If first error only... */ + if (traceErrorMessage == NULL) + { + traceErrorMessage = (char*)(intptr_t) msg; + if (RecorderDataPtr != NULL) + { + prvStrncpy(RecorderDataPtr->systemInfo, traceErrorMessage, 80); + RecorderDataPtr->internalErrorOccured = 1; + } + } +} + +void vTraceSetFilterMask(uint16_t filterMask) +{ + CurrentFilterMask = filterMask; +} + +void vTraceSetFilterGroup(uint16_t filterGroup) +{ + CurrentFilterGroup = filterGroup; +} + +/****************************************************************************** + * prvCheckDataToBeOverwrittenForMultiEntryEvents + * + * This checks if the next event to be overwritten is a multi-entry user event, + * i.e., a USER_EVENT followed by data entries. + * Such data entries do not have an event code at byte 0, as other events. + * All 4 bytes are user data, so the first byte of such data events must + * not be interpreted as type field. The number of data entries following + * a USER_EVENT is given in the event code of the USER_EVENT. + * Therefore, when overwriting a USER_EVENT (when using in ring-buffer mode) + * any data entries following must be replaced with NULL events (code 0). + * + * This is assumed to execute within a critical section... + *****************************************************************************/ + +#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER) +void prvCheckDataToBeOverwrittenForMultiEntryEvents(uint8_t nofEntriesToCheck) +{ + /* Generic "int" type is desired - should be 16 bit variable on 16 bit HW */ + unsigned int i = 0; + unsigned int e = 0; + + TRACE_ASSERT(nofEntriesToCheck != 0, + "prvCheckDataToBeOverwrittenForMultiEntryEvents: nofEntriesToCheck == 0", TRC_UNUSED); + + while (i < nofEntriesToCheck) + { + e = RecorderDataPtr->nextFreeIndex + i; + if ((RecorderDataPtr->eventData[e*4] > USER_EVENT) && + (RecorderDataPtr->eventData[e*4] < USER_EVENT + 16)) + { + uint8_t nDataEvents = (uint8_t)(RecorderDataPtr->eventData[e*4] - USER_EVENT); + if ((e + nDataEvents) < RecorderDataPtr->maxEvents) + { + (void)memset(& RecorderDataPtr->eventData[e*4], 0, (size_t) (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++; + } +} +#endif + +/******************************************************************************* + * prvTraceUpdateCounters + * + * Updates the index of the event buffer. + ******************************************************************************/ +void prvTraceUpdateCounters(void) +{ + if (RecorderDataPtr->recorderActive == 0) + { + return; + } + + RecorderDataPtr->numEvents++; + + RecorderDataPtr->nextFreeIndex++; + + if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE)) + { +#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER) + RecorderDataPtr->bufferIsFull = 1; + RecorderDataPtr->nextFreeIndex = 0; +#else + vTraceStop(); +#endif + } + +#if (TRC_CFG_SNAPSHOT_MODE == TRC_SNAPSHOT_MODE_RING_BUFFER) + prvCheckDataToBeOverwrittenForMultiEntryEvents(1); +#endif +} + +/****************************************************************************** + * prvTraceGetDTS + * + * Returns a differential timestamp (DTS), i.e., the time since + * last event, and creates an XTS event if the DTS does not fit in the + * number of bits given. The XTS event holds the MSB bytes of the DTS. + * + * The parameter param_maxDTS should be 0xFF for 8-bit dts or 0xFFFF for + * events with 16-bit dts fields. + *****************************************************************************/ +uint16_t prvTraceGetDTS(uint16_t param_maxDTS) +{ + static uint32_t old_timestamp = 0; + XTSEvent* xts = 0; + uint32_t dts = 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 (timestampFrequency != 0) + { + /* If to override default TRC_HWTC_FREQ_HZ value with value set by vTraceSetFrequency */ + RecorderDataPtr->frequency = timestampFrequency / (TRC_HWTC_DIVISOR); + } + else if (init_hwtc_count != (TRC_HWTC_COUNT)) + { + /* If using default value and timer has been started. + Note: If the default frequency value set here would be incorrect, e.g., + if the timer has actually not been configured yet, override this + with vTraceSetFrequency. + */ + RecorderDataPtr->frequency = (TRC_HWTC_FREQ_HZ) / (TRC_HWTC_DIVISOR); + } + /* If no override (vTraceSetFrequency) and timer inactive -> no action */ + } + + /************************************************************************** + * The below statements read the timestamp from the timer port module. + * If necessary, whole seconds are extracted using division while the rest + * comes from the modulo operation. + **************************************************************************/ + + prvTracePortGetTimeStamp(×tamp); + + /*************************************************************************** + * Since dts is unsigned the result will be correct even if timestamp has + * wrapped around. + ***************************************************************************/ + dts = timestamp - old_timestamp; + old_timestamp = timestamp; + + if (RecorderDataPtr->frequency > 0) + { + /* Check if dts > 1 second */ + if (dts > RecorderDataPtr->frequency) + { + /* More than 1 second has passed */ + RecorderDataPtr->absTimeLastEventSecond += dts / RecorderDataPtr->frequency; + /* The part that is not an entire second is added to absTimeLastEvent */ + RecorderDataPtr->absTimeLastEvent += dts % RecorderDataPtr->frequency; + } + else + { + RecorderDataPtr->absTimeLastEvent += dts; + } + + /* Check if absTimeLastEvent >= 1 second */ + if (RecorderDataPtr->absTimeLastEvent >= RecorderDataPtr->frequency) + { + /* RecorderDataPtr->absTimeLastEvent is more than or equal to 1 second, but always less than 2 seconds */ + RecorderDataPtr->absTimeLastEventSecond++; + RecorderDataPtr->absTimeLastEvent -= RecorderDataPtr->frequency; + /* RecorderDataPtr->absTimeLastEvent is now less than 1 second */ + } + } + else + { + /* Special case if the recorder has not yet started (frequency may be uninitialized, i.e., zero) */ + RecorderDataPtr->absTimeLastEvent = timestamp; + } + + /* If the dts (time since last event) does not fit in event->dts (only 8 or 16 bits) */ + if (dts > param_maxDTS) + { + /* Create an XTS event (eXtended TimeStamp) containing the higher dts bits*/ + xts = (XTSEvent*) prvTraceNextFreeEventBufferSlot(); + + if (xts != NULL) + { + if (param_maxDTS == 0xFFFF) + { + xts->type = XTS16; + xts->xts_16 = (uint16_t)((dts / 0x10000) & 0xFFFF); + xts->xts_8 = 0; + } + else if (param_maxDTS == 0xFF) + { + xts->type = XTS8; + xts->xts_16 = (uint16_t)((dts / 0x100) & 0xFFFF); + xts->xts_8 = (uint8_t)((dts / 0x1000000) & 0xFF); + } + else + { + prvTraceError("Bad param_maxDTS in prvTraceGetDTS"); + } + prvTraceUpdateCounters(); + } + } + + return (uint16_t)dts & param_maxDTS; +} + +/******************************************************************************* + * prvTraceLookupSymbolTableEntry + * + * Find an entry in the symbol table, return 0 if not present. + * + * The strings are stored in a byte pool, with four bytes of "meta-data" for + * every string. + * byte 0-1: index of next entry with same checksum (for fast lookup). + * byte 2-3: reference to a symbol table entry, a label for vTracePrintF + * format strings only (the handle of the destination channel). + * byte 4..(4 + length): the string (object name or user event label), with + * zero-termination + ******************************************************************************/ +traceString prvTraceLookupSymbolTableEntry(const char* name, + uint8_t crc6, + uint8_t len, + traceString chn) +{ + uint16_t i = RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ]; + + TRACE_ASSERT(name != NULL, "prvTraceLookupSymbolTableEntry: name == NULL", (traceString)0); + TRACE_ASSERT(len != 0, "prvTraceLookupSymbolTableEntry: len == 0", (traceString)0); + + while (i != 0) + { + if (RecorderDataPtr->SymbolTable.symbytes[i + 2] == (chn & 0x00FF)) + { + if (RecorderDataPtr->SymbolTable.symbytes[i + 3] == (chn / 0x100)) + { + if (RecorderDataPtr->SymbolTable.symbytes[i + 4 + len] == '\0') + { + if (strncmp((char*)(& RecorderDataPtr->SymbolTable.symbytes[i + 4]), name, len) == 0) + { + break; /* found */ + } + } + } + } + i = (uint16_t)(RecorderDataPtr->SymbolTable.symbytes[i] + (RecorderDataPtr->SymbolTable.symbytes[i + 1] * 0x100)); + } + return i; +} + +/******************************************************************************* + * prvTraceCreateSymbolTableEntry + * + * Creates an entry in the symbol table, independent if it exists already. + * + * The strings are stored in a byte pool, with four bytes of "meta-data" for + * every string. + * byte 0-1: index of next entry with same checksum (for fast lookup). + * byte 2-3: reference to a symbol table entry, a label for vTracePrintF + * format strings only (the handle of the destination channel). + * byte 4..(4 + length): the string (object name or user event label), with + * zero-termination + ******************************************************************************/ +uint16_t prvTraceCreateSymbolTableEntry(const char* name, + uint8_t crc6, + uint8_t len, + traceString channel) +{ + 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 >= (TRC_CFG_SYMBOL_TABLE_SIZE)) + { + prvTraceError("Symbol table full. Increase TRC_CFG_SYMBOL_TABLE_SIZE in trcConfig.h"); + ret = 0; + } + else + { + + RecorderDataPtr->SymbolTable.symbytes + [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex] = + (uint8_t)(RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ] & 0x00FF); + + RecorderDataPtr->SymbolTable.symbytes + [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 1] = + (uint8_t)(RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ] / 0x100); + + RecorderDataPtr->SymbolTable.symbytes + [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 2] = + (uint8_t)(channel & 0x00FF); + + RecorderDataPtr->SymbolTable.symbytes + [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 3] = + (uint8_t)(channel / 0x100); + + /* set name (bytes 4...4+len-1) */ + prvStrncpy((char*)&(RecorderDataPtr->SymbolTable.symbytes + [ RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 4]), name, len); + + /* Set zero termination (at offset 4+len) */ + RecorderDataPtr->SymbolTable.symbytes + [RecorderDataPtr->SymbolTable.nextFreeSymbolIndex + 4 + len] = '\0'; + + /* store index of entry (for return value, and as head of LL[crc6]) */ + RecorderDataPtr->SymbolTable.latestEntryOfChecksum + [ crc6 ] = (uint16_t)RecorderDataPtr->SymbolTable.nextFreeSymbolIndex; + + RecorderDataPtr->SymbolTable.nextFreeSymbolIndex += (uint32_t) (len + 5); + + ret = (uint16_t)(RecorderDataPtr->SymbolTable.nextFreeSymbolIndex - (uint8_t)(len + 5)); + } + + return ret; +} + + +/******************************************************************************* + * prvTraceGetChecksum + * + * Calculates a simple 6-bit checksum from a string, used to index the string + * for fast symbol table lookup. + ******************************************************************************/ +void prvTraceGetChecksum(const char *pname, uint8_t* pcrc, uint8_t* plength) +{ + unsigned char c; + int length = 1; /* Should be 1 to account for '\0' */ + int crc = 0; + + TRACE_ASSERT(pname != NULL, "prvTraceGetChecksum: pname == NULL", TRC_UNUSED); + TRACE_ASSERT(pcrc != NULL, "prvTraceGetChecksum: pcrc == NULL", TRC_UNUSED); + TRACE_ASSERT(plength != NULL, "prvTraceGetChecksum: plength == NULL", TRC_UNUSED); + + if (pname != (const char *) 0) + { + for (; (c = (unsigned char) *pname++) != '\0';) + { + crc += c; + length++; + } + } + *pcrc = (uint8_t)(crc & 0x3F); + *plength = (uint8_t)length; +} + +#if (TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1) + +static void prvTraceStoreXID(traceHandle handle); + +/****************************************************************************** + * prvTraceStoreXID + * + * Stores an XID (eXtended IDentifier) event. + * This is used if an object/task handle is larger than 255. + * The parameter "handle" is the full (16 bit) handle, assumed to be 256 or + * larger. Handles below 256 should not use this function. + * + * NOTE: this function MUST be called from within a critical section. + *****************************************************************************/ +static void prvTraceStoreXID(traceHandle handle) +{ + XPSEvent* xid; + + TRACE_ASSERT(handle >= 256, "prvTraceStoreXID: Handle < 256", TRC_UNUSED); + + xid = (XPSEvent*)prvTraceNextFreeEventBufferSlot(); + + if (xid != NULL) + { + xid->type = XID; + + /* This function is (only) used when traceHandle is 16 bit... */ + xid->xps_16 = handle; + + prvTraceUpdateCounters(); + } +} + +static uint8_t prvTraceGet8BitHandle(traceHandle handle) +{ + if (handle > 255) + { + prvTraceStoreXID(handle); + /* The full handle (16 bit) is stored in the XID event. + This code (255) is used instead of zero (which is an error code).*/ + return 255; + } + return (uint8_t)(handle & 0xFF); +} +#endif /*(TRC_CFG_USE_16BIT_OBJECT_HANDLES == 1)*/ + + +/* If using DWT timestamping (default on ARM Cortex-M3, M4 and M7), make sure the DWT unit is initialized. */ +#ifndef TRC_CFG_ARM_CM_USE_SYSTICK +#if ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) && (defined (__CORTEX_M) && (__CORTEX_M >= 0x03))) +void prvTraceInitCortexM() +{ + /* Ensure that the DWT registers are unlocked and can be modified. */ + TRC_REG_ITM_LOCKACCESS = TRC_ITM_LOCKACCESS_UNLOCK; + + /* Make sure DWT is enabled, if supported */ + TRC_REG_DEMCR |= TRC_DEMCR_TRCENA; + + do{ + /* Verify that DWT is supported */ + if (TRC_REG_DEMCR == 0) + { + /* This function is called on Cortex-M3, M4 and M7 devices to initialize + the DWT unit, assumed present. The DWT cycle counter is used for timestamping. + + If the below error is produced, the DWT unit does not seem to be available. + + In that case, define the macro TRC_CFG_ARM_CM_USE_SYSTICK in your build + to use SysTick timestamping instead, or define your own timestamping by + setting TRC_CFG_HARDWARE_PORT to TRC_HARDWARE_PORT_APPLICATION_DEFINED + and make the necessary definitions, as explained in trcHardwarePort.h.*/ + + prvTraceError("DWT unit not available, see code comment."); + break; + } + + /* Verify that DWT_CYCCNT is supported */ + if (TRC_REG_DWT_CTRL & TRC_DWT_CTRL_NOCYCCNT) + { + /* This function is called on Cortex-M3, M4 and M7 devices to initialize + the DWT unit, assumed present. The DWT cycle counter is used for timestamping. + + If the below error is produced, the cycle counter does not seem to be available. + + In that case, define the macro TRC_CFG_ARM_CM_USE_SYSTICK in your build + to use SysTick timestamping instead, or define your own timestamping by + setting TRC_CFG_HARDWARE_PORT to TRC_HARDWARE_PORT_APPLICATION_DEFINED + and make the necessary definitions, as explained in trcHardwarePort.h.*/ + + prvTraceError("DWT_CYCCNT not available, see code comment."); + break; + } + + /* Reset the cycle counter */ + TRC_REG_DWT_CYCCNT = 0; + + /* Enable the cycle counter */ + TRC_REG_DWT_CTRL |= TRC_DWT_CTRL_CYCCNTENA; + + }while(0); /* breaks above jump here */ +} +#endif +#endif + +/****************************************************************************** + * prvTracePortGetTimeStamp + * + * Returns the current time based on the HWTC macros which provide a hardware + * isolation layer towards the hardware timer/counter. + * + * The HWTC macros and prvTracePortGetTimeStamp is the main porting issue + * or the trace recorder library. Typically you should not need to change + * the code of prvTracePortGetTimeStamp if using the HWTC macros. + * + ******************************************************************************/ +void prvTracePortGetTimeStamp(uint32_t *pTimestamp) +{ + static uint32_t last_hwtc_count = 0; + uint32_t hwtc_count = 0; + +#if TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR + /* systick based timer */ + static uint32_t last_traceTickCount = 0; + uint32_t traceTickCount = 0; +#else /*TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR*/ + /* Free running timer */ + static uint32_t last_hwtc_rest = 0; + uint32_t diff = 0; + uint32_t diff_scaled = 0; +#endif /*TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR*/ + + if (trace_disable_timestamp == 1) + { + if (pTimestamp) + *pTimestamp = last_timestamp; + return; + } + + /* Retrieve TRC_HWTC_COUNT only once since the same value should be used all throughout this function. */ +#if (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_INCR) + /* Get the increasing tick count */ + hwtc_count = (TRC_HWTC_COUNT); +#elif (TRC_HWTC_TYPE == TRC_OS_TIMER_DECR || TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_DECR) + /* Convert decreasing tick count into increasing tick count */ + hwtc_count = (TRC_HWTC_PERIOD) - (TRC_HWTC_COUNT); +#else + #error "TRC_HWTC_TYPE has unexpected value" +#endif + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win32) + /* The Win32 port uses ulGetRunTimeCounterValue for timestamping, which in turn + uses QueryPerformanceCounter. That function is not always reliable when used over + multiple threads. We must therefore handle rare cases where the timestamp is less + than the previous. In practice, this should "never" roll over since the + performance counter is 64 bit wide. */ + + if (last_hwtc_count > hwtc_count) + { + hwtc_count = last_hwtc_count; + } +#endif + +#if (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR) + /* Timestamping is based on a timer that wraps at TRC_HWTC_PERIOD */ + 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. */ + last_timestamp = traceTickCount * ((TRC_HWTC_PERIOD) / (TRC_HWTC_DIVISOR)); + /* Increase timestamp by (hwtc_count + "lost hardware ticks from scaling down period") / TRC_HWTC_DIVISOR. */ + last_timestamp += (hwtc_count + traceTickCount * ((TRC_HWTC_PERIOD) % (TRC_HWTC_DIVISOR))) / (TRC_HWTC_DIVISOR); + } + /* Store the previous value */ + last_traceTickCount = traceTickCount; + +#else /*(TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)*/ + + /* Timestamping is based on a free running timer */ + /* This part handles free running clocks that can be scaled down to avoid too large DTS values. + Without this, the scaled timestamp will incorrectly wrap at (2^32 / TRC_HWTC_DIVISOR) ticks. + The scaled timestamp returned from this function is supposed to go from 0 -> 2^32, which in real time would represent (0 -> 2^32 * TRC_HWTC_DIVISOR) ticks. */ + + /* First we see how long time has passed since the last timestamp call, and we also add the ticks that was lost when we scaled down the last time. */ + diff = (hwtc_count - last_hwtc_count) + last_hwtc_rest; + + /* Scale down the diff */ + diff_scaled = diff / (TRC_HWTC_DIVISOR); + + /* Find out how many ticks were lost when scaling down, so we can add them the next time */ + last_hwtc_rest = diff % (TRC_HWTC_DIVISOR); + + /* We increase the scaled timestamp by the scaled amount */ + last_timestamp += diff_scaled; +#endif /*(TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)*/ + + /* Is anyone interested in the results? */ + if (pTimestamp) + *pTimestamp = last_timestamp; + + /* Store the previous value */ + last_hwtc_count = hwtc_count; +} + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c index dc1b87865..0ca034b84 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c @@ -1,1896 +1,2035 @@ -/*******************************************************************************
- * Trace Recorder Library for Tracealyzer v4.1.5
- * Percepio AB, www.percepio.com
- *
- * trcStreamingRecorder.c
- *
- * The generic core of the trace recorder's streaming mode.
- *
- * Terms of Use
- * This file is part of the trace recorder library (RECORDER), which is the
- * intellectual property of Percepio AB (PERCEPIO) and provided under a
- * license as follows.
- * The RECORDER may be used free of charge for the purpose of recording data
- * intended for analysis in PERCEPIO products. It may not be used or modified
- * for other purposes without explicit permission from PERCEPIO.
- * You may distribute the RECORDER in its original source code form, assuming
- * this text (terms of use, disclaimer, copyright notice) is unchanged. You are
- * allowed to distribute the RECORDER with minor modifications intended for
- * configuration or porting of the RECORDER, e.g., to allow using it on a
- * specific processor, processor family or with a specific communication
- * interface. Any such modifications should be documented directly below
- * this comment block.
- *
- * Disclaimer
- * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty
- * as to its use or performance. PERCEPIO does not and cannot warrant the
- * performance or results you may obtain by using the RECORDER or documentation.
- * PERCEPIO 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, 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 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.
- *
- * Tabs are used for indent in this file (1 tab = 4 spaces)
- *
- * Copyright Percepio AB, 2018.
- * www.percepio.com
- ******************************************************************************/
-
-#include "trcRecorder.h"
-
-#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
-
-#if (TRC_USE_TRACEALYZER_RECORDER == 1)
-
-#include <stdio.h>
-#include <stdarg.h>
-
-typedef struct{
- uint16_t EventID;
- uint16_t EventCount;
- uint32_t TS;
-} BaseEvent;
-
-typedef struct{
- BaseEvent base;
- uint32_t param1;
-} EventWithParam_1;
-
-typedef struct{
- BaseEvent base;
- uint32_t param1;
- uint32_t param2;
-} EventWithParam_2;
-
-typedef struct{
- BaseEvent base;
- uint32_t param1;
- uint32_t param2;
- uint32_t param3;
-} EventWithParam_3;
-
-/* Used in event functions with variable number of parameters. */
-typedef struct
-{
- BaseEvent base;
- uint32_t data[15]; /* maximum payload size */
-} largestEventType;
-
-typedef struct{
- uint32_t psf;
- uint16_t version;
- uint16_t platform;
- uint32_t options;
- uint16_t symbolSize;
- uint16_t symbolCount;
- uint16_t objectDataSize;
- uint16_t objectDataCount;
-} PSFHeaderInfo;
-
-
-/* The size of each slot in the Symbol Table */
-#define SYMBOL_TABLE_SLOT_SIZE (sizeof(uint32_t) + (((TRC_CFG_SYMBOL_MAX_LENGTH)+(sizeof(uint32_t)-1))/sizeof(uint32_t))*sizeof(uint32_t))
-
-#define OBJECT_DATA_SLOT_SIZE (sizeof(uint32_t) + sizeof(uint32_t))
-
-/* The total size of the Symbol Table */
-#define SYMBOL_TABLE_BUFFER_SIZE ((TRC_CFG_SYMBOL_TABLE_SLOTS) * SYMBOL_TABLE_SLOT_SIZE)
-
-/* The total size of the Object Data Table */
-#define OBJECT_DATA_TABLE_BUFFER_SIZE ((TRC_CFG_OBJECT_DATA_SLOTS) * OBJECT_DATA_SLOT_SIZE)
-
-/* The Symbol Table type - just a byte array */
-typedef struct{
- union
- {
- uint32_t pSymbolTableBufferUINT32[SYMBOL_TABLE_BUFFER_SIZE / sizeof(uint32_t)];
- uint8_t pSymbolTableBufferUINT8[SYMBOL_TABLE_BUFFER_SIZE];
- } SymbolTableBuffer;
-} SymbolTable;
-
-/* The Object Data Table type - just a byte array */
-typedef struct{
- union
- {
- uint32_t pObjectDataTableBufferUINT32[OBJECT_DATA_TABLE_BUFFER_SIZE / sizeof(uint32_t)];
- uint8_t pObjectDataTableBufferUINT8[OBJECT_DATA_TABLE_BUFFER_SIZE];
- } ObjectDataTableBuffer;
-} ObjectDataTable;
-
-typedef struct{
- uint16_t Status; /* 16 bit to avoid implicit padding (warnings) */
- uint16_t BytesRemaining;
- char* WritePointer;
-} PageType;
-
-/* Code used for "task address" when no task has started. (NULL = idle task) */
-#define HANDLE_NO_TASK 2
-
-#define PAGE_STATUS_FREE 0
-#define PAGE_STATUS_WRITE 1
-#define PAGE_STATUS_READ 2
-
-#define PSF_ASSERT(_assert, _err) if (! (_assert)){ prvTraceError(_err); return; }
-
-/* Part of the PSF format - encodes the number of 32-bit params in an event */
-#define PARAM_COUNT(n) ((n & 0xF) << 12)
-
-/* The Symbol Table instance - keeps names of tasks and other named objects. */
-static SymbolTable symbolTable = { { { 0 } } };
-
-/* This points to the first unused entry in the symbol table. */
-static uint32_t firstFreeSymbolTableIndex = 0;
-
-/* The Object Data Table instance - keeps initial priorities of tasks. */
-static ObjectDataTable objectDataTable = { { { 0 } } };
-
-/* This points to the first unused entry in the object data table. */
-static uint32_t firstFreeObjectDataTableIndex = 0;
-
-/* Keeps track of ISR nesting */
-static uint32_t ISR_stack[TRC_CFG_MAX_ISR_NESTING];
-
-/* Keeps track of ISR nesting */
-static int8_t ISR_stack_index = -1;
-
-/* Any error that occurred in the recorder (also creates User Event) */
-static int errorCode = 0;
-
-/* Counts the number of trace sessions (not yet used) */
-static uint32_t SessionCounter = 0u;
-
-/* Master switch for recording (0 => Disabled, 1 => Enabled) */
-uint32_t RecorderEnabled = 0u;
-
-/* Used to determine endian of data (big/little) */
-static uint32_t PSFEndianessIdentifier = 0x50534600;
-
-/* Used to interpret the data format */
-static uint16_t FormatVersion = 0x0004;
-
-/* The number of events stored. Used as event sequence number. */
-static uint32_t eventCounter = 0;
-
-/* Remembers if an earlier ISR in a sequence of adjacent ISRs has triggered a task switch.
-In that case, vTraceStoreISREnd does not store a return to the previously executing task. */
-int32_t isPendingContextSwitch = 0;
-
-uint32_t uiTraceTickCount = 0;
-uint32_t timestampFrequency = 0;
-uint32_t DroppedEventCounter = 0;
-uint32_t TotalBytesRemaining_LowWaterMark = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
-uint32_t TotalBytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
-
-PageType PageInfo[TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT];
-
-char* EventBuffer = NULL;
-
-/*******************************************************************************
- * NoRoomForSymbol
- *
- * Incremented on prvTraceSaveSymbol if no room for saving the symbol name. This
- * is used for storing the names of:
- * - Tasks
- * - Named ISRs (xTraceSetISRProperties)
- * - Named kernel objects (vTraceStoreKernelObjectName)
- * - User event channels (xTraceRegisterString)
- *
- * This variable should be zero. If not, it shows the number of missing slots so
- * far. In that case, increment SYMBOL_TABLE_SLOTS with (at least) this value.
- ******************************************************************************/
-volatile uint32_t NoRoomForSymbol = 0;
-
-/*******************************************************************************
- * NoRoomForObjectData
- *
- * Incremented on prvTraceSaveObjectData if no room for saving the object data,
- * i.e., the base priorities of tasks. There must be one slot for each task.
- * If not, this variable will show the difference.
- *
- * This variable should be zero. If not, it shows the number of missing slots so
- * far. In that case, increment OBJECT_DATA_SLOTS with (at least) this value.
- ******************************************************************************/
-volatile uint32_t NoRoomForObjectData = 0;
-
-/*******************************************************************************
- * LongestSymbolName
- *
- * Updated in prvTraceSaveSymbol. Should not exceed TRC_CFG_SYMBOL_MAX_LENGTH,
- * otherwise symbol names will be truncated. In that case, set
- * TRC_CFG_SYMBOL_MAX_LENGTH to (at least) this value.
- ******************************************************************************/
-volatile uint32_t LongestSymbolName = 0;
-
-/*******************************************************************************
- * MaxBytesTruncated
- *
- * Set in prvTraceStoreStringEvent if the total data payload exceeds 60 bytes,
- * including data arguments and the string. For user events, that is 52 bytes
- * for string and data arguments. In that is exceeded, the event is truncated
- * (usually only the string, unless more than 15 parameters) and this variable
- * holds the maximum number of truncated bytes, from any event.
- ******************************************************************************/
-volatile uint32_t MaxBytesTruncated = 0;
-
-uint16_t CurrentFilterMask = 0xFFFF;
-
-uint16_t CurrentFilterGroup = FilterGroup0;
-
-/* Internal common function for storing string events */
-static void prvTraceStoreStringEventHelper( int nArgs,
- uint16_t eventID,
- traceString userEvtChannel,
- int len,
- const char* str,
- va_list* vl);
-
-/* Not static to avoid warnings from SysGCC/PPC */
-void prvTraceStoreSimpleStringEventHelper(traceString userEvtChannel,
- const char* str);
-
-
-/* Stores the header information on Start */
-static void prvTraceStoreHeader(void);
-
-/* Stores the symbol table on Start */
-static void prvTraceStoreSymbolTable(void);
-
-/* Stores the object table on Start */
-static void prvTraceStoreObjectDataTable(void);
-
-/* Store the Timestamp Config on Start */
-static void prvTraceStoreTSConfig(void);
-
-/* Store the current warnings */
-static void prvTraceStoreWarnings(void);
-
-/* Internal function for starting/stopping the recorder. */
-static void prvSetRecorderEnabled(uint32_t isEnabled);
-
-/* Mark the page read as complete. */
-static void prvPageReadComplete(int pageIndex);
-
-/* Retrieve a buffer page to write to. */
-static int prvAllocateBufferPage(int prevPage);
-
-/* Get the current buffer page index (return value) and the number
-of valid bytes in the buffer page (bytesUsed). */
-static int prvGetBufferPage(int32_t* bytesUsed);
-
-/* Performs timestamping using definitions in trcHardwarePort.h */
-static uint32_t prvGetTimestamp32(void);
-
-/* Signal an error. */
-void prvTraceError(int errCode);
-
-/* Signal an warning (does not stop the recorder). */
-void prvTraceWarning(int errCode);
-
-/******************************************************************************
- * vTraceInstanceFinishedNow
- *
- * Creates an event that ends the current task instance at this very instant.
- * This makes the viewer to splits the current fragment at this point and begin
- * a new actor instance, even if no task-switch has occurred.
- *****************************************************************************/
-void vTraceInstanceFinishedNow(void)
-{
- prvTraceStoreEvent0(PSF_EVENT_IFE_DIRECT);
-}
-
-/******************************************************************************
- * vTraceInstanceFinishedNext
- *
- * Marks the current "task instance" as finished on the next kernel call.
- *
- * If that kernel call is blocking, the instance ends after the blocking event
- * and the corresponding return event is then the start of the next instance.
- * If the kernel call is not blocking, the viewer instead splits the current
- * fragment right before the kernel call, which makes this call the first event
- * of the next instance.
- *****************************************************************************/
-void vTraceInstanceFinishedNext(void)
-{
- prvTraceStoreEvent0(PSF_EVENT_IFE_NEXT);
-}
-
-/*******************************************************************************
- * vTraceStoreKernelObjectName
- *
- * Parameter object: pointer to the Event Group that shall be named
- * Parameter name: the name to set (const string literal)
- *
- * Sets a name for a kernel object for display in Tracealyzer.
- ******************************************************************************/
-void vTraceStoreKernelObjectName(void* object, const char* name)
-{
- /* Always save in symbol table, if the recording has not yet started */
- prvTraceSaveSymbol(object, name);
-
- prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, name, (uint32_t)object);
-}
-
-
-/******************************************************************************
-* vTraceSetFrequency
-*
-* Registers the clock rate of the time source for the event timestamping.
-* This is normally not required, but if the default value (TRC_HWTC_FREQ_HZ)
-* should be incorrect for your setup, you can override it using this function.
-*
-* Must be called prior to vTraceEnable, and the time source is assumed to
-* have a fixed clock frequency after the startup.
-*****************************************************************************/
-void vTraceSetFrequency(uint32_t frequency)
-{
- timestampFrequency = frequency;
-}
-
-#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)
-
-/*******************************************************************************
-* xTraceRegisterString
-*
-* Stores a name for a user event channel, returns the handle.
-******************************************************************************/
-traceString xTraceRegisterString(const char* name)
-{
- prvTraceSaveSymbol((const void*)name, name);
-
- /* Always save in symbol table, if the recording has not yet started */
- prvTraceStoreStringEvent(1, PSF_EVENT_OBJ_NAME, (const char*)name, (uint32_t)name);
-
- return (traceString)name;
-}
-
-/******************************************************************************
- * vTracePrint
- *
- * Generates "User Events", with unformatted text.
- *
- * User Events can be used for very efficient application logging, and are shown
- * as yellow labels in the main trace view.
- *
- * You may group User Events into User Event Channels. The yellow User Event
- * labels shows the logged string, preceded by the channel name within
- * brackets. For example:
- *
- * "[MyChannel] Hello World!"
- *
- * The User Event Channels are shown in the View Filter, which makes it easy to
- * select what User Events you wish to display. User Event Channels are created
- * using xTraceRegisterString().
- *
- * Example:
- *
- * traceString chn = xTraceRegisterString("MyChannel");
- * ...
- * vTracePrint(chn, "Hello World!");
- *
- ******************************************************************************/
-void vTracePrint(traceString chn, const char* str)
-{
- prvTraceStoreSimpleStringEventHelper(chn, str);
-}
-
-
-/*******************************************************************************
-* vTraceConsoleChannelPrintF
-*
-* Wrapper for vTracePrint, using the default channel. Can be used as a drop-in
-* replacement for printf and similar functions, e.g. in a debug logging macro.
-*
-* Example:
-*
-* // Old: #define LogString debug_console_printf
-*
-* // New, log to Tracealyzer instead:
-* #define LogString vTraceConsoleChannelPrintF
-* ...
-* LogString("My value is: %d", myValue);
-******************************************************************************/
-void vTraceConsoleChannelPrintF(const char* fmt, ...)
-{
- va_list vl;
- char tempBuf[60];
- static traceString consoleChannel = NULL;
-
- if (consoleChannel == NULL)
- consoleChannel = xTraceRegisterString("Debug Console");
-
- va_start(vl, fmt);
- vsnprintf(tempBuf, 60, fmt, vl);
- vTracePrint(consoleChannel, tempBuf);
- va_end(vl);
-}
-
-/******************************************************************************
- * vTracePrintF
- *
- * Generates "User Events", with formatted text and data, similar to a "printf".
- * It is very fast since the actual formatting is done on the host side when the
- * trace is displayed.
- *
- * User Events can be used for very efficient application logging, and are shown
- * as yellow labels in the main trace view.
- * An advantage of User Events is that data can be plotted in the "User Event
- * Signal Plot" view, visualizing any data you log as User Events, discrete
- * states or control system signals (e.g. system inputs or outputs).
- *
- * You may group User Events into User Event Channels. The yellow User Event
- * labels show the logged string, preceded by the channel name within brackets.
- *
- * Example:
- *
- * "[MyChannel] Hello World!"
- *
- * The User Event Channels are shown in the View Filter, which makes it easy to
- * select what User Events you wish to display. User Event Channels are created
- * using xTraceRegisterString().
- *
- * Example:
- *
- * traceString adc_uechannel = xTraceRegisterString("ADC User Events");
- * ...
- * vTracePrintF(adc_uechannel,
- * "ADC channel %d: %d volts",
- * ch, adc_reading);
- *
- * All data arguments are assumed to be 32 bit wide. The following formats are
- * supported:
- * %d - signed integer. The following width and padding format is supported: "%05d" -> "-0042" and "%5d" -> " -42"
- * %u - unsigned integer. The following width and padding format is supported: "%05u" -> "00042" and "%5u" -> " 42"
- * %X - hexadecimal (uppercase). The following width and padding format is supported: "%04X" -> "002A" and "%4X" -> " 2A"
- * %x - hexadecimal (lowercase). The following width and padding format is supported: "%04x" -> "002a" and "%4x" -> " 2a"
- * %s - string (currently, this must be an earlier stored symbol name)
- *
- * Up to 15 data arguments are allowed, with a total size of maximum 60 byte
- * including 8 byte for the base event fields and the format string. So with
- * one data argument, the maximum string length is 48 chars. If this is exceeded
- * the string is truncated (4 bytes at a time).
- *
- ******************************************************************************/
-void vTracePrintF(traceString chn, const char* fmt, ...)
-{
- va_list vl;
- int i = 0;
-
- int nArgs = 0;
-
- /* Count the number of arguments in the format string (e.g., %d) */
- for (i = 0; (fmt[i] != 0) && (i < 52); i++)
- {
- if (fmt[i] == '%')
- {
- if (fmt[i + 1] != 0 && fmt[i + 1] != '%')
- {
- nArgs++; /* Found an argument */
- }
-
- i++; /* Move past format specifier or non-argument '%' */
- }
- }
-
- va_start(vl, fmt);
-
- if (chn != NULL)
- {
- prvTraceStoreStringEventHelper(nArgs, (uint16_t)(PSF_EVENT_USER_EVENT + nArgs + 1), chn, i, fmt, &vl);
- }
- else
- {
- prvTraceStoreStringEventHelper(nArgs, (uint16_t)(PSF_EVENT_USER_EVENT + nArgs), chn, i, fmt, &vl);
- }
- va_end(vl);
-}
-#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) */
-
-/*******************************************************************************
- * xTraceSetISRProperties
- *
- * Stores a name and priority level for an Interrupt Service Routine, to allow
- * for better visualization. Returns a traceHandle used by vTraceStoreISRBegin.
- *
- * Example:
- * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt
- * ...
- * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1);
- * ...
- * void ISR_handler()
- * {
- * vTraceStoreISRBegin(Timer1Handle);
- * ...
- * vTraceStoreISREnd(0);
- * }
- *
- ******************************************************************************/
-traceHandle xTraceSetISRProperties(const char* name, uint8_t priority)
-{
- /* Save object data in object data table */
- prvTraceSaveObjectData((const void*)name, priority);
-
- /* Note: "name" is used both as a string argument, and the address as ID */
- prvTraceStoreStringEvent(2, PSF_EVENT_DEFINE_ISR, name, name, priority);
-
- /* Always save in symbol table, if the recording has not yet started */
- prvTraceSaveSymbol((const void*)name, name);
-
- return (traceHandle)name;
-}
-
-/*******************************************************************************
- * vTraceStoreISRBegin
- *
- * Registers the beginning of an Interrupt Service Routine, using a traceHandle
- * provided by xTraceSetISRProperties.
- *
- * Example:
- * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt
- * ...
- * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1);
- * ...
- * void ISR_handler()
- * {
- * vTraceStoreISRBegin(Timer1Handle);
- * ...
- * vTraceStoreISREnd(0);
- * }
- *
- ******************************************************************************/
-void vTraceStoreISRBegin(traceHandle handle)
-{
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- /* We are at the start of a possible ISR chain.
- No context switches should have been triggered now. */
- if (ISR_stack_index == -1)
- isPendingContextSwitch = 0;
-
- if (ISR_stack_index < (TRC_CFG_MAX_ISR_NESTING) - 1)
- {
- ISR_stack_index++;
- ISR_stack[ISR_stack_index] = (uint32_t)handle;
-#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
- prvTraceStoreEvent1(PSF_EVENT_ISR_BEGIN, (uint32_t)handle);
-#endif
- TRACE_EXIT_CRITICAL_SECTION();
- }
- else
- {
- TRACE_EXIT_CRITICAL_SECTION();
- prvTraceError(PSF_ERROR_ISR_NESTING_OVERFLOW);
- }
-}
-
-/*******************************************************************************
- * vTraceStoreISREnd
- *
- * Registers the end of an Interrupt Service Routine.
- *
- * The parameter pendingISR indicates if the interrupt has requested a
- * task-switch (= 1), e.g., by signaling a semaphore. Otherwise (= 0) the
- * interrupt is assumed to return to the previous context.
- *
- * Example:
- * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt
- * traceHandle traceHandleIsrTimer1 = 0; // The ID set by the recorder
- * ...
- * traceHandleIsrTimer1 = xTraceSetISRProperties("ISRTimer1", PRIO_OF_ISR_TIMER1);
- * ...
- * void ISR_handler()
- * {
- * vTraceStoreISRBegin(traceHandleIsrTimer1);
- * ...
- * vTraceStoreISREnd(0);
- * }
- *
- ******************************************************************************/
-void vTraceStoreISREnd(int isTaskSwitchRequired)
-{
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- (void)ISR_stack;
-
- /* Is there a pending task-switch? (perhaps from an earlier ISR) */
- isPendingContextSwitch |= isTaskSwitchRequired;
-
- if (ISR_stack_index > 0)
- {
- ISR_stack_index--;
-
-#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
- /* Store return to interrupted ISR (if nested ISRs)*/
- prvTraceStoreEvent1(PSF_EVENT_ISR_RESUME, (uint32_t)ISR_stack[ISR_stack_index]);
-#endif
- }
- else
- {
- ISR_stack_index--;
-
- /* Store return to interrupted task, if no context switch will occur in between. */
- if ((isPendingContextSwitch == 0) || (prvTraceIsSchedulerSuspended()))
- {
-#if (TRC_CFG_INCLUDE_ISR_TRACING == 1)
- prvTraceStoreEvent1(PSF_EVENT_TS_RESUME, (uint32_t)TRACE_GET_CURRENT_TASK());
-#endif
- }
- }
-
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-
-/*******************************************************************************
- * xTraceGetLastError
- *
- * Returns the last error or warning, as a string, or NULL if none.
- *****************************************************************************/
-const char* xTraceGetLastError(void)
-{
- /* Note: the error messages are short, in order to fit in a User Event.
- Instead, the users can read more in the below comments.*/
-
- switch (errorCode)
- {
-
- case PSF_WARNING_SYMBOL_TABLE_SLOTS:
- /* There was not enough symbol table slots for storing symbol names.
- The number of missing slots is counted by NoRoomForSymbol. Inspect this
- variable and increase TRC_CFG_SYMBOL_TABLE_SLOTS by at least that value. */
-
- return "Exceeded SYMBOL_TABLE_SLOTS (see xTraceGetLastError)";
-
- case PSF_WARNING_SYMBOL_MAX_LENGTH:
- /* A symbol name exceeded TRC_CFG_SYMBOL_MAX_LENGTH in length.
- Make sure the symbol names are at most TRC_CFG_SYMBOL_MAX_LENGTH,
- or inspect LongestSymbolName and increase TRC_CFG_SYMBOL_MAX_LENGTH
- to at least this value. */
-
- return "Exceeded SYMBOL_MAX_LENGTH (see xTraceGetLastError)";
-
- case PSF_WARNING_OBJECT_DATA_SLOTS:
- /* There was not enough symbol object table slots for storing object
- properties, such as task priorites. The number of missing slots is
- counted by NoRoomForObjectData. Inspect this variable and increase
- TRC_CFG_OBJECT_DATA_SLOTS by at least that value. */
-
- return "Exceeded OBJECT_DATA_SLOTS (see xTraceGetLastError)";
-
- case PSF_WARNING_STRING_TOO_LONG:
- /* Some string argument was longer than the maximum payload size
- and has been truncated by "MaxBytesTruncated" bytes.
-
- This may happen for the following functions:
- - vTracePrint
- - vTracePrintF
- - vTraceStoreKernelObjectName
- - xTraceRegisterString
- - vTraceSetISRProperties
-
- A PSF event may store maximum 60 bytes payload, including data
- arguments and string characters. For User Events, also the User
- Event Channel (4 bytes) must be squeezed in, if a channel is
- specified (can be NULL). */
-
- return "String too long (see xTraceGetLastError)";
-
- case PSF_WARNING_STREAM_PORT_READ:
- /* TRC_STREAM_PORT_READ_DATA is expected to return 0 when completed successfully.
- This means there is an error in the communication with host/Tracealyzer. */
-
- return "TRC_STREAM_PORT_READ_DATA returned error (!= 0).";
-
- case PSF_WARNING_STREAM_PORT_WRITE:
- /* TRC_STREAM_PORT_WRITE_DATA is expected to return 0 when completed successfully.
- This means there is an error in the communication with host/Tracealyzer. */
-
- return "TRC_STREAM_PORT_WRITE_DATA returned error (!= 0).";
-
- case PSF_ERROR_EVENT_CODE_TOO_LARGE:
- /* The highest allowed event code is 4095, anything higher is an unexpected error.
- Please contact support@percepio.com for assistance.*/
-
- return "Invalid event code (see xTraceGetLastError)";
-
- case PSF_ERROR_ISR_NESTING_OVERFLOW:
- /* Nesting of ISR trace calls exceeded the limit (TRC_CFG_MAX_ISR_NESTING).
- If this is unlikely, make sure that you call vTraceStoreISRExit in the end
- of all ISR handlers. Or increase TRC_CFG_MAX_ISR_NESTING. */
-
- return "Exceeded ISR nesting (see xTraceGetLastError)";
-
- case PSF_ERROR_DWT_NOT_SUPPORTED:
- /* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip.
- DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M
- macro normally set by ARM's CMSIS library, since typically available. You can however select
- SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/
-
- return "DWT not supported (see xTraceGetLastError)";
-
- case PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED:
- /* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip.
- DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M
- macro normally set by ARM's CMSIS library, since typically available. You can however select
- SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/
-
- return "DWT_CYCCNT not supported (see xTraceGetLastError)";
-
- case PSF_ERROR_TZCTRLTASK_NOT_CREATED:
- /* vTraceEnable failed creating the trace control task (TzCtrl) - incorrect parameters (priority?)
- or insufficient heap size? */
- return "Could not create TzCtrl (see xTraceGetLastError)";
-
- }
-
- return NULL;
-}
-
-/*******************************************************************************
- * vTraceClearError
- *
- * Clears any errors.
- *****************************************************************************/
-void vTraceClearError(void)
-{
- NoRoomForSymbol = 0;
- LongestSymbolName = 0;
- NoRoomForObjectData = 0;
- MaxBytesTruncated = 0;
- errorCode = PSF_ERROR_NONE;
-}
-
-/*******************************************************************************
- * vTraceStop
- *
- * Stops the tracing.
- *****************************************************************************/
-void vTraceStop(void)
-{
- prvSetRecorderEnabled(0);
-}
-
-/*******************************************************************************
- * vTraceSetRecorderDataBuffer
- *
- * If custom allocation is used, this function must be called so the recorder
- * library knows where to save the trace data.
- ******************************************************************************/
-#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM)
-
-extern char* _TzTraceData;
-
-void vTraceSetRecorderDataBuffer(void* pRecorderData)
-{
- _TzTraceData = pRecorderData;
-}
-#endif
-
-
-/*******************************************************************************
-* xTraceIsRecordingEnabled
-* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0.
-******************************************************************************/
-int xTraceIsRecordingEnabled(void)
-{
- return (int)RecorderEnabled;
-}
-
-void vTraceSetFilterMask(uint16_t filterMask)
-{
- CurrentFilterMask = filterMask;
-}
-
-void vTraceSetFilterGroup(uint16_t filterGroup)
-{
- CurrentFilterGroup = filterGroup;
-}
-
-
-/******************************************************************************/
-/*** INTERNAL FUNCTIONS *******************************************************/
-/******************************************************************************/
-
-/* Internal function for starting/stopping the recorder. */
-static void prvSetRecorderEnabled(uint32_t isEnabled)
-{
- void* currentTask;
-
- TRACE_ALLOC_CRITICAL_SECTION();
-
- if (RecorderEnabled == isEnabled)
- {
- return;
- }
-
- currentTask = TRACE_GET_CURRENT_TASK();
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- RecorderEnabled = isEnabled;
-
- if (currentTask == NULL)
- {
- currentTask = (void*)HANDLE_NO_TASK;
- }
-
- if (RecorderEnabled)
- {
- TRC_STREAM_PORT_ON_TRACE_BEGIN();
-
- #if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1)
- prvPagedEventBufferInit(_TzTraceData);
- #endif
-
- eventCounter = 0;
- ISR_stack_index = -1;
- prvTraceStoreHeader();
- prvTraceStoreSymbolTable();
- prvTraceStoreObjectDataTable();
- prvTraceStoreEvent3( PSF_EVENT_TRACE_START,
- (uint32_t)TRACE_GET_OS_TICKS(),
- (uint32_t)currentTask,
- SessionCounter++);
- prvTraceStoreTSConfig();
- prvTraceStoreWarnings();
- }
- else
- {
- TRC_STREAM_PORT_ON_TRACE_END();
- }
-
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Stores the symbol table on Start */
-static void prvTraceStoreSymbolTable(void)
-{
- uint32_t i = 0;
- uint32_t j = 0;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- if (RecorderEnabled)
- {
- for (i = 0; i < (sizeof(SymbolTable) / sizeof(uint32_t)); i += (SYMBOL_TABLE_SLOT_SIZE / sizeof(uint32_t)))
- {
- TRC_STREAM_PORT_ALLOCATE_EVENT(uint32_t, data, SYMBOL_TABLE_SLOT_SIZE);
- if (data != NULL)
- {
- for (j = 0; j < (SYMBOL_TABLE_SLOT_SIZE / sizeof(uint32_t)); j++)
- {
- data[j] = symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT32[i+j];
- }
- TRC_STREAM_PORT_COMMIT_EVENT(data, SYMBOL_TABLE_SLOT_SIZE);
- }
- }
- }
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Stores the object table on Start */
-static void prvTraceStoreObjectDataTable(void)
-{
- uint32_t i = 0;
- uint32_t j = 0;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- if (RecorderEnabled)
- {
- for (i = 0; i < (sizeof(ObjectDataTable) / sizeof(uint32_t)); i += (OBJECT_DATA_SLOT_SIZE / sizeof(uint32_t)))
- {
- TRC_STREAM_PORT_ALLOCATE_EVENT(uint32_t, data, OBJECT_DATA_SLOT_SIZE);
- if (data != NULL)
- {
- for (j = 0; j < (OBJECT_DATA_SLOT_SIZE / sizeof(uint32_t)); j++)
- {
- data[j] = objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[i+j];
- }
- TRC_STREAM_PORT_COMMIT_EVENT(data, OBJECT_DATA_SLOT_SIZE);
- }
- }
- }
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Stores the header information on Start */
-static void prvTraceStoreHeader(void)
-{
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- if (RecorderEnabled)
- {
- TRC_STREAM_PORT_ALLOCATE_EVENT(PSFHeaderInfo, header, sizeof(PSFHeaderInfo));
- if (header != NULL)
- {
- header->psf = PSFEndianessIdentifier;
- header->version = FormatVersion;
- header->platform = TRACE_KERNEL_VERSION;
- header->options = 0;
- /* Lowest bit used for TRC_IRQ_PRIORITY_ORDER */
- header->options = header->options | (TRC_IRQ_PRIORITY_ORDER << 0);
- header->symbolSize = SYMBOL_TABLE_SLOT_SIZE;
- header->symbolCount = (TRC_CFG_SYMBOL_TABLE_SLOTS);
- header->objectDataSize = 8;
- header->objectDataCount = (TRC_CFG_OBJECT_DATA_SLOTS);
- TRC_STREAM_PORT_COMMIT_EVENT(header, sizeof(PSFHeaderInfo));
- }
- }
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Store the current warnings */
-static void prvTraceStoreWarnings(void)
-{
- if (RecorderEnabled)
- {
- const char* errStr = xTraceGetLastError();
-
- if (errStr != NULL)
- {
- vTracePrint(trcWarningChannel, errStr);
- }
- }
-}
-
-/* Store an event with zero parameters (event ID only) */
-void prvTraceStoreEvent0(uint16_t eventID)
-{
- TRACE_ALLOC_CRITICAL_SECTION();
-
- PSF_ASSERT(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE);
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- if (RecorderEnabled)
- {
- eventCounter++;
-
- {
- TRC_STREAM_PORT_ALLOCATE_EVENT(BaseEvent, event, sizeof(BaseEvent));
- if (event != NULL)
- {
- event->EventID = eventID | PARAM_COUNT(0);
- event->EventCount = (uint16_t)eventCounter;
- event->TS = prvGetTimestamp32();
- TRC_STREAM_PORT_COMMIT_EVENT(event, sizeof(BaseEvent));
- }
- }
- }
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Store an event with one 32-bit parameter (pointer address or an int) */
-void prvTraceStoreEvent1(uint16_t eventID, uint32_t param1)
-{
- TRACE_ALLOC_CRITICAL_SECTION();
-
- PSF_ASSERT(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE);
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- if (RecorderEnabled)
- {
- eventCounter++;
-
- {
- TRC_STREAM_PORT_ALLOCATE_EVENT(EventWithParam_1, event, sizeof(EventWithParam_1));
- if (event != NULL)
- {
- event->base.EventID = eventID | PARAM_COUNT(1);
- event->base.EventCount = (uint16_t)eventCounter;
- event->base.TS = prvGetTimestamp32();
- event->param1 = (uint32_t)param1;
- TRC_STREAM_PORT_COMMIT_EVENT(event, sizeof(EventWithParam_1));
- }
- }
- }
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Store an event with two 32-bit parameters */
-void prvTraceStoreEvent2(uint16_t eventID, uint32_t param1, uint32_t param2)
-{
- TRACE_ALLOC_CRITICAL_SECTION();
-
- PSF_ASSERT(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE);
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- if (RecorderEnabled)
- {
- eventCounter++;
-
- {
- TRC_STREAM_PORT_ALLOCATE_EVENT(EventWithParam_2, event, sizeof(EventWithParam_2));
- if (event != NULL)
- {
- event->base.EventID = eventID | PARAM_COUNT(2);
- event->base.EventCount = (uint16_t)eventCounter;
- event->base.TS = prvGetTimestamp32();
- event->param1 = (uint32_t)param1;
- event->param2 = param2;
- TRC_STREAM_PORT_COMMIT_EVENT(event, sizeof(EventWithParam_2));
- }
- }
- }
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Store an event with three 32-bit parameters */
-void prvTraceStoreEvent3( uint16_t eventID,
- uint32_t param1,
- uint32_t param2,
- uint32_t param3)
-{
- TRACE_ALLOC_CRITICAL_SECTION();
-
- PSF_ASSERT(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE);
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- if (RecorderEnabled)
- {
- eventCounter++;
-
- {
- TRC_STREAM_PORT_ALLOCATE_EVENT(EventWithParam_3, event, sizeof(EventWithParam_3));
- if (event != NULL)
- {
- event->base.EventID = eventID | PARAM_COUNT(3);
- event->base.EventCount = (uint16_t)eventCounter;
- event->base.TS = prvGetTimestamp32();
- event->param1 = (uint32_t)param1;
- event->param2 = param2;
- event->param3 = param3;
- TRC_STREAM_PORT_COMMIT_EVENT(event, sizeof(EventWithParam_3));
- }
- }
- }
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Stores an event with <nParam> 32-bit integer parameters */
-void prvTraceStoreEvent(int nParam, uint16_t eventID, ...)
-{
- va_list vl;
- int i;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- PSF_ASSERT(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE);
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- if (RecorderEnabled)
- {
- int eventSize = (int)sizeof(BaseEvent) + nParam * (int)sizeof(uint32_t);
-
- eventCounter++;
-
- {
- TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(largestEventType, event, eventSize);
- if (event != NULL)
- {
- event->base.EventID = eventID | (uint16_t)PARAM_COUNT(nParam);
- event->base.EventCount = (uint16_t)eventCounter;
- event->base.TS = prvGetTimestamp32();
-
- va_start(vl, eventID);
- for (i = 0; i < nParam; i++)
- {
- uint32_t* tmp = (uint32_t*) &(event->data[i]);
- *tmp = va_arg(vl, uint32_t);
- }
- va_end(vl);
-
- TRC_STREAM_PORT_COMMIT_EVENT(event, (uint32_t)eventSize);
- }
- }
- }
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Stories an event with a string and <nParam> 32-bit integer parameters */
-void prvTraceStoreStringEvent(int nArgs, uint16_t eventID, const char* str, ...)
-{
- int len;
- va_list vl;
-
- for (len = 0; (str[len] != 0) && (len < 52); len++); /* empty loop */
-
- va_start(vl, str);
- prvTraceStoreStringEventHelper(nArgs, eventID, NULL, len, str, &vl);
- va_end(vl);
-}
-
-/* Internal common function for storing string events */
-static void prvTraceStoreStringEventHelper(int nArgs,
- uint16_t eventID,
- traceString userEvtChannel,
- int len,
- const char* str,
- va_list* vl)
-{
- int nWords;
- int nStrWords;
- int i;
- int offset = 0;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- PSF_ASSERT(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE);
-
- /* The string length in multiples of 32 bit words (+1 for null character) */
- nStrWords = (len+1+3)/4;
-
- /* If a user event channel is specified, add in the list */
- if (userEvtChannel)
- nArgs++;
-
- offset = nArgs * 4;
-
- /* The total number of 32-bit words needed for the whole payload */
- nWords = nStrWords + nArgs;
-
- if (nWords > 15) /* if attempting to store more than 60 byte (= max) */
- {
- /* Truncate event if too large. The string characters are stored
- last, so usually only the string is truncated, unless there a lot
- of parameters... */
-
- /* Diagnostics ... */
- uint32_t bytesTruncated = (uint32_t)(nWords - 15) * 4;
-
- if (bytesTruncated > MaxBytesTruncated)
- {
- MaxBytesTruncated = bytesTruncated;
- }
-
- nWords = 15;
- len = 15 * 4 - offset;
- }
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- if (RecorderEnabled)
- {
- int eventSize = (int)sizeof(BaseEvent) + nWords * (int)sizeof(uint32_t);
-
- eventCounter++;
-
- {
- TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(largestEventType, event, eventSize);
- if (event != NULL)
- {
- uint32_t* data32;
- uint8_t* data8;
- event->base.EventID = (eventID) | (uint16_t)PARAM_COUNT(nWords);
- event->base.EventCount = (uint16_t)eventCounter;
- event->base.TS = prvGetTimestamp32();
-
- /* 32-bit write-pointer for the data argument */
- data32 = (uint32_t*) &(event->data[0]);
-
- for (i = 0; i < nArgs; i++)
- {
- if ((userEvtChannel != NULL) && (i == 0))
- {
- /* First, add the User Event Channel if not NULL */
- data32[i] = (uint32_t)userEvtChannel;
- }
- else
- {
- /* Add data arguments... */
- data32[i] = va_arg(*vl, uint32_t);
- }
- }
- data8 = (uint8_t*)&(event->data[0]);
- for (i = 0; i < len; i++)
- {
- data8[offset + i] = str[i];
- }
-
- if (len < (15 * 4 - offset))
- data8[offset + len] = 0; /* Only truncate if we don't fill up the buffer completely */
- TRC_STREAM_PORT_COMMIT_EVENT(event, (uint32_t)eventSize);
- }
- }
- }
-
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Internal common function for storing string events without additional arguments */
-void prvTraceStoreSimpleStringEventHelper(traceString userEvtChannel,
- const char* str)
-{
- int len;
- int nWords;
- int nStrWords;
- int i;
- int nArgs = 0;
- int offset = 0;
- uint16_t eventID = PSF_EVENT_USER_EVENT;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- PSF_ASSERT(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE);
-
- for (len = 0; (str[len] != 0) && (len < 52); len++); /* empty loop */
-
- /* The string length in multiples of 32 bit words (+1 for null character) */
- nStrWords = (len+1+3)/4;
-
- /* If a user event channel is specified, add in the list */
- if (userEvtChannel)
- {
- nArgs++;
- eventID++;
- }
-
- offset = nArgs * 4;
-
- /* The total number of 32-bit words needed for the whole payload */
- nWords = nStrWords + nArgs;
-
- if (nWords > 15) /* if attempting to store more than 60 byte (= max) */
- {
- /* Truncate event if too large. The string characters are stored
- last, so usually only the string is truncated, unless there a lot
- of parameters... */
-
- /* Diagnostics ... */
- uint32_t bytesTruncated = (uint32_t)(nWords - 15) * 4;
-
- if (bytesTruncated > MaxBytesTruncated)
- {
- MaxBytesTruncated = bytesTruncated;
- }
-
- nWords = 15;
- len = 15 * 4 - offset;
- }
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- if (RecorderEnabled)
- {
- int eventSize = (int)sizeof(BaseEvent) + nWords * (int)sizeof(uint32_t);
-
- eventCounter++;
-
- {
- TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(largestEventType, event, eventSize);
- if (event != NULL)
- {
- uint32_t* data32;
- uint8_t* data8;
- event->base.EventID = (eventID) | (uint16_t)PARAM_COUNT(nWords);
- event->base.EventCount = (uint16_t)eventCounter;
- event->base.TS = prvGetTimestamp32();
-
- /* 32-bit write-pointer for the data argument */
- data32 = (uint32_t*) &(event->data[0]);
-
- if (userEvtChannel != NULL)
- {
- /* First, add the User Event Channel if not NULL */
- data32[0] = (uint32_t)userEvtChannel;
- }
-
- data8 = (uint8_t*) &(event->data[0]);
- for (i = 0; i < len; i++)
- {
- data8[offset + i] = str[i];
- }
-
- if (len < (15 * 4 - offset))
- data8[offset + len] = 0; /* Only truncate if we don't fill up the buffer completely */
- TRC_STREAM_PORT_COMMIT_EVENT(event, (uint32_t)eventSize);
- }
- }
- }
-
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Saves a symbol name (task name etc.) in symbol table */
-void prvTraceSaveSymbol(const void *address, const char *name)
-{
- uint32_t i;
- uint32_t foundSlot;
- uint32_t *ptrAddress;
- uint8_t *ptrSymbol;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- foundSlot = firstFreeSymbolTableIndex;
-
- /* First look for previous entries using this address */
- for (i = 0; i < firstFreeSymbolTableIndex; i += SYMBOL_TABLE_SLOT_SIZE)
- {
- /* We access the symbol table via the union member pSymbolTableBufferUINT32 to avoid strict-aliasing issues */
- ptrAddress = &symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT32[i / sizeof(uint32_t)];
- if (*ptrAddress == (uint32_t)address)
- {
- foundSlot = i;
- break;
- }
- }
-
- if (foundSlot < SYMBOL_TABLE_BUFFER_SIZE)
- {
- /* We access the symbol table via the union member pSymbolTableBufferUINT32 to avoid strict-aliasing issues */
- symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT32[foundSlot / sizeof(uint32_t)] = (uint32_t)address;
-
- /* We access the symbol table via the union member pSymbolTableBufferUINT8 to avoid strict-aliasing issues */
- ptrSymbol = &symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT8[foundSlot + sizeof(uint32_t)];
- for (i = 0; i < (TRC_CFG_SYMBOL_MAX_LENGTH); i++)
- {
- ptrSymbol[i] = (uint8_t)name[i]; /* We do this first to ensure we also get the 0 termination, if there is one */
-
- if (name[i] == 0)
- break;
- }
-
- /* Check the length of "name", if longer than SYMBOL_MAX_LENGTH */
- while ((name[i] != 0) && i < 128)
- {
- i++;
- }
-
- /* Remember the longest symbol name, for diagnostic purposes */
- if (i > LongestSymbolName)
- {
- LongestSymbolName = i;
- }
-
- /* Is this the last entry in the symbol table? */
- if (foundSlot == firstFreeSymbolTableIndex)
- {
- firstFreeSymbolTableIndex += SYMBOL_TABLE_SLOT_SIZE;
- }
- }
- else
- {
- NoRoomForSymbol++;
- }
-
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Deletes a symbol name (task name etc.) from symbol table */
-void prvTraceDeleteSymbol(void *address)
-{
- uint32_t i, j;
- uint32_t *ptr, *lastEntryPtr;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- for (i = 0; i < firstFreeSymbolTableIndex; i += SYMBOL_TABLE_SLOT_SIZE)
- {
- /* We access the symbol table via the union member pSymbolTableBufferUINT32 to avoid strict-aliasing issues */
- ptr = &symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT32[i / sizeof(uint32_t)];
- if (*ptr == (uint32_t)address)
- {
- /* See if we have another entry in the table, and that this isn't already the last entry */
- if (firstFreeSymbolTableIndex > SYMBOL_TABLE_SLOT_SIZE && i != (firstFreeSymbolTableIndex - SYMBOL_TABLE_SLOT_SIZE))
- {
- /* Another entry is available, get pointer to the last one */
- /* We access the symbol table via the union member pSymbolTableBufferUINT32 to avoid strict-aliasing issues */
- lastEntryPtr = &symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT32[(firstFreeSymbolTableIndex - SYMBOL_TABLE_SLOT_SIZE) / sizeof(uint32_t)];
-
- /* Copy last entry to this position */
- for (j = 0; j < (SYMBOL_TABLE_SLOT_SIZE) / sizeof(uint32_t); j++)
- {
- ptr[j] = lastEntryPtr[j];
- }
-
- /* For good measure we also zero out the original position */
- *lastEntryPtr = 0;
- }
- else
- *ptr = 0; /* No other entry found, or this is the last entry */
-
- /* Lower index */
- firstFreeSymbolTableIndex -= SYMBOL_TABLE_SLOT_SIZE;
-
- break;
- }
- }
-
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Saves an object data entry (current task priority) in object data table */
-void prvTraceSaveObjectData(const void *address, uint32_t data)
-{
- uint32_t i;
- uint32_t foundSlot;
- uint32_t *ptr;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- foundSlot = firstFreeObjectDataTableIndex;
-
- /* First look for previous entries using this address */
- for (i = 0; i < firstFreeObjectDataTableIndex; i += OBJECT_DATA_SLOT_SIZE)
- {
- /* We access the data table via the union member pObjectDataTableBufferUINT32 to avoid strict-aliasing issues */
- ptr = &objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[i / sizeof(uint32_t)];
- if (*ptr == (uint32_t)address)
- {
- foundSlot = i;
- break;
- }
- }
-
- if (foundSlot < OBJECT_DATA_TABLE_BUFFER_SIZE)
- {
- /* We access the data table via the union member pObjectDataTableBufferUINT32 to avoid strict-aliasing issues */
- objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[foundSlot / sizeof(uint32_t)] = (uint32_t)address;
- objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[foundSlot / sizeof(uint32_t) + 1] = data;
-
- /* Is this the last entry in the object data table? */
- if (foundSlot == firstFreeObjectDataTableIndex)
- {
- firstFreeObjectDataTableIndex += OBJECT_DATA_SLOT_SIZE;
- }
- }
- else
- {
- NoRoomForObjectData++;
- }
-
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Removes an object data entry (task base priority) from object data table */
-void prvTraceDeleteObjectData(void *address)
-{
- uint32_t i, j;
- uint32_t *ptr, *lastEntryPtr;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ENTER_CRITICAL_SECTION();
-
- for (i = 0; i < firstFreeObjectDataTableIndex; i += OBJECT_DATA_SLOT_SIZE)
- {
- /* We access the data table via the union member pObjectDataTableBufferUINT32 to avoid strict-aliasing issues */
- ptr = &objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[i / sizeof(uint32_t)];
- if (*ptr == (uint32_t)address)
- {
- /* See if we have another entry in the table, and that this isn't already the last entry */
- if (firstFreeObjectDataTableIndex > OBJECT_DATA_SLOT_SIZE && i != (firstFreeObjectDataTableIndex - OBJECT_DATA_SLOT_SIZE))
- {
- /* Another entry is available, get pointer to the last one */
- /* We access the data table via the union member pObjectDataTableBufferUINT32 to avoid strict-aliasing issues */
- lastEntryPtr = &objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[(firstFreeObjectDataTableIndex - OBJECT_DATA_SLOT_SIZE) / sizeof(uint32_t)];
-
- /* Copy last entry to this position */
- for (j = 0; j < (OBJECT_DATA_SLOT_SIZE) / sizeof(uint32_t); j++)
- {
- ptr[j] = lastEntryPtr[j];
- }
-
- /* For good measure we also zero out the original position */
- *lastEntryPtr = 0;
- }
- else
- *ptr = 0; /* No other entry found, or this is the last entry */
-
- /* Lower index */
- firstFreeObjectDataTableIndex -= OBJECT_DATA_SLOT_SIZE;
-
- break;
- }
- }
-
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Checks if the provided command is a valid command */
-int prvIsValidCommand(TracealyzerCommandType* cmd)
-{
- uint16_t checksum = (uint16_t)(0xFFFF - ( cmd->cmdCode +
- cmd->param1 +
- cmd->param2 +
- cmd->param3 +
- cmd->param4 +
- cmd->param5));
-
- if (cmd->checksumMSB != (unsigned char)(checksum >> 8))
- return 0;
-
- if (cmd->checksumLSB != (unsigned char)(checksum & 0xFF))
- return 0;
-
- if (cmd->cmdCode > CMD_LAST_COMMAND)
- return 0;
-
- return 1;
-}
-
-/* Executed the received command (Start or Stop) */
-void prvProcessCommand(TracealyzerCommandType* cmd)
-{
- switch(cmd->cmdCode)
- {
- case CMD_SET_ACTIVE:
- prvSetRecorderEnabled(cmd->param1);
- break;
- default:
- break;
- }
-}
-
-/* Called on warnings, when the recording can continue. */
-void prvTraceWarning(int errCode)
-{
- if (!errorCode)
- {
- errorCode = errCode;
- prvTraceStoreWarnings();
- }
-}
-
-/* Called on critical errors in the recorder. Stops the recorder! */
-void prvTraceError(int errCode)
-{
- if (! errorCode)
- {
- errorCode = errCode;
- prvTraceStoreWarnings();
- vTracePrintF(trcWarningChannel, "Recorder stopped in prvTraceError()");
-
- prvSetRecorderEnabled(0);
- }
-}
-
-/* If using DWT timestamping (default on ARM Cortex-M3, M4 and M7), make sure the DWT unit is initialized. */
-#ifndef TRC_CFG_ARM_CM_USE_SYSTICK
-#if ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) && (defined (__CORTEX_M) && (__CORTEX_M >= 0x03)))
-
-void prvTraceInitCortexM()
-{
- /* Make sure the DWT registers are unlocked, in case the debugger doesn't do this. */
- TRC_REG_ITM_LOCKACCESS = TRC_ITM_LOCKACCESS_UNLOCK;
-
- /* Make sure DWT is enabled is enabled, if supported */
- TRC_REG_DEMCR |= TRC_DEMCR_TRCENA;
-
- do
- {
- /* Verify that DWT is supported */
- if (TRC_REG_DEMCR == 0)
- {
- /* This function is called on Cortex-M3, M4 and M7 devices to initialize
- the DWT unit, assumed present. The DWT cycle counter is used for timestamping.
-
- If the below error is produced, the DWT unit does not seem to be available.
-
- In that case, define the macro TRC_CFG_ARM_CM_USE_SYSTICK in your build
- to use SysTick timestamping instead, or define your own timestamping by
- setting TRC_CFG_HARDWARE_PORT to TRC_HARDWARE_PORT_APPLICATION_DEFINED
- and make the necessary definitions, as explained in trcHardwarePort.h.*/
-
- prvTraceError(PSF_ERROR_DWT_NOT_SUPPORTED);
- break;
- }
-
- /* Verify that DWT_CYCCNT is supported */
- if (TRC_REG_DWT_CTRL & TRC_DWT_CTRL_NOCYCCNT)
- {
- /* This function is called on Cortex-M3, M4 and M7 devices to initialize
- the DWT unit, assumed present. The DWT cycle counter is used for timestamping.
-
- If the below error is produced, the cycle counter does not seem to be available.
-
- In that case, define the macro TRC_CFG_ARM_CM_USE_SYSTICK in your build
- to use SysTick timestamping instead, or define your own timestamping by
- setting TRC_CFG_HARDWARE_PORT to TRC_HARDWARE_PORT_APPLICATION_DEFINED
- and make the necessary definitions, as explained in trcHardwarePort.h.*/
-
- prvTraceError(PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED);
- break;
- }
-
- /* Reset the cycle counter */
- TRC_REG_DWT_CYCCNT = 0;
-
- /* Enable the cycle counter */
- TRC_REG_DWT_CTRL |= TRC_DWT_CTRL_CYCCNTENA;
-
- } while(0); /* breaks above jump here */
-}
-#endif
-#endif
-
-/* Performs timestamping using definitions in trcHardwarePort.h */
-static uint32_t prvGetTimestamp32(void)
-{
-#if ((TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_INCR) || (TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_DECR))
- return TRC_HWTC_COUNT;
-#endif
-
-#if ((TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR) || (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR))
- return TRC_HWTC_COUNT;
-#endif
-
-#if ((TRC_HWTC_TYPE == TRC_OS_TIMER_INCR) || (TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))
- uint32_t ticks = TRACE_GET_OS_TICKS();
- return ((TRC_HWTC_COUNT) & 0x00FFFFFFU) + ((ticks & 0x000000FFU) << 24);
-#endif
-}
-
-/* Store the Timestamp Config event */
-static void prvTraceStoreTSConfig(void)
-{
- /* If not overridden using vTraceSetFrequency, use default value */
- if (timestampFrequency == 0)
- {
- timestampFrequency = TRC_HWTC_FREQ_HZ;
- }
-
- #if (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR || TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR)
-
- prvTraceStoreEvent(5,
- PSF_EVENT_TS_CONFIG,
- (uint32_t)timestampFrequency,
- (uint32_t)(TRACE_TICK_RATE_HZ),
- (uint32_t)(TRC_HWTC_TYPE),
- (uint32_t)(TRC_CFG_ISR_TAILCHAINING_THRESHOLD),
- (uint32_t)(TRC_HWTC_PERIOD));
-
- #else
-
- prvTraceStoreEvent(4,
- PSF_EVENT_TS_CONFIG,
- (uint32_t)timestampFrequency,
- (uint32_t)(TRACE_TICK_RATE_HZ),
- (uint32_t)(TRC_HWTC_TYPE),
- (uint32_t)(TRC_CFG_ISR_TAILCHAINING_THRESHOLD));
- #endif
-}
-
-/* Retrieve a buffer page to write to. */
-static int prvAllocateBufferPage(int prevPage)
-{
- int index;
- int count = 0;
-
- index = (prevPage + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT);
-
- while((PageInfo[index].Status != PAGE_STATUS_FREE) && (count ++ < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT)))
- {
- index = (index + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT);
- }
-
- if (PageInfo[index].Status == PAGE_STATUS_FREE)
- {
- return index;
- }
-
- return -1;
-}
-
-/* Mark the page read as complete. */
-static void prvPageReadComplete(int pageIndex)
-{
- TRACE_ALLOC_CRITICAL_SECTION();
-
- TRACE_ENTER_CRITICAL_SECTION();
- PageInfo[pageIndex].BytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
- PageInfo[pageIndex].WritePointer = &EventBuffer[pageIndex * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];
- PageInfo[pageIndex].Status = PAGE_STATUS_FREE;
-
- TotalBytesRemaining += (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
-
- TRACE_EXIT_CRITICAL_SECTION();
-}
-
-/* Get the current buffer page index and remaining number of bytes. */
-static int prvGetBufferPage(int32_t* bytesUsed)
-{
- static int8_t lastPage = -1;
- int count = 0;
- int8_t index = (int8_t) ((lastPage + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT));
-
- while((PageInfo[index].Status != PAGE_STATUS_READ) && (count++ < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT)))
- {
- index = (int8_t)((index + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT));
- }
-
- if (PageInfo[index].Status == PAGE_STATUS_READ)
- {
- *bytesUsed = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE) - PageInfo[index].BytesRemaining;
- lastPage = index;
- return index;
- }
-
- *bytesUsed = 0;
-
- return -1;
-}
-
-/*******************************************************************************
- * uint32_t prvPagedEventBufferTransfer(void)
- *
- * Transfers one buffer page of trace data, if a full page is available, using
- * the macro TRC_STREAM_PORT_WRITE_DATA as defined in trcStreamingPort.h.
- *
- * This function is intended to be called the periodic TzCtrl task with a suitable
- * delay (e.g. 10-100 ms).
- *
- * Returns the number of bytes sent. If non-zero, it is good to call this
- * again, in order to send any additional data waiting in the buffer.
- * If zero, wait a while before calling again.
- *
- * In case of errors from the streaming interface, it registers a warning
- * (PSF_WARNING_STREAM_PORT_WRITE) provided by xTraceGetLastError().
- *
- *******************************************************************************/
-uint32_t prvPagedEventBufferTransfer(void)
-{
- int8_t pageToTransfer = -1;
- int32_t bytesTransferredTotal = 0;
- int32_t bytesTransferredNow = 0;
- int32_t bytesToTransfer;
-
- pageToTransfer = (int8_t)prvGetBufferPage(&bytesToTransfer);
-
- /* bytesToTransfer now contains the number of "valid" bytes in the buffer page, that should be transmitted.
- There might be some unused junk bytes in the end, that must be ignored. */
-
- if (pageToTransfer > -1)
- {
- while (1) /* Keep going until we have transferred all that we intended to */
- {
- if (TRC_STREAM_PORT_WRITE_DATA(
- &EventBuffer[pageToTransfer * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE) + bytesTransferredTotal],
- (uint32_t)(bytesToTransfer - bytesTransferredTotal),
- &bytesTransferredNow) == 0)
- {
- /* Write was successful. Update the number of transferred bytes. */
- bytesTransferredTotal += bytesTransferredNow;
-
- if (bytesTransferredTotal == bytesToTransfer)
- {
- /* All bytes have been transferred. Mark the buffer page as "Read Complete" (so it can be written to) and return OK. */
- prvPageReadComplete(pageToTransfer);
- return (uint32_t)bytesTransferredTotal;
- }
- }
- else
- {
- /* Some error from the streaming interface... */
- prvTraceWarning(PSF_WARNING_STREAM_PORT_WRITE);
- return 0;
- }
- }
- }
- return 0;
-}
-
-/*******************************************************************************
- * void* prvPagedEventBufferGetWritePointer(int sizeOfEvent)
- *
- * Returns a pointer to an available location in the buffer able to store the
- * requested size.
- *
- * Return value: The pointer.
- *
- * Parameters:
- * - sizeOfEvent: The size of the event that is to be placed in the buffer.
- *
-*******************************************************************************/
-void* prvPagedEventBufferGetWritePointer(int sizeOfEvent)
-{
- void* ret;
- static int currentWritePage = -1;
-
- if (currentWritePage == -1)
- {
- currentWritePage = prvAllocateBufferPage(currentWritePage);
- if (currentWritePage == -1)
- {
- DroppedEventCounter++;
- return NULL;
- }
- }
-
- if (PageInfo[currentWritePage].BytesRemaining - sizeOfEvent < 0)
- {
- PageInfo[currentWritePage].Status = PAGE_STATUS_READ;
-
- TotalBytesRemaining -= PageInfo[currentWritePage].BytesRemaining; // Last trailing bytes
-
- if (TotalBytesRemaining < TotalBytesRemaining_LowWaterMark)
- TotalBytesRemaining_LowWaterMark = TotalBytesRemaining;
-
- currentWritePage = prvAllocateBufferPage(currentWritePage);
- if (currentWritePage == -1)
- {
- DroppedEventCounter++;
- return NULL;
- }
- }
- ret = PageInfo[currentWritePage].WritePointer;
- PageInfo[currentWritePage].WritePointer += sizeOfEvent;
- PageInfo[currentWritePage].BytesRemaining = (uint16_t)(PageInfo[currentWritePage].BytesRemaining -sizeOfEvent);
-
- TotalBytesRemaining = (TotalBytesRemaining-(uint16_t)sizeOfEvent);
-
- if (TotalBytesRemaining < TotalBytesRemaining_LowWaterMark)
- TotalBytesRemaining_LowWaterMark = TotalBytesRemaining;
-
- return ret;
-}
-
-/*******************************************************************************
- * void prvPagedEventBufferInit(char* buffer)
- *
- * Assigns the buffer to use and initializes the PageInfo structure.
- *
- * Return value: void
- *
- * Parameters:
- * - char* buffer: pointer to the trace data buffer, allocated by the caller.
- *
-*******************************************************************************/
-void prvPagedEventBufferInit(char* buffer)
-{
- int i;
- TRACE_ALLOC_CRITICAL_SECTION();
-
- EventBuffer = buffer;
-
- TRACE_ENTER_CRITICAL_SECTION();
- for (i = 0; i < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT); i++)
- {
- PageInfo[i].BytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE);
- PageInfo[i].WritePointer = &EventBuffer[i * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)];
- PageInfo[i].Status = PAGE_STATUS_FREE;
- }
- TRACE_EXIT_CRITICAL_SECTION();
-
-}
-
-#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
-
-#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
+/******************************************************************************* + * Trace Recorder Library for Tracealyzer v4.3.11 + * Percepio AB, www.percepio.com + * + * trcStreamingRecorder.c + * + * The generic core of the trace recorder's streaming mode. + * + * Terms of Use + * This file is part of the trace recorder library (RECORDER), which is the + * intellectual property of Percepio AB (PERCEPIO) and provided under a + * license as follows. + * The RECORDER may be used free of charge for the purpose of recording data + * intended for analysis in PERCEPIO products. It may not be used or modified + * for other purposes without explicit permission from PERCEPIO. + * You may distribute the RECORDER in its original source code form, assuming + * this text (terms of use, disclaimer, copyright notice) is unchanged. You are + * allowed to distribute the RECORDER with minor modifications intended for + * configuration or porting of the RECORDER, e.g., to allow using it on a + * specific processor, processor family or with a specific communication + * interface. Any such modifications should be documented directly below + * this comment block. + * + * Disclaimer + * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty + * as to its use or performance. PERCEPIO does not and cannot warrant the + * performance or results you may obtain by using the RECORDER or documentation. + * PERCEPIO 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, 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 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. + * + * Tabs are used for indent in this file (1 tab = 4 spaces) + * + * Copyright Percepio AB, 2018. + * www.percepio.com + ******************************************************************************/ + +#include "trcRecorder.h" + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#include <stdio.h> +#include <string.h> +#include <stdarg.h> + +#include "trcExtensions.h" + +uint32_t trcHeapCounter = 0; + +typedef struct{ + uint16_t EventID; + uint16_t EventCount; + uint32_t TS; +} BaseEvent; + +typedef struct{ + BaseEvent base; + uint32_t param1; +} EventWithParam_1; + +typedef struct{ + BaseEvent base; + uint32_t param1; + uint32_t param2; +} EventWithParam_2; + +typedef struct{ + BaseEvent base; + uint32_t param1; + uint32_t param2; + uint32_t param3; +} EventWithParam_3; + +typedef struct{ + BaseEvent base; + uint32_t param1; + uint32_t param2; + uint32_t param3; + uint32_t param4; +} EventWithParam_4; + +typedef struct{ + BaseEvent base; + uint32_t param1; + uint32_t param2; + uint32_t param3; + uint32_t param4; + uint32_t param5; +} EventWithParam_5; + +/* Used in event functions with variable number of parameters. */ +typedef struct +{ + BaseEvent base; + uint32_t data[15]; /* maximum payload size */ +} largestEventType; + +typedef struct{ + uint32_t psf; + uint16_t version; + uint16_t platform; + uint32_t options; + uint32_t heapCounter; + uint16_t symbolSize; + uint16_t symbolCount; + uint16_t objectDataSize; + uint16_t objectDataCount; +} PSFHeaderInfo; + + +/* The size of each slot in the Symbol Table */ +#define SYMBOL_TABLE_SLOT_SIZE (sizeof(uint32_t) + (((TRC_CFG_SYMBOL_MAX_LENGTH)+(sizeof(uint32_t)-1))/sizeof(uint32_t))*sizeof(uint32_t)) + +#define OBJECT_DATA_SLOT_SIZE (sizeof(uint32_t) + sizeof(uint32_t)) + +/* The total size of the Symbol Table */ +#define SYMBOL_TABLE_BUFFER_SIZE ((TRC_CFG_SYMBOL_TABLE_SLOTS) * SYMBOL_TABLE_SLOT_SIZE) + +/* The total size of the Object Data Table */ +#define OBJECT_DATA_TABLE_BUFFER_SIZE ((TRC_CFG_OBJECT_DATA_SLOTS) * OBJECT_DATA_SLOT_SIZE) + +#if (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT > 128) +#error "TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT cannot be larger than 128" +#endif /* (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT > 128) */ + +/* The Symbol Table type - just a byte array */ +typedef struct{ + union + { + uint32_t pSymbolTableBufferUINT32[SYMBOL_TABLE_BUFFER_SIZE / sizeof(uint32_t)]; + uint8_t pSymbolTableBufferUINT8[SYMBOL_TABLE_BUFFER_SIZE]; + } SymbolTableBuffer; +} SymbolTable; + +/* The Object Data Table type - just a byte array */ +typedef struct{ + union + { + uint32_t pObjectDataTableBufferUINT32[OBJECT_DATA_TABLE_BUFFER_SIZE / sizeof(uint32_t)]; + uint8_t pObjectDataTableBufferUINT8[OBJECT_DATA_TABLE_BUFFER_SIZE]; + } ObjectDataTableBuffer; +} ObjectDataTable; + +typedef struct{ + uint16_t Status; /* 16 bit to avoid implicit padding (warnings) */ + uint16_t BytesRemaining; + char* WritePointer; +} PageType; + +/* Code used for "task address" when no task has started, to indicate "(startup)". + * This value was used since NULL/0 was already reserved for the idle task. */ +#define HANDLE_NO_TASK 2 + +/* The status codes for the pages of the internal trace buffer. */ +#define PAGE_STATUS_FREE 0 +#define PAGE_STATUS_WRITE 1 +#define PAGE_STATUS_READ 2 + +/* Calls prvTraceError if the _assert condition is false. For void functions, +where no return value is to be provided. */ +#define PSF_ASSERT_VOID(_assert, _err) if (! (_assert)){ prvTraceError(_err); return; } + +/* Calls prvTraceError if the _assert condition is false. For non-void functions, +where a return value is to be provided. */ +#define PSF_ASSERT_RET(_assert, _err, _return) if (! (_assert)){ prvTraceError(_err); return _return; } + +/* Part of the PSF format - encodes the number of 32-bit params in an event */ +#define PARAM_COUNT(n) ((n & 0xF) << 12) + +/* We skip the slot for PSF_ERROR_NONE so error code 1 is the first bit */ +#define GET_ERROR_WARNING_FLAG(errCode) (ErrorAndWarningFlags & (1 << ((errCode) - 1))) +#define SET_ERROR_WARNING_FLAG(errCode) (ErrorAndWarningFlags |= (1 << ((errCode) - 1))) + +/* Used for flags indicating if a certain error or warning has occurred */ +static uint32_t ErrorAndWarningFlags = 0; + +/* The Symbol Table instance - keeps names of tasks and other named objects. */ +static SymbolTable symbolTable = { { { 0 } } }; + +/* This points to the first unused entry in the symbol table. */ +static uint32_t firstFreeSymbolTableIndex = 0; + +/* The Object Data Table instance - keeps initial priorities of tasks. */ +static ObjectDataTable objectDataTable = { { { 0 } } }; + +/* This points to the first unused entry in the object data table. */ +static uint32_t firstFreeObjectDataTableIndex = 0; + +/* Keeps track of ISR nesting */ +static uint32_t ISR_stack[TRC_CFG_MAX_ISR_NESTING]; + +/* Keeps track of ISR nesting */ +static int8_t ISR_stack_index = -1; + +/* Any error that occurred in the recorder (also creates User Event) */ +static int errorCode = PSF_ERROR_NONE; + +/* Counts the number of trace sessions (not yet used) */ +static uint32_t SessionCounter = 0u; + +/* Master switch for recording (0 => Disabled, 1 => Enabled) */ +uint32_t RecorderEnabled = 0u; + +/* Used to determine endian of data (big/little) */ +static uint32_t PSFEndianessIdentifier = 0x50534600; + +/* Used to interpret the data format */ +static uint16_t FormatVersion = 0x0006; + +/* The number of events stored. Used as event sequence number. */ +static uint32_t eventCounter = 0; + +/* Remembers if an earlier ISR in a sequence of adjacent ISRs has triggered a task switch. +In that case, vTraceStoreISREnd does not store a return to the previously executing task. */ +int32_t isPendingContextSwitch = 0; + +uint32_t uiTraceTickCount = 0; +uint32_t timestampFrequency = 0; +uint32_t DroppedEventCounter = 0; +uint32_t TotalBytesRemaining_LowWaterMark = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE); +uint32_t TotalBytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT) * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE); + +PageType PageInfo[TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT]; + +char* EventBuffer = NULL; + +PSFExtensionInfoType PSFExtensionInfo = TRC_EXTENSION_INFO; + +/******************************************************************************* + * NoRoomForSymbol + * + * Incremented on prvTraceSaveSymbol if no room for saving the symbol name. This + * is used for storing the names of: + * - Tasks + * - Named ISRs (xTraceSetISRProperties) + * - Named kernel objects (vTraceStoreKernelObjectName) + * - User event channels (xTraceRegisterString) + * + * This variable should be zero. If not, it shows the number of missing slots so + * far. In that case, increment SYMBOL_TABLE_SLOTS with (at least) this value. + ******************************************************************************/ +volatile uint32_t NoRoomForSymbol = 0; + +/******************************************************************************* + * NoRoomForObjectData + * + * Incremented on prvTraceSaveObjectData if no room for saving the object data, + * i.e., the base priorities of tasks. There must be one slot for each task. + * If not, this variable will show the difference. + * + * This variable should be zero. If not, it shows the number of missing slots so + * far. In that case, increment OBJECT_DATA_SLOTS with (at least) this value. + ******************************************************************************/ +volatile uint32_t NoRoomForObjectData = 0; + +/******************************************************************************* + * LongestSymbolName + * + * Updated in prvTraceSaveSymbol. Should not exceed TRC_CFG_SYMBOL_MAX_LENGTH, + * otherwise symbol names will be truncated. In that case, set + * TRC_CFG_SYMBOL_MAX_LENGTH to (at least) this value. + ******************************************************************************/ +volatile uint32_t LongestSymbolName = 0; + +/******************************************************************************* + * MaxBytesTruncated + * + * Set in prvTraceStoreStringEvent if the total data payload exceeds 60 bytes, + * including data arguments and the string. For user events, that is 52 bytes + * for string and data arguments. In that is exceeded, the event is truncated + * (usually only the string, unless more than 15 parameters) and this variable + * holds the maximum number of truncated bytes, from any event. + ******************************************************************************/ +volatile uint32_t MaxBytesTruncated = 0; + +uint16_t CurrentFilterMask = 0xFFFF; + +uint16_t CurrentFilterGroup = FilterGroup0; + +volatile uint32_t uiTraceSystemState = TRC_STATE_IN_STARTUP; + +/* Internal common function for storing string events */ +static void prvTraceStoreStringEventHelper( int nArgs, + uint16_t eventID, + traceString userEvtChannel, + int len, + const char* str, + va_list vl); + +/* Not static to avoid warnings from SysGCC/PPC */ +void prvTraceStoreSimpleStringEventHelper(uint16_t eventID, + traceString userEvtChannel, + const char* str); + +/* Stores the header information on Start */ +static void prvTraceStoreHeader(void); + +/* Stores the Start Event */ +static void prvTraceStoreStartEvent(void); + +/* Stores the symbol table on Start */ +static void prvTraceStoreSymbolTable(void); + +/* Stores the object table on Start */ +static void prvTraceStoreObjectDataTable(void); + +/* Store the Timestamp Config on Start */ +static void prvTraceStoreTSConfig(void); + +/* Store information about trace library extensions. */ +static void prvTraceStoreExtensionInfo(void); + +/* Internal function for starting/stopping the recorder. */ +static void prvSetRecorderEnabled(uint32_t isEnabled); + +/* Mark the page read as complete. */ +static void prvPageReadComplete(int pageIndex); + +/* Retrieve a buffer page to write to. */ +static int prvAllocateBufferPage(int prevPage); + +/* Get the current buffer page index (return value) and the number +of valid bytes in the buffer page (bytesUsed). */ +static int prvGetBufferPage(int32_t* bytesUsed); + +/* Performs timestamping using definitions in trcHardwarePort.h */ +static uint32_t prvGetTimestamp32(void); + +/* Returns the string associated with the error code */ +static const char* prvTraceGetError(int errCode); + +/* Signal an error. */ +void prvTraceError(int errCode); + +/* Signal a warning (does not stop the recorder). */ +void prvTraceWarning(int errCode); + +/****************************************************************************** + * vTraceInstanceFinishedNow + * + * Creates an event that ends the current task instance at this very instant. + * This makes the viewer to splits the current fragment at this point and begin + * a new actor instance, even if no task-switch has occurred. + *****************************************************************************/ +void vTraceInstanceFinishedNow(void) +{ + prvTraceStoreEvent0(PSF_EVENT_IFE_DIRECT); +} + +/****************************************************************************** + * vTraceInstanceFinishedNext + * + * Marks the current "task instance" as finished on the next kernel call. + * + * If that kernel call is blocking, the instance ends after the blocking event + * and the corresponding return event is then the start of the next instance. + * If the kernel call is not blocking, the viewer instead splits the current + * fragment right before the kernel call, which makes this call the first event + * of the next instance. + *****************************************************************************/ +void vTraceInstanceFinishedNext(void) +{ + prvTraceStoreEvent0(PSF_EVENT_IFE_NEXT); +} + +/******************************************************************************* + * vTraceStoreKernelObjectName + * + * Parameter object: pointer to the Event Group that shall be named + * Parameter name: the name to set (const string literal) + * + * Sets a name for a kernel object for display in Tracealyzer. + ******************************************************************************/ +void vTraceStoreKernelObjectName(void* object, const char* name) +{ + uint16_t eventID = PSF_EVENT_OBJ_NAME; + + PSF_ASSERT_VOID(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE); + + /* Always save in symbol table, in case the recording has not yet started */ + prvTraceSaveObjectSymbol(object, name); + + prvTraceStoreStringEvent(1, eventID, name, object); +} + + +/****************************************************************************** +* vTraceSetFrequency +* +* Registers the clock rate of the time source for the event timestamping. +* This is normally not required, but if the default value (TRC_HWTC_FREQ_HZ) +* should be incorrect for your setup, you can override it using this function. +* +* Must be called prior to vTraceEnable, and the time source is assumed to +* have a fixed clock frequency after the startup. +*****************************************************************************/ +void vTraceSetFrequency(uint32_t frequency) +{ + timestampFrequency = frequency; +} + +#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) + +/******************************************************************************* +* xTraceRegisterString +* +* Stores a name for a user event channel, returns the handle. +******************************************************************************/ +traceString xTraceRegisterString(const char* name) +{ + traceString str; + uint16_t eventID = PSF_EVENT_OBJ_NAME; + + str = prvTraceSaveSymbol(name); + + PSF_ASSERT_RET(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE, str); + + /* Always save in symbol table, if the recording has not yet started */ + prvTraceStoreStringEvent(1, eventID, (const char*)name, str); + + return str; +} + +/****************************************************************************** + * vTracePrint + * + * Generates "User Events", with unformatted text. + * + * User Events can be used for very efficient application logging, and are shown + * as yellow labels in the main trace view. + * + * You may group User Events into User Event Channels. The yellow User Event + * labels shows the logged string, preceded by the channel name within + * brackets. For example: + * + * "[MyChannel] Hello World!" + * + * The User Event Channels are shown in the View Filter, which makes it easy to + * select what User Events you wish to display. User Event Channels are created + * using xTraceRegisterString(). + * + * Example: + * + * traceString chn = xTraceRegisterString("MyChannel"); + * ... + * vTracePrint(chn, "Hello World!"); + * + ******************************************************************************/ +void vTracePrint(traceString chn, const char* str) +{ + uint16_t eventID = PSF_EVENT_USER_EVENT; + PSF_ASSERT_VOID(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE); + + prvTraceStoreSimpleStringEventHelper(eventID, chn, str); +} + +/******************************************************************************* +* vTraceConsoleChannelPrintF +* +* Wrapper for vTracePrint, using the default channel. Can be used as a drop-in +* replacement for printf and similar functions, e.g. in a debug logging macro. +* +* Example: +* +* // Old: #define LogString debug_console_printf +* +* // New, log to Tracealyzer instead: +* #define LogString vTraceConsoleChannelPrintF +* ... +* LogString("My value is: %d", myValue); +******************************************************************************/ +void vTraceConsoleChannelPrintF(const char* fmt, ...) +{ + va_list vl; + char tempBuf[60]; + static traceString consoleChannel = NULL; + + if (consoleChannel == NULL) + consoleChannel = xTraceRegisterString("Debug Console"); + + va_start(vl, fmt); + vsnprintf(tempBuf, 60, fmt, vl); + vTracePrint(consoleChannel, tempBuf); + va_end(vl); +} + +/****************************************************************************** + * vTracePrintF + * + * Generates "User Events", with formatted text and data, similar to a "printf". + * It is very fast since the actual formatting is done on the host side when the + * trace is displayed. + * + * User Events can be used for very efficient application logging, and are shown + * as yellow labels in the main trace view. + * An advantage of User Events is that data can be plotted in the "User Event + * Signal Plot" view, visualizing any data you log as User Events, discrete + * states or control system signals (e.g. system inputs or outputs). + * + * You may group User Events into User Event Channels. The yellow User Event + * labels show the logged string, preceded by the channel name within brackets. + * + * Example: + * + * "[MyChannel] Hello World!" + * + * The User Event Channels are shown in the View Filter, which makes it easy to + * select what User Events you wish to display. User Event Channels are created + * using xTraceRegisterString(). + * + * Example: + * + * traceString adc_uechannel = xTraceRegisterString("ADC User Events"); + * ... + * vTracePrintF(adc_uechannel, + * "ADC channel %d: %d volts", + * ch, adc_reading); + * + * All data arguments are assumed to be 32 bit wide. The following formats are + * supported: + * %d - signed integer. The following width and padding format is supported: "%05d" -> "-0042" and "%5d" -> " -42" + * %u - unsigned integer. The following width and padding format is supported: "%05u" -> "00042" and "%5u" -> " 42" + * %X - hexadecimal (uppercase). The following width and padding format is supported: "%04X" -> "002A" and "%4X" -> " 2A" + * %x - hexadecimal (lowercase). The following width and padding format is supported: "%04x" -> "002a" and "%4x" -> " 2a" + * %s - string (currently, this must be an earlier stored symbol name) + * + * Up to 15 data arguments are allowed, with a total size of maximum 60 byte + * including 8 byte for the base event fields and the format string. So with + * one data argument, the maximum string length is 48 chars. If this is exceeded + * the string is truncated (4 bytes at a time). + * + ******************************************************************************/ +void vTracePrintF(traceString chn, const char* fmt, ...) +{ + va_list vl; + + va_start(vl, fmt); + vTraceVPrintF(chn, fmt, vl); + va_end(vl); +} + +/****************************************************************************** + * vTraceVPrintF + * + * vTracePrintF variant that accepts a va_list. + * See vTracePrintF documentation for further details. + * + ******************************************************************************/ +void vTraceVPrintF(traceString chn, const char* fmt, va_list vl) +{ + int i = 0; + int nArgs = 0; + int eventID = PSF_EVENT_USER_EVENT; + + /* Count the number of arguments in the format string (e.g., %d) */ + for (i = 0; (fmt[i] != 0) && (i < 52); i++) + { + if (fmt[i] == '%') + { + if (fmt[i + 1] == 0) + { + /* Found end of string, let for loop detect it */ + continue; + } + + if (fmt[i + 1] != '%') + { + nArgs++; /* Found an argument */ + } + + i++; /* Move past format specifier or non-argument '%' */ + } + } + + if (chn != NULL) + { + /* Make room for the channel */ + nArgs++; + } + eventID += nArgs; + + PSF_ASSERT_VOID(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE); + + prvTraceStoreStringEventHelper(nArgs, (uint16_t)eventID, chn, i, fmt, vl); +} +#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) */ + +/******************************************************************************* + * xTraceSetISRProperties + * + * Stores a name and priority level for an Interrupt Service Routine, to allow + * for better visualization. Returns a traceHandle used by vTraceStoreISRBegin. + * + * Example: + * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt + * ... + * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1); + * ... + * void ISR_handler() + * { + * vTraceStoreISRBegin(Timer1Handle); + * ... + * vTraceStoreISREnd(0); + * } + * + ******************************************************************************/ +traceHandle xTraceSetISRProperties(const char* name, uint8_t priority) +{ + traceHandle isrHandle; + uint16_t eventID = PSF_EVENT_DEFINE_ISR; + + /* Always save in symbol table, in case the recording has not yet started */ + isrHandle = prvTraceSaveSymbol(name); + + /* Save object data in object data table */ + prvTraceSaveObjectData((void*)isrHandle, priority); + + PSF_ASSERT_RET(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE, isrHandle); + + prvTraceStoreStringEvent(2, eventID, name, isrHandle, priority); + + return isrHandle; +} + +/******************************************************************************* + * vTraceStoreISRBegin + * + * Registers the beginning of an Interrupt Service Routine, using a traceHandle + * provided by xTraceSetISRProperties. + * + * Example: + * #define PRIO_ISR_TIMER1 3 // the hardware priority of the interrupt + * ... + * traceHandle Timer1Handle = xTraceSetISRProperties("ISRTimer1", PRIO_ISR_TIMER1); + * ... + * void ISR_handler() + * { + * vTraceStoreISRBegin(Timer1Handle); + * ... + * vTraceStoreISREnd(0); + * } + * + ******************************************************************************/ +void vTraceStoreISRBegin(traceHandle handle) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + /* We are at the start of a possible ISR chain. + No context switches should have been triggered now. */ + if (ISR_stack_index == -1) + isPendingContextSwitch = 0; + + if (ISR_stack_index < (TRC_CFG_MAX_ISR_NESTING) - 1) + { + ISR_stack_index++; + ISR_stack[ISR_stack_index] = (uint32_t)handle; +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) + prvTraceStoreEvent1(PSF_EVENT_ISR_BEGIN, (uint32_t)handle); +#endif + TRACE_EXIT_CRITICAL_SECTION(); + } + else + { + TRACE_EXIT_CRITICAL_SECTION(); + prvTraceError(PSF_ERROR_ISR_NESTING_OVERFLOW); + } +} + +/******************************************************************************* + * vTraceStoreISREnd + * + * Registers the end of an Interrupt Service Routine. + * + * The parameter pendingISR indicates if the interrupt has requested a + * task-switch (= 1), e.g., by signaling a semaphore. Otherwise (= 0) the + * interrupt is assumed to return to the previous context. + * + * Example: + * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt + * traceHandle traceHandleIsrTimer1 = 0; // The ID set by the recorder + * ... + * traceHandleIsrTimer1 = xTraceSetISRProperties("ISRTimer1", PRIO_OF_ISR_TIMER1); + * ... + * void ISR_handler() + * { + * vTraceStoreISRBegin(traceHandleIsrTimer1); + * ... + * vTraceStoreISREnd(0); + * } + * + ******************************************************************************/ +void vTraceStoreISREnd(int isTaskSwitchRequired) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + (void)ISR_stack; + + /* Is there a pending task-switch? (perhaps from an earlier ISR) */ + isPendingContextSwitch |= isTaskSwitchRequired; + + if (ISR_stack_index > 0) + { + ISR_stack_index--; + +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) + /* Store return to interrupted ISR (if nested ISRs)*/ + prvTraceStoreEvent1(PSF_EVENT_ISR_RESUME, (uint32_t)ISR_stack[ISR_stack_index]); +#endif + } + else + { + ISR_stack_index--; + + /* Store return to interrupted task, if no context switch will occur in between. */ + if ((isPendingContextSwitch == 0) || (prvTraceIsSchedulerSuspended())) + { +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) + prvTraceStoreEvent1(PSF_EVENT_TS_RESUME, (uint32_t)TRACE_GET_CURRENT_TASK()); +#endif + } + } + + TRACE_EXIT_CRITICAL_SECTION(); +} + +/******************************************************************************* + * xTraceGetLastError + * + * Returns the last error or warning, as a string, or NULL if none. + *****************************************************************************/ +const char* xTraceGetLastError(void) +{ + return prvTraceGetError(errorCode); +} + +/******************************************************************************* + * vTraceClearError + * + * Clears any errors. + *****************************************************************************/ +void vTraceClearError(void) +{ + NoRoomForSymbol = 0; + LongestSymbolName = 0; + NoRoomForObjectData = 0; + MaxBytesTruncated = 0; + errorCode = PSF_ERROR_NONE; +} + +/******************************************************************************* + * vTraceStop + * + * Stops the tracing. + *****************************************************************************/ +void vTraceStop(void) +{ + prvSetRecorderEnabled(0); +} + +/******************************************************************************* + * vTraceSetRecorderDataBuffer + * + * If custom allocation is used, this function must be called so the recorder + * library knows where to save the trace data. + ******************************************************************************/ +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) + +extern char* _TzTraceData; + +void vTraceSetRecorderDataBuffer(void* pRecorderData) +{ + _TzTraceData = pRecorderData; +} +#endif + + +/******************************************************************************* +* xTraceIsRecordingEnabled +* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0. +******************************************************************************/ +int xTraceIsRecordingEnabled(void) +{ + return (int)RecorderEnabled; +} + +void vTraceSetFilterMask(uint16_t filterMask) +{ + CurrentFilterMask = filterMask; +} + +void vTraceSetFilterGroup(uint16_t filterGroup) +{ + CurrentFilterGroup = filterGroup; +} + + +/******************************************************************************/ +/*** INTERNAL FUNCTIONS *******************************************************/ +/******************************************************************************/ + +/* Internal function for starting/stopping the recorder. */ +static void prvSetRecorderEnabled(uint32_t isEnabled) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + if (RecorderEnabled == isEnabled) + { + return; + } + + TRACE_ENTER_CRITICAL_SECTION(); + + if (isEnabled) + { + TRC_STREAM_PORT_ON_TRACE_BEGIN(); + + #if (TRC_STREAM_PORT_USE_INTERNAL_BUFFER == 1) + prvPagedEventBufferInit(_TzTraceData); + #endif + + eventCounter = 0; + ISR_stack_index = -1; + prvTraceStoreHeader(); + prvTraceStoreSymbolTable(); + prvTraceStoreObjectDataTable(); + prvTraceStoreExtensionInfo(); + prvTraceStoreStartEvent(); + prvTraceStoreTSConfig(); + } + else + { + TRC_STREAM_PORT_ON_TRACE_END(); + } + + RecorderEnabled = isEnabled; + + TRACE_EXIT_CRITICAL_SECTION(); +} + +static void prvTraceStoreStartEvent() +{ + void* currentTask; + + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (uiTraceSystemState == TRC_STATE_IN_STARTUP) + { + currentTask = (void*)HANDLE_NO_TASK; + } + else + { + currentTask = TRACE_GET_CURRENT_TASK(); + } + + eventCounter++; + + { + TRC_STREAM_PORT_ALLOCATE_EVENT_BLOCKING(EventWithParam_3, pxEvent, sizeof(EventWithParam_3)); + if (pxEvent != NULL) + { + pxEvent->base.EventID = PSF_EVENT_TRACE_START | PARAM_COUNT(3); + pxEvent->base.EventCount = (uint16_t)eventCounter; + pxEvent->base.TS = prvGetTimestamp32(); + pxEvent->param1 = (uint32_t)TRACE_GET_OS_TICKS(); + pxEvent->param2 = (uint32_t)currentTask; + pxEvent->param3 = SessionCounter++; + TRC_STREAM_PORT_COMMIT_EVENT_BLOCKING(pxEvent, sizeof(EventWithParam_3)); + } + } + + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Store the Timestamp Config event */ +static void prvTraceStoreTSConfig(void) +{ + /* If not overridden using vTraceSetFrequency, use default value */ + if (timestampFrequency == 0) + { + timestampFrequency = TRC_HWTC_FREQ_HZ; + } + + eventCounter++; + + + { +#if (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR || TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR) + + TRC_STREAM_PORT_ALLOCATE_EVENT_BLOCKING(EventWithParam_5, event, sizeof(EventWithParam_5)); + if (event != NULL) + { + event->base.EventID = PSF_EVENT_TS_CONFIG | (uint16_t)PARAM_COUNT(5); + event->base.EventCount = (uint16_t)eventCounter; + event->base.TS = prvGetTimestamp32(); + + event->param1 = (uint32_t)timestampFrequency; + event->param2 = (uint32_t)(TRACE_TICK_RATE_HZ); + event->param3 = (uint32_t)(TRC_HWTC_TYPE); + event->param4 = (uint32_t)(TRC_CFG_ISR_TAILCHAINING_THRESHOLD); + event->param5 = (uint32_t)(TRC_HWTC_PERIOD); + TRC_STREAM_PORT_COMMIT_EVENT_BLOCKING(event, (uint32_t)sizeof(EventWithParam_5)); + } +#else + TRC_STREAM_PORT_ALLOCATE_EVENT_BLOCKING(EventWithParam_4, event, sizeof(EventWithParam_4)); + if (event != NULL) + { + event->base.EventID = PSF_EVENT_TS_CONFIG | (uint16_t)PARAM_COUNT(4); + event->base.EventCount = (uint16_t)eventCounter; + event->base.TS = prvGetTimestamp32(); + + event->param1 = (uint32_t)timestampFrequency; + event->param2 = (uint32_t)(TRACE_TICK_RATE_HZ); + event->param3 = (uint32_t)(TRC_HWTC_TYPE); + event->param4 = (uint32_t)(TRC_CFG_ISR_TAILCHAINING_THRESHOLD); + TRC_STREAM_PORT_COMMIT_EVENT_BLOCKING(event, (uint32_t)sizeof(EventWithParam_4)); + } +#endif + + } +} + +/* Stores the symbol table on Start */ +static void prvTraceStoreSymbolTable(void) +{ + uint32_t i = 0; + uint32_t j = 0; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + { + for (i = 0; i < (sizeof(SymbolTable) / sizeof(uint32_t)); i += (SYMBOL_TABLE_SLOT_SIZE / sizeof(uint32_t))) + { + TRC_STREAM_PORT_ALLOCATE_EVENT_BLOCKING(uint32_t, data, SYMBOL_TABLE_SLOT_SIZE); + + for (j = 0; j < (SYMBOL_TABLE_SLOT_SIZE / sizeof(uint32_t)); j++) + { + data[j] = symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT32[i+j]; + } + + TRC_STREAM_PORT_COMMIT_EVENT_BLOCKING(data, SYMBOL_TABLE_SLOT_SIZE); + } + } + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Stores the object table on Start */ +static void prvTraceStoreObjectDataTable(void) +{ + uint32_t i = 0; + uint32_t j = 0; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + { + for (i = 0; i < (sizeof(ObjectDataTable) / sizeof(uint32_t)); i += (OBJECT_DATA_SLOT_SIZE / sizeof(uint32_t))) + { + TRC_STREAM_PORT_ALLOCATE_EVENT_BLOCKING(uint32_t, data, OBJECT_DATA_SLOT_SIZE); + + for (j = 0; j < (OBJECT_DATA_SLOT_SIZE / sizeof(uint32_t)); j++) + { + data[j] = objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[i+j]; + } + + TRC_STREAM_PORT_COMMIT_EVENT_BLOCKING(data, OBJECT_DATA_SLOT_SIZE); + } + } + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Stores the header information on Start */ +static void prvTraceStoreHeader(void) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + { + TRC_STREAM_PORT_ALLOCATE_EVENT_BLOCKING(PSFHeaderInfo, header, sizeof(PSFHeaderInfo)); + header->psf = PSFEndianessIdentifier; + header->version = FormatVersion; + header->platform = TRACE_KERNEL_VERSION; + header->options = 0; + header->heapCounter = trcHeapCounter; + /* Lowest bit used for TRC_IRQ_PRIORITY_ORDER */ + header->options = header->options | (TRC_IRQ_PRIORITY_ORDER << 0); + header->symbolSize = SYMBOL_TABLE_SLOT_SIZE; + header->symbolCount = (TRC_CFG_SYMBOL_TABLE_SLOTS); + header->objectDataSize = 8; + header->objectDataCount = (TRC_CFG_OBJECT_DATA_SLOTS); + TRC_STREAM_PORT_COMMIT_EVENT_BLOCKING(header, sizeof(PSFHeaderInfo)); + } + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Stores the header information on Start */ +static void prvTraceStoreExtensionInfo(void) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + { + TRC_STREAM_PORT_ALLOCATE_EVENT_BLOCKING(PSFExtensionInfoType, extinfo, sizeof(PSFExtensionInfoType)); + memcpy(extinfo, &PSFExtensionInfo, sizeof(PSFExtensionInfoType)); + TRC_STREAM_PORT_COMMIT_EVENT_BLOCKING(extinfo, sizeof(PSFExtensionInfoType)); + } + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Returns the error or warning, as a string, or NULL if none. */ +static const char* prvTraceGetError(int errCode) +{ + /* Note: the error messages are short, in order to fit in a User Event. + Instead, the users can read more in the below comments.*/ + + switch (errCode) + { + + case PSF_WARNING_SYMBOL_TABLE_SLOTS: + /* There was not enough symbol table slots for storing symbol names. + The number of missing slots is counted by NoRoomForSymbol. Inspect this + variable and increase TRC_CFG_SYMBOL_TABLE_SLOTS by at least that value. */ + + return "Exceeded SYMBOL_TABLE_SLOTS (see prvTraceGetError)"; + + case PSF_WARNING_SYMBOL_MAX_LENGTH: + /* A symbol name exceeded TRC_CFG_SYMBOL_MAX_LENGTH in length. + Make sure the symbol names are at most TRC_CFG_SYMBOL_MAX_LENGTH, + or inspect LongestSymbolName and increase TRC_CFG_SYMBOL_MAX_LENGTH + to at least this value. */ + + return "Exceeded SYMBOL_MAX_LENGTH (see prvTraceGetError)"; + + case PSF_WARNING_OBJECT_DATA_SLOTS: + /* There was not enough symbol object table slots for storing object + properties, such as task priorites. The number of missing slots is + counted by NoRoomForObjectData. Inspect this variable and increase + TRC_CFG_OBJECT_DATA_SLOTS by at least that value. */ + + return "Exceeded OBJECT_DATA_SLOTS (see prvTraceGetError)"; + + case PSF_WARNING_STRING_TOO_LONG: + /* Some string argument was longer than the maximum payload size + and has been truncated by "MaxBytesTruncated" bytes. + + This may happen for the following functions: + - vTracePrint + - vTracePrintF + - vTraceStoreKernelObjectName + - xTraceRegisterString + - vTraceSetISRProperties + + A PSF event may store maximum 60 bytes payload, including data + arguments and string characters. For User Events, also the User + Event Channel (4 bytes) must be squeezed in, if a channel is + specified (can be NULL). */ + + return "String too long (see prvTraceGetError)"; + + case PSF_WARNING_STREAM_PORT_READ: + /* TRC_STREAM_PORT_READ_DATA is expected to return 0 when completed successfully. + This means there is an error in the communication with host/Tracealyzer. */ + + return "TRC_STREAM_PORT_READ_DATA returned error (!= 0)."; + + case PSF_WARNING_STREAM_PORT_WRITE: + /* TRC_STREAM_PORT_WRITE_DATA is expected to return 0 when completed successfully. + This means there is an error in the communication with host/Tracealyzer. */ + + return "TRC_STREAM_PORT_WRITE_DATA returned error (!= 0)."; + + case PSF_WARNING_STACKMON_NO_SLOTS: + /* TRC_CFG_STACK_MONITOR_MAX_TASKS is too small to monitor all tasks. */ + + return "TRC_CFG_STACK_MONITOR_MAX_TASKS too small!"; + + case PSF_WARNING_STREAM_PORT_INITIAL_BLOCKING: + /* Blocking occurred during vTraceEnable. This happens if the trace buffer is + smaller than the initial transmission (trace header, object table, and symbol table). */ + + return "Blocking in vTraceEnable (see xTraceGetLastError)"; + + case PSF_ERROR_EVENT_CODE_TOO_LARGE: + /* The highest allowed event code is 4095, anything higher is an unexpected error. + Please contact support@percepio.com for assistance.*/ + + return "Invalid event code (see prvTraceGetError)"; + + case PSF_ERROR_ISR_NESTING_OVERFLOW: + /* Nesting of ISR trace calls exceeded the limit (TRC_CFG_MAX_ISR_NESTING). + If this is unlikely, make sure that you call vTraceStoreISRExit in the end + of all ISR handlers. Or increase TRC_CFG_MAX_ISR_NESTING. */ + + return "Exceeded ISR nesting (see prvTraceGetError)"; + + case PSF_ERROR_DWT_NOT_SUPPORTED: + /* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip. + DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M + macro normally set by ARM's CMSIS library, since typically available. You can however select + SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/ + + return "DWT not supported (see prvTraceGetError)"; + + case PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED: + /* On ARM Cortex-M only - failed to initialize DWT Cycle Counter since not supported by this chip. + DWT timestamping is selected automatically for ART Cortex-M3, M4 and higher, based on the __CORTEX_M + macro normally set by ARM's CMSIS library, since typically available. You can however select + SysTick timestamping instead by defining adding "#define TRC_CFG_ARM_CM_USE_SYSTICK".*/ + + return "DWT_CYCCNT not supported (see prvTraceGetError)"; + + case PSF_ERROR_TZCTRLTASK_NOT_CREATED: + /* vTraceEnable failed creating the trace control task (TzCtrl) - incorrect parameters (priority?) + or insufficient heap size? */ + return "Could not create TzCtrl (see prvTraceGetError)"; + + case PSF_ERROR_STREAM_PORT_WRITE: + /* TRC_STREAM_PORT_WRITE_DATA is expected to return 0 when completed successfully. + This means there is an error in the communication with host/Tracealyzer. */ + return "TRC_STREAM_PORT_WRITE_DATA returned error (!= 0)."; + } + + return NULL; +} + +/* Store an event with zero parameters (event ID only) */ +void prvTraceStoreEvent0(uint16_t eventID) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + PSF_ASSERT_VOID(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (RecorderEnabled) + { + eventCounter++; + + { + TRC_STREAM_PORT_ALLOCATE_EVENT(BaseEvent, event, sizeof(BaseEvent)); + if (event != NULL) + { + event->EventID = eventID | PARAM_COUNT(0); + event->EventCount = (uint16_t)eventCounter; + event->TS = prvGetTimestamp32(); + TRC_STREAM_PORT_COMMIT_EVENT(event, sizeof(BaseEvent)); + } + } + } + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Store an event with one 32-bit parameter (pointer address or an int) */ +void prvTraceStoreEvent1(uint16_t eventID, uint32_t param1) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + PSF_ASSERT_VOID(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (RecorderEnabled) + { + eventCounter++; + + { + TRC_STREAM_PORT_ALLOCATE_EVENT(EventWithParam_1, event, sizeof(EventWithParam_1)); + if (event != NULL) + { + event->base.EventID = eventID | PARAM_COUNT(1); + event->base.EventCount = (uint16_t)eventCounter; + event->base.TS = prvGetTimestamp32(); + event->param1 = (uint32_t)param1; + TRC_STREAM_PORT_COMMIT_EVENT(event, sizeof(EventWithParam_1)); + } + } + } + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Store an event with two 32-bit parameters */ +void prvTraceStoreEvent2(uint16_t eventID, uint32_t param1, uint32_t param2) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + PSF_ASSERT_VOID(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (RecorderEnabled) + { + eventCounter++; + + { + TRC_STREAM_PORT_ALLOCATE_EVENT(EventWithParam_2, event, sizeof(EventWithParam_2)); + if (event != NULL) + { + event->base.EventID = eventID | PARAM_COUNT(2); + event->base.EventCount = (uint16_t)eventCounter; + event->base.TS = prvGetTimestamp32(); + event->param1 = (uint32_t)param1; + event->param2 = param2; + TRC_STREAM_PORT_COMMIT_EVENT(event, sizeof(EventWithParam_2)); + } + } + } + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Store an event with three 32-bit parameters */ +void prvTraceStoreEvent3( uint16_t eventID, + uint32_t param1, + uint32_t param2, + uint32_t param3) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + PSF_ASSERT_VOID(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (RecorderEnabled) + { + eventCounter++; + + { + TRC_STREAM_PORT_ALLOCATE_EVENT(EventWithParam_3, event, sizeof(EventWithParam_3)); + if (event != NULL) + { + event->base.EventID = eventID | PARAM_COUNT(3); + event->base.EventCount = (uint16_t)eventCounter; + event->base.TS = prvGetTimestamp32(); + event->param1 = (uint32_t)param1; + event->param2 = param2; + event->param3 = param3; + TRC_STREAM_PORT_COMMIT_EVENT(event, sizeof(EventWithParam_3)); + } + } + } + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Stores an event with <nParam> 32-bit integer parameters */ +void prvTraceStoreEvent(int nParam, uint16_t eventID, ...) +{ + va_list vl; + int i; + TRACE_ALLOC_CRITICAL_SECTION(); + + PSF_ASSERT_VOID(eventID < 4096, PSF_ERROR_EVENT_CODE_TOO_LARGE); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (RecorderEnabled) + { + int eventSize = (int)sizeof(BaseEvent) + nParam * (int)sizeof(uint32_t); + + eventCounter++; + + { + TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(largestEventType, event, eventSize); + if (event != NULL) + { + event->base.EventID = eventID | (uint16_t)PARAM_COUNT(nParam); + event->base.EventCount = (uint16_t)eventCounter; + event->base.TS = prvGetTimestamp32(); + + va_start(vl, eventID); + for (i = 0; i < nParam; i++) + { + uint32_t* tmp = (uint32_t*) &(event->data[i]); + *tmp = va_arg(vl, uint32_t); + } + va_end(vl); + + TRC_STREAM_PORT_COMMIT_EVENT(event, (uint32_t)eventSize); + } + } + } + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Stories an event with a string and <nParam> 32-bit integer parameters */ +void prvTraceStoreStringEvent(int nArgs, uint16_t eventID, const char* str, ...) +{ + int len; + va_list vl; + + for (len = 0; (str[len] != 0) && (len < 52); len++); /* empty loop */ + + va_start(vl, str); + prvTraceStoreStringEventHelper(nArgs, eventID, NULL, len, str, vl); + va_end(vl); +} + +/* Internal common function for storing string events */ +static void prvTraceStoreStringEventHelper(int nArgs, + uint16_t eventID, + traceString userEvtChannel, + int len, + const char* str, + va_list vl) +{ + int nWords; + int nStrWords; + int i; + int offset = 0; + TRACE_ALLOC_CRITICAL_SECTION(); + + /* The string length in multiples of 32 bit words (+1 for null character) */ + nStrWords = (len+1+3)/4; + + offset = nArgs * 4; + + /* The total number of 32-bit words needed for the whole payload */ + nWords = nStrWords + nArgs; + + if (nWords > 15) /* if attempting to store more than 60 byte (= max) */ + { + /* Truncate event if too large. The string characters are stored + last, so usually only the string is truncated, unless there a lot + of parameters... */ + + /* Diagnostics ... */ + uint32_t bytesTruncated = (uint32_t)(nWords - 15) * 4; + + if (bytesTruncated > MaxBytesTruncated) + { + MaxBytesTruncated = bytesTruncated; + } + + nWords = 15; + len = 15 * 4 - offset; + } + + TRACE_ENTER_CRITICAL_SECTION(); + + if (RecorderEnabled) + { + int eventSize = (int)sizeof(BaseEvent) + nWords * (int)sizeof(uint32_t); + + eventCounter++; + + { + TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(largestEventType, event, eventSize); + if (event != NULL) + { + uint32_t* data32; + uint8_t* data8; + event->base.EventID = (eventID) | (uint16_t)PARAM_COUNT(nWords); + event->base.EventCount = (uint16_t)eventCounter; + event->base.TS = prvGetTimestamp32(); + + /* 32-bit write-pointer for the data argument */ + data32 = (uint32_t*) &(event->data[0]); + + for (i = 0; i < nArgs; i++) + { + if ((userEvtChannel != NULL) && (i == 0)) + { + /* First, add the User Event Channel if not NULL */ + data32[i] = (uint32_t)userEvtChannel; + } + else + { + /* Add data arguments... */ + data32[i] = va_arg(vl, uint32_t); + } + } + data8 = (uint8_t*)&(event->data[0]); + for (i = 0; i < len; i++) + { + data8[offset + i] = str[i]; + } + + if (len < (15 * 4 - offset)) + data8[offset + len] = 0; /* Only truncate if we don't fill up the buffer completely */ + TRC_STREAM_PORT_COMMIT_EVENT(event, (uint32_t)eventSize); + } + } + } + + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Internal common function for storing string events without additional arguments */ +void prvTraceStoreSimpleStringEventHelper(uint16_t eventID, + traceString userEvtChannel, + const char* str) +{ + int len; + int nWords; + int nStrWords; + int i; + int nArgs = 0; + int offset = 0; + TRACE_ALLOC_CRITICAL_SECTION(); + + for (len = 0; (str[len] != 0) && (len < 52); len++); /* empty loop */ + + /* The string length in multiples of 32 bit words (+1 for null character) */ + nStrWords = (len+1+3)/4; + + /* If a user event channel is specified, add in the list */ + if (userEvtChannel) + { + nArgs++; + eventID++; + } + + offset = nArgs * 4; + + /* The total number of 32-bit words needed for the whole payload */ + nWords = nStrWords + nArgs; + + if (nWords > 15) /* if attempting to store more than 60 byte (= max) */ + { + /* Truncate event if too large. The string characters are stored + last, so usually only the string is truncated, unless there a lot + of parameters... */ + + /* Diagnostics ... */ + uint32_t bytesTruncated = (uint32_t)(nWords - 15) * 4; + + if (bytesTruncated > MaxBytesTruncated) + { + MaxBytesTruncated = bytesTruncated; + } + + nWords = 15; + len = 15 * 4 - offset; + } + + TRACE_ENTER_CRITICAL_SECTION(); + + if (RecorderEnabled) + { + int eventSize = (int)sizeof(BaseEvent) + nWords * (int)sizeof(uint32_t); + + eventCounter++; + + { + TRC_STREAM_PORT_ALLOCATE_DYNAMIC_EVENT(largestEventType, event, eventSize); + if (event != NULL) + { + uint32_t* data32; + uint8_t* data8; + event->base.EventID = (eventID) | (uint16_t)PARAM_COUNT(nWords); + event->base.EventCount = (uint16_t)eventCounter; + event->base.TS = prvGetTimestamp32(); + + /* 32-bit write-pointer for the data argument */ + data32 = (uint32_t*) &(event->data[0]); + + if (userEvtChannel != NULL) + { + /* First, add the User Event Channel if not NULL */ + data32[0] = (uint32_t)userEvtChannel; + } + + data8 = (uint8_t*) &(event->data[0]); + for (i = 0; i < len; i++) + { + data8[offset + i] = str[i]; + } + + if (len < (15 * 4 - offset)) + data8[offset + len] = 0; /* Only truncate if we don't fill up the buffer completely */ + TRC_STREAM_PORT_COMMIT_EVENT(event, (uint32_t)eventSize); + } + } + } + + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Saves a symbol name in the symbol table and returns the slot address */ +void* prvTraceSaveSymbol(const char *name) +{ + void* retVal = 0; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + if (firstFreeSymbolTableIndex < SYMBOL_TABLE_BUFFER_SIZE) + { + /* The address to the available symbol table slot is the address we use */ + retVal = &symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT8[firstFreeSymbolTableIndex]; + prvTraceSaveObjectSymbol(retVal, name); + } + TRACE_EXIT_CRITICAL_SECTION(); + + return retVal; +} + +/* Saves a string in the symbol table for an object (task name etc.) */ +void prvTraceSaveObjectSymbol(void* address, const char *name) +{ + uint32_t i; + uint8_t *ptrSymbol; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + /* We do not look for previous entries -> changing a registered string is no longer possible */ + if (firstFreeSymbolTableIndex < SYMBOL_TABLE_BUFFER_SIZE) + { + /* We access the symbol table via the union member pSymbolTableBufferUINT32 to avoid strict-aliasing issues */ + symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT32[firstFreeSymbolTableIndex / sizeof(uint32_t)] = (uint32_t)address; + + /* We access the symbol table via the union member pSymbolTableBufferUINT8 to avoid strict-aliasing issues */ + ptrSymbol = &symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT8[firstFreeSymbolTableIndex + sizeof(uint32_t)]; + for (i = 0; i < (TRC_CFG_SYMBOL_MAX_LENGTH); i++) + { + ptrSymbol[i] = (uint8_t)name[i]; /* We do this first to ensure we also get the 0 termination, if there is one */ + + if (name[i] == 0) + break; + } + + /* Check the length of "name", if longer than SYMBOL_MAX_LENGTH */ + while ((name[i] != 0) && i < 128) + { + i++; + } + + /* Remember the longest symbol name, for diagnostic purposes */ + if (i > LongestSymbolName) + { + LongestSymbolName = i; + } + + firstFreeSymbolTableIndex += SYMBOL_TABLE_SLOT_SIZE; + } + else + { + NoRoomForSymbol++; + } + + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Deletes a symbol name (task name etc.) from symbol table */ +void prvTraceDeleteSymbol(void *address) +{ + uint32_t i, j; + uint32_t *ptr, *lastEntryPtr; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + for (i = 0; i < firstFreeSymbolTableIndex; i += SYMBOL_TABLE_SLOT_SIZE) + { + /* We access the symbol table via the union member pSymbolTableBufferUINT32 to avoid strict-aliasing issues */ + ptr = &symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT32[i / sizeof(uint32_t)]; + if (*ptr == (uint32_t)address) + { + /* See if we have another entry in the table, and that this isn't already the last entry */ + if (firstFreeSymbolTableIndex > SYMBOL_TABLE_SLOT_SIZE && i != (firstFreeSymbolTableIndex - SYMBOL_TABLE_SLOT_SIZE)) + { + /* Another entry is available, get pointer to the last one */ + /* We access the symbol table via the union member pSymbolTableBufferUINT32 to avoid strict-aliasing issues */ + lastEntryPtr = &symbolTable.SymbolTableBuffer.pSymbolTableBufferUINT32[(firstFreeSymbolTableIndex - SYMBOL_TABLE_SLOT_SIZE) / sizeof(uint32_t)]; + + /* Copy last entry to this position */ + for (j = 0; j < (SYMBOL_TABLE_SLOT_SIZE) / sizeof(uint32_t); j++) + { + ptr[j] = lastEntryPtr[j]; + } + + /* For good measure we also zero out the original position */ + *lastEntryPtr = 0; + } + else + *ptr = 0; /* No other entry found, or this is the last entry */ + + /* Lower index */ + firstFreeSymbolTableIndex -= SYMBOL_TABLE_SLOT_SIZE; + + break; + } + } + + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Saves an object data entry (current task priority) in object data table */ +void prvTraceSaveObjectData(const void *address, uint32_t data) +{ + uint32_t i; + uint32_t foundSlot; + uint32_t *ptr; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + foundSlot = firstFreeObjectDataTableIndex; + + /* First look for previous entries using this address */ + for (i = 0; i < firstFreeObjectDataTableIndex; i += OBJECT_DATA_SLOT_SIZE) + { + /* We access the data table via the union member pObjectDataTableBufferUINT32 to avoid strict-aliasing issues */ + ptr = &objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[i / sizeof(uint32_t)]; + if (*ptr == (uint32_t)address) + { + foundSlot = i; + break; + } + } + + if (foundSlot < OBJECT_DATA_TABLE_BUFFER_SIZE) + { + /* We access the data table via the union member pObjectDataTableBufferUINT32 to avoid strict-aliasing issues */ + objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[foundSlot / sizeof(uint32_t)] = (uint32_t)address; + objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[foundSlot / sizeof(uint32_t) + 1] = data; + + /* Is this the last entry in the object data table? */ + if (foundSlot == firstFreeObjectDataTableIndex) + { + firstFreeObjectDataTableIndex += OBJECT_DATA_SLOT_SIZE; + } + } + else + { + NoRoomForObjectData++; + } + + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Removes an object data entry (task base priority) from object data table */ +void prvTraceDeleteObjectData(void *address) +{ + uint32_t i, j; + uint32_t *ptr, *lastEntryPtr; + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + for (i = 0; i < firstFreeObjectDataTableIndex; i += OBJECT_DATA_SLOT_SIZE) + { + /* We access the data table via the union member pObjectDataTableBufferUINT32 to avoid strict-aliasing issues */ + ptr = &objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[i / sizeof(uint32_t)]; + if (*ptr == (uint32_t)address) + { + /* See if we have another entry in the table, and that this isn't already the last entry */ + if (firstFreeObjectDataTableIndex > OBJECT_DATA_SLOT_SIZE && i != (firstFreeObjectDataTableIndex - OBJECT_DATA_SLOT_SIZE)) + { + /* Another entry is available, get pointer to the last one */ + /* We access the data table via the union member pObjectDataTableBufferUINT32 to avoid strict-aliasing issues */ + lastEntryPtr = &objectDataTable.ObjectDataTableBuffer.pObjectDataTableBufferUINT32[(firstFreeObjectDataTableIndex - OBJECT_DATA_SLOT_SIZE) / sizeof(uint32_t)]; + + /* Copy last entry to this position */ + for (j = 0; j < (OBJECT_DATA_SLOT_SIZE) / sizeof(uint32_t); j++) + { + ptr[j] = lastEntryPtr[j]; + } + + /* For good measure we also zero out the original position */ + *lastEntryPtr = 0; + } + else + *ptr = 0; /* No other entry found, or this is the last entry */ + + /* Lower index */ + firstFreeObjectDataTableIndex -= OBJECT_DATA_SLOT_SIZE; + + break; + } + } + + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Checks if the provided command is a valid command */ +int prvIsValidCommand(TracealyzerCommandType* cmd) +{ + uint16_t checksum = (uint16_t)(0xFFFF - ( cmd->cmdCode + + cmd->param1 + + cmd->param2 + + cmd->param3 + + cmd->param4 + + cmd->param5)); + + if (cmd->checksumMSB != (unsigned char)(checksum >> 8)) + return 0; + + if (cmd->checksumLSB != (unsigned char)(checksum & 0xFF)) + return 0; + + if (cmd->cmdCode > CMD_LAST_COMMAND) + return 0; + + return 1; +} + +/* Executed the received command (Start or Stop) */ +void prvProcessCommand(TracealyzerCommandType* cmd) +{ + switch(cmd->cmdCode) + { + case CMD_SET_ACTIVE: + prvSetRecorderEnabled(cmd->param1); + break; + default: + break; + } +} + +/* Called on warnings, when the recording can continue. */ +void prvTraceWarning(int errCode) +{ + if (GET_ERROR_WARNING_FLAG(errCode) == 0) + { + /* Will never reach this point more than once per warning type, since we verify if ErrorAndWarningFlags[errCode] has already been set */ + SET_ERROR_WARNING_FLAG(errCode); + + prvTraceStoreSimpleStringEventHelper(PSF_EVENT_USER_EVENT, trcWarningChannel, prvTraceGetError(errCode)); + } +} + +/* Called on critical errors in the recorder. Stops the recorder! */ +void prvTraceError(int errCode) +{ + if (errorCode == PSF_ERROR_NONE) + { + /* Will never reach this point more than once, since we verify if errorCode has already been set */ + errorCode = errCode; + SET_ERROR_WARNING_FLAG(errorCode); + + prvTraceStoreSimpleStringEventHelper(PSF_EVENT_USER_EVENT, trcWarningChannel, prvTraceGetError(errorCode)); + prvTraceStoreSimpleStringEventHelper(PSF_EVENT_USER_EVENT, trcWarningChannel, "Recorder stopped in prvTraceError()"); + + prvSetRecorderEnabled(0); + } +} + +/* If using DWT timestamping (default on ARM Cortex-M3, M4 and M7), make sure the DWT unit is initialized. */ +#ifndef TRC_CFG_ARM_CM_USE_SYSTICK +#if ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) && (defined (__CORTEX_M) && (__CORTEX_M >= 0x03))) + +void prvTraceInitCortexM() +{ + /* Make sure the DWT registers are unlocked, in case the debugger doesn't do this. */ + TRC_REG_ITM_LOCKACCESS = TRC_ITM_LOCKACCESS_UNLOCK; + + /* Make sure DWT is enabled is enabled, if supported */ + TRC_REG_DEMCR |= TRC_DEMCR_TRCENA; + + do + { + /* Verify that DWT is supported */ + if (TRC_REG_DEMCR == 0) + { + /* This function is called on Cortex-M3, M4 and M7 devices to initialize + the DWT unit, assumed present. The DWT cycle counter is used for timestamping. + + If the below error is produced, the DWT unit does not seem to be available. + + In that case, define the macro TRC_CFG_ARM_CM_USE_SYSTICK in your build + to use SysTick timestamping instead, or define your own timestamping by + setting TRC_CFG_HARDWARE_PORT to TRC_HARDWARE_PORT_APPLICATION_DEFINED + and make the necessary definitions, as explained in trcHardwarePort.h.*/ + + prvTraceError(PSF_ERROR_DWT_NOT_SUPPORTED); + break; + } + + /* Verify that DWT_CYCCNT is supported */ + if (TRC_REG_DWT_CTRL & TRC_DWT_CTRL_NOCYCCNT) + { + /* This function is called on Cortex-M3, M4 and M7 devices to initialize + the DWT unit, assumed present. The DWT cycle counter is used for timestamping. + + If the below error is produced, the cycle counter does not seem to be available. + + In that case, define the macro TRC_CFG_ARM_CM_USE_SYSTICK in your build + to use SysTick timestamping instead, or define your own timestamping by + setting TRC_CFG_HARDWARE_PORT to TRC_HARDWARE_PORT_APPLICATION_DEFINED + and make the necessary definitions, as explained in trcHardwarePort.h.*/ + + prvTraceError(PSF_ERROR_DWT_CYCCNT_NOT_SUPPORTED); + break; + } + + /* Reset the cycle counter */ + TRC_REG_DWT_CYCCNT = 0; + + /* Enable the cycle counter */ + TRC_REG_DWT_CTRL |= TRC_DWT_CTRL_CYCCNTENA; + + } while(0); /* breaks above jump here */ +} +#endif +#endif + +/* Performs timestamping using definitions in trcHardwarePort.h */ +static uint32_t prvGetTimestamp32(void) +{ +#if ((TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_INCR) || (TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_DECR)) + return TRC_HWTC_COUNT; +#endif + +#if ((TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR) || (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR)) + return TRC_HWTC_COUNT; +#endif + +#if ((TRC_HWTC_TYPE == TRC_OS_TIMER_INCR) || (TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)) + uint32_t ticks = TRACE_GET_OS_TICKS(); + return ((TRC_HWTC_COUNT) & 0x00FFFFFFU) + ((ticks & 0x000000FFU) << 24); +#endif +} + +/* Retrieve a buffer page to write to. */ +static int prvAllocateBufferPage(int prevPage) +{ + int index; + int count = 0; + + index = (prevPage + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT); + + while((PageInfo[index].Status != PAGE_STATUS_FREE) && (count ++ < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT))) + { + index = (index + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT); + } + + if (PageInfo[index].Status == PAGE_STATUS_FREE) + { + return index; + } + + return -1; +} + +/* Mark the page read as complete. */ +static void prvPageReadComplete(int pageIndex) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + PageInfo[pageIndex].BytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE); + PageInfo[pageIndex].WritePointer = &EventBuffer[pageIndex * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)]; + PageInfo[pageIndex].Status = PAGE_STATUS_FREE; + + TotalBytesRemaining += (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE); + + TRACE_EXIT_CRITICAL_SECTION(); +} + +/* Get the current buffer page index and remaining number of bytes. */ +static int prvGetBufferPage(int32_t* bytesUsed) +{ + static int8_t lastPage = -1; + int count = 0; + int8_t index = (int8_t) ((lastPage + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT)); + + while((PageInfo[index].Status != PAGE_STATUS_READ) && (count++ < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT))) + { + index = (int8_t)((index + 1) % (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT)); + } + + if (PageInfo[index].Status == PAGE_STATUS_READ) + { + *bytesUsed = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE) - PageInfo[index].BytesRemaining; + lastPage = index; + return index; + } + + *bytesUsed = 0; + + return -1; +} + +/******************************************************************************* + * uint32_t prvPagedEventBufferTransfer(void) + * + * Transfers one buffer page of trace data, if a full page is available, using + * the macro TRC_STREAM_PORT_WRITE_DATA as defined in trcStreamingPort.h. + * + * This function is intended to be called the periodic TzCtrl task with a suitable + * delay (e.g. 10-100 ms). + * + * Returns the number of bytes sent. If non-zero, it is good to call this + * again, in order to send any additional data waiting in the buffer. + * If zero, wait a while before calling again. + * + * In case of errors from the streaming interface, it registers a warning + * (PSF_WARNING_STREAM_PORT_WRITE) provided by xTraceGetLastError(). + * + *******************************************************************************/ +uint32_t prvPagedEventBufferTransfer(void) +{ + int8_t pageToTransfer = -1; + int32_t bytesTransferredTotal = 0; + int32_t bytesTransferredNow = 0; + int32_t bytesToTransfer; + + pageToTransfer = (int8_t)prvGetBufferPage(&bytesToTransfer); + + /* bytesToTransfer now contains the number of "valid" bytes in the buffer page, that should be transmitted. + There might be some unused junk bytes in the end, that must be ignored. */ + + if (pageToTransfer > -1) + { + while (1) /* Keep going until we have transferred all that we intended to */ + { + if (TRC_STREAM_PORT_WRITE_DATA( + &EventBuffer[pageToTransfer * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE) + bytesTransferredTotal], + (uint32_t)(bytesToTransfer - bytesTransferredTotal), + &bytesTransferredNow) == 0) + { + /* Write was successful. Update the number of transferred bytes. */ + bytesTransferredTotal += bytesTransferredNow; + + if (bytesTransferredTotal == bytesToTransfer) + { + /* All bytes have been transferred. Mark the buffer page as "Read Complete" (so it can be written to) and return OK. */ + prvPageReadComplete(pageToTransfer); + return (uint32_t)bytesTransferredTotal; + } + } + else + { + /* Some error from the streaming interface... */ + vTraceStop(); + return 0; + } + } + } + return 0; +} + +/******************************************************************************* + * void* prvPagedEventBufferGetWritePointer(int sizeOfEvent) + * + * Returns a pointer to an available location in the buffer able to store the + * requested size. + * + * Return value: The pointer. + * + * Parameters: + * - sizeOfEvent: The size of the event that is to be placed in the buffer. + * +*******************************************************************************/ +void* prvPagedEventBufferGetWritePointer(int sizeOfEvent) +{ + void* ret; + static int currentWritePage = -1; + + if (currentWritePage == -1) + { + currentWritePage = prvAllocateBufferPage(currentWritePage); + if (currentWritePage == -1) + { + DroppedEventCounter++; + return NULL; + } + } + + if (PageInfo[currentWritePage].BytesRemaining - sizeOfEvent < 0) + { + PageInfo[currentWritePage].Status = PAGE_STATUS_READ; + + TotalBytesRemaining -= PageInfo[currentWritePage].BytesRemaining; // Last trailing bytes + + if (TotalBytesRemaining < TotalBytesRemaining_LowWaterMark) + TotalBytesRemaining_LowWaterMark = TotalBytesRemaining; + + currentWritePage = prvAllocateBufferPage(currentWritePage); + if (currentWritePage == -1) + { + DroppedEventCounter++; + return NULL; + } + } + ret = PageInfo[currentWritePage].WritePointer; + PageInfo[currentWritePage].WritePointer += sizeOfEvent; + PageInfo[currentWritePage].BytesRemaining = (uint16_t)(PageInfo[currentWritePage].BytesRemaining -sizeOfEvent); + + TotalBytesRemaining = (TotalBytesRemaining-(uint16_t)sizeOfEvent); + + if (TotalBytesRemaining < TotalBytesRemaining_LowWaterMark) + TotalBytesRemaining_LowWaterMark = TotalBytesRemaining; + + return ret; +} + +/******************************************************************************* + * void prvPagedEventBufferInit(char* buffer) + * + * Assigns the buffer to use and initializes the PageInfo structure. + * + * Return value: void + * + * Parameters: + * - char* buffer: pointer to the trace data buffer, allocated by the caller. + * +*******************************************************************************/ +void prvPagedEventBufferInit(char* buffer) +{ + int i; + TRACE_ALLOC_CRITICAL_SECTION(); + + EventBuffer = buffer; + + TRACE_ENTER_CRITICAL_SECTION(); + for (i = 0; i < (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT); i++) + { + PageInfo[i].BytesRemaining = (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE); + PageInfo[i].WritePointer = &EventBuffer[i * (TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE)]; + PageInfo[i].Status = PAGE_STATUS_FREE; + } + TRACE_EXIT_CRITICAL_SECTION(); + +} + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ |