From d248555de5ec05260201e48a06f8252852c5fb18 Mon Sep 17 00:00:00 2001 From: Ming Yue Date: Thu, 13 Aug 2020 14:29:33 -0700 Subject: [PATCH] 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 --- .../Trace_Recorder_Configuration/trcConfig.h | 141 +- .../Include/aws_secure_sockets.tzext.h | 170 + .../Include/aws_wifi.tzext.h | 169 + .../Include/trcExtensions.h | 422 ++ .../Include/trcHardwarePort.h | 1036 +-- .../Include/trcKernelPort.h | 5356 +++++++------- .../Include/trcPortDefines.h | 275 +- .../FreeRTOS-Plus-Trace/Include/trcRecorder.h | 3694 +++++----- .../FreeRTOS-Plus-Trace/config/trcConfig.h | 712 +- .../config/trcSnapshotConfig.h | 754 +- .../config/trcStreamingConfig.h | 314 +- .../Source/FreeRTOS-Plus-Trace/readme.txt | 152 - .../AFR_WIFI_LOCAL/Readme-Streamport.txt | 22 + .../AFR_WIFI_LOCAL/include/trcStreamingPort.h | 161 + .../AFR_WIFI_LOCAL/trcStreamingPort.c | 191 + .../streamports/ARM_ITM/Readme-ARM_ITM.txt | 58 +- .../ARM_ITM/include/trcStreamingPort.h | 228 +- .../streamports/ARM_ITM/trcStreamingPort.c | 240 +- .../streamports/File/Readme-Streamport.txt | 36 +- .../File/include/trcStreamingPort.h | 174 +- .../streamports/File/trcStreamingPort.c | 206 +- .../Jlink_RTT/Readme-Streamport.txt | 42 +- .../Jlink_RTT/include/SEGGER_RTT_Conf.h | 4 + .../Jlink_RTT/include/trcStreamingPort.h | 392 +- .../streamports/Jlink_RTT/trcStreamingPort.c | 127 +- .../streamports/TCPIP/Readme-Streamport.txt | 70 +- .../TCPIP/include/trcStreamingPort.h | 134 +- .../streamports/TCPIP/trcStreamingPort.c | 366 +- .../TCPIP_Win32/Readme-Streamport.txt | 38 + .../TCPIP_Win32/include/trcStreamingPort.h | 75 + .../TCPIP_Win32/trcStreamingPort.c | 210 + .../streamports/USB_CDC/Readme-Streamport.txt | 52 +- .../USB_CDC/include/trcStreamingPort.h | 166 +- .../streamports/USB_CDC/trcStreamingPort.c | 537 +- .../tracealyzer_readme.txt | 748 +- .../FreeRTOS-Plus-Trace/trcKernelPort.c | 1916 ++--- .../FreeRTOS-Plus-Trace/trcSnapshotRecorder.c | 6179 ++++++++--------- .../trcStreamingRecorder.c | 3931 ++++++----- 38 files changed, 16058 insertions(+), 13440 deletions(-) create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/aws_secure_sockets.tzext.h create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/aws_wifi.tzext.h create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcExtensions.h delete mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/readme.txt create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/Readme-Streamport.txt create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/include/trcStreamingPort.h create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/trcStreamingPort.c create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/Readme-Streamport.txt create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/include/trcStreamingPort.h create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/trcStreamingPort.c 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 3a6fab81b3..0989814e68 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 ". + * 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 0000000000..f2ebf74c04 --- /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 *****/ + +/****************************************************************************** + * _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-.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__VERSION macros below. + * + * Note: The extension name displayed in Tracealyzer is defined in the XML file + * in the EventGroup element (e.g. ) + * + *****************************************************************************/ +#define TRC_EXT_SOCKETS_NAME "aws_secure_sockets" + +/****************************************************************************** + * _VERSION_MAJOR + * _VERSION_MINOR + * _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 + + +/****************************************************************************** + * _ + * The event codes used in the trace wrapper functions. Important that these + * are relative to _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) + +/****************************************************************************** + * _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 0000000000..238eacaff8 --- /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!) *****/ + +/****************************************************************************** + * _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-.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__VERSION macros below. + * + * Note: The extension name displayed in Tracealyzer is defined in the XML file + * in the EventGroup element (e.g. ) + * + *****************************************************************************/ +#define TRC_EXT_WIFI_NAME "aws_wifi" + +/****************************************************************************** + * _VERSION_MAJOR + * _VERSION_MINOR + * _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 + +/****************************************************************************** + * _ + * The event codes used in the trace wrapper functions. Important that these + * are relative to _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) + +/****************************************************************************** + * _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 0000000000..dfcdfcea72 --- /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. + * + * -v.<..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 _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 6bd981c4cb..e452999eef 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 - #include - #include - - /*************************************************************************** - * 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 + #include + + #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 + #include + #include + + /*************************************************************************** + * 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 965dabad9d..d877e81c6c 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 - * - * - * - * 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 + * + * + * + * 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 258bf220a5..99a2fbf50f 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 edcd5f0aeb..3d4f3d635d 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 -#include - -#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: -* -* vTraceEnable(TRC_START); -* -* -* Snapshot trace, from a later point: -* -* vTraceEnable(TRC_INIT); -* -* ... -* vTraceEnable(TRC_START); // e.g., in task context, at some relevant event -* -* Streaming trace, from startup: -* -* vTraceEnable(TRC_START_AWAIT_HOST); // Blocks! -* -* -* Streaming trace, from a later point: -* -* vTraceEnable(TRC_INIT); -* -* -******************************************************************************/ -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 " -* -* - Streaming mode: "char []", -* where 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) -* -* -* // Assign Q1 and Q2 to FilterGroup1 -* vTraceSetFilterGroup(FilterGroup1); -* -* -* -* // Assigns Q3 to FilterGroup2 -* vTraceSetFilterGroup(FilterGroup2); -* -* -* // 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); -* -* -* 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 32-bit integer parameters */ -void prvTraceStoreEvent(int nParam, uint16_t EventID, ...); - -/* Stories an event with a string and 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 +#include +#include + +#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: +* +* vTraceEnable(TRC_START); +* +* +* Snapshot trace, from a later point: +* +* vTraceEnable(TRC_INIT); +* +* ... +* vTraceEnable(TRC_START); // e.g., in task context, at some relevant event +* +* Streaming trace, from startup: +* +* vTraceEnable(TRC_START_AWAIT_HOST); // Blocks! +* +* +* Streaming trace, from a later point: +* +* vTraceEnable(TRC_INIT); +* +* +******************************************************************************/ +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 " +* +* - Streaming mode: "char []", +* where 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) +* +* +* // Assign Q1 and Q2 to FilterGroup1 +* vTraceSetFilterGroup(FilterGroup1); +* +* +* +* // Assigns Q3 to FilterGroup2 +* vTraceSetFilterGroup(FilterGroup2); +* +* +* // 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); +* +* +* 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 32-bit integer parameters */ +void prvTraceStoreEvent(int nParam, uint16_t EventID, ...); + +/* Stories an event with a string and 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 dceb6d85b6..fa113949d7 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 ". + * 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 5ce12fcaa5..601dfda68c 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 f578f10ece..9ad2ce577d 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 79b64006d2..0000000000 --- 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 0000000000..8774f20f55 --- /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 0000000000..4d4322d926 --- /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 0000000000..1edee04c31 --- /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 0802b5331c..be48c6df38 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 ca20ae753e..c14c4e1f9e 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 0d36b4ab38..4b51d7f0e5 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 afc5a09516..c88517ef1d 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 2897b7ce26..0deb9ad1cc 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 - -#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 + +#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 a019791cd2..03a5a9a6ff 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 cae5e8ecc9..0dcd1591ef 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 4f7f4cc3c1..4bb1fdb5a5 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 b1074b4240..6ad22d5076 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 d279f83b9f..d4d7ec1180 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 f8f097baab..c2d9ce78d6 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 51e52e862f..b305df4f52 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 d420d121a8..df92f6f0a7 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 0000000000..b61ecff8f1 --- /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 0000000000..594ba21506 --- /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 + +#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 0000000000..d6eb0e3b79 --- /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 +#include + +#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 260f12ace7..a231518058 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 6940b4d6de..082eebf510 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 800022a1b0..351d833259 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;iTxState != 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 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 d41b526876..374e9a6d5f 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: +* +* vTraceEnable(TRC_START); +* +* +* Snapshot trace, from a later point: +* +* vTraceEnable(TRC_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 9eec9d2edd..a2513b08a4 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 -#include -#include - -#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: -* -* vTraceEnable(TRC_START); -* -* -* Snapshot trace, from a later point: -* -* vTraceEnable(TRC_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 +#include +#include + +#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 dc1b87865c..0ca034b84b 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 -#include - -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 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 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 +#include +#include + +#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 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 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)*/