diff --git a/.github/scripts/core_checker.py b/.github/scripts/core_checker.py index c0e2e36b54..7058709fe9 100755 --- a/.github/scripts/core_checker.py +++ b/.github/scripts/core_checker.py @@ -268,9 +268,12 @@ FREERTOS_IGNORED_PATTERNS = [ r'.*/trcConfig\.h.*', r'.*/trcConfig\.c.*', r'.*/trcSnapshotConfig\.h.*', + r'.*/trcKernelPortConfig\.h.*', r'.*/MicroZed_hw_platform.*', r'.*/ThirdParty/.*', - r'FreeRTOS\-Plus/Demo/Common/WinPCap/.*' + r'FreeRTOS\-Plus/Demo/Common/WinPCap/.*', + r'FreeRTOS\-Plus/Source/FreeRTOS-Plus-Trace/.*', + r'FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/.*' ] FREERTOS_IGNORED_FILES = [ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/CLI-commands.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/CLI-commands.c index e39a18172c..5496b7414d 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/CLI-commands.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/CLI-commands.c @@ -1,6 +1,6 @@ /* * FreeRTOS V202112.00 - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -20,7 +20,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * https://www.FreeRTOS.org - * https://aws.amazon.com/freertos + * https://github.com/FreeRTOS * */ @@ -335,7 +335,9 @@ BaseType_t lParameterStringLength; /* Start or restart the trace. */ vTraceStop(); vTraceClear(); - uiTraceStart(); + + vTraceEnable( TRC_START ); + traceSTART(); sprintf( pcWriteBuffer, "Trace recording (re)started.\r\n" ); } diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/FreeRTOS_Plus_CLI_with_Trace.sln b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/FreeRTOS_Plus_CLI_with_Trace.sln index 6334f86684..c2852da5c9 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/FreeRTOS_Plus_CLI_with_Trace.sln +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/FreeRTOS_Plus_CLI_with_Trace.sln @@ -19,4 +19,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F78FDCED-CBDF-4B81-B6E3-78A0A2989E82} + EndGlobalSection EndGlobal 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 76c60a0531..0b0933a1c7 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 @@ -52,8 +52,6 @@ extern "C" { #endif -#include "trcPortDefines.h" - /****************************************************************************** * Include of processor header file * @@ -99,32 +97,6 @@ extern "C" { ******************************************************************************/ #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 TRC_FREERTOS_VERSION_10_4_0 - /******************************************************************************* * TRC_CFG_SCHEDULING_ONLY * @@ -224,17 +196,6 @@ extern "C" { *****************************************************************************/ #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 * @@ -258,18 +219,6 @@ extern "C" { *****************************************************************************/ #define TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS 1 -/******************************************************************************* - * 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 * @@ -387,15 +336,19 @@ 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 */ + /** + * @def TRC_CFG_RECORDER_DATA_ATTRIBUTE + * @brief When setting TRC_CFG_RECORDER_DATA_INIT to 0, you might also need to make + * sure certain recorder data is placed in a specific RAM section to avoid being + * zeroed out after initialization. Define TRC_CFG_RECORDER_DATA_ATTRIBUTE as + * that attribute. + * + * Example: + * #define TRC_CFG_RECORDER_DATA_ATTRIBUTE __attribute__((section(".bss.trace_recorder_data"))) + * + * Default value is empty. + */ +#define TRC_CFG_RECORDER_DATA_ATTRIBUTE /* Specific configuration, depending on Streaming/Snapshot mode */ #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcKernelPortConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcKernelPortConfig.h new file mode 100644 index 0000000000..84879b35a9 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcKernelPortConfig.h @@ -0,0 +1,116 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Configuration parameters for the kernel port. + * More settings can be found in trcKernelPortStreamingConfig.h and + * trcKernelPortSnapshotConfig.h. + */ + +#ifndef TRC_KERNEL_PORT_CONFIG_H +#define TRC_KERNEL_PORT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def TRC_CFG_RECORDER_MODE + * @brief 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 + +/** + * @def TRC_CFG_FREERTOS_VERSION + * @brief 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 + * TRC_FREERTOS_VERSION_10_4_1 If using FreeRTOS v10.4.1 or later + */ +#define TRC_CFG_FREERTOS_VERSION TRC_FREERTOS_VERSION_10_4_1 + +/** + * @def TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS + * @brief 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 + +/** + * @def TRC_CFG_INCLUDE_TIMER_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS + * @brief 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 + +/** + * @def TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND + * @brief 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 */ + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_KERNEL_PORT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcKernelPortSnapshotConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcKernelPortSnapshotConfig.h new file mode 100644 index 0000000000..d4910f2b0e --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcKernelPortSnapshotConfig.h @@ -0,0 +1,69 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Kernel port configuration parameters for snapshot mode. + */ + +#ifndef TRC_KERNEL_PORT_SNAPSHOT_CONFIG_H +#define TRC_KERNEL_PORT_SNAPSHOT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def TRC_CFG_NTASK, TRC_CFG_NISR, TRC_CFG_NQUEUE, TRC_CFG_NSEMAPHORE... + * @brief 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 150 +#define TRC_CFG_NISR 90 +#define TRC_CFG_NQUEUE 90 +#define TRC_CFG_NSEMAPHORE 90 +#define TRC_CFG_NMUTEX 90 +#define TRC_CFG_NTIMER 250 +#define TRC_CFG_NEVENTGROUP 90 +#define TRC_CFG_NSTREAMBUFFER 50 +#define TRC_CFG_NMESSAGEBUFFER 50 + +/** + * @def TRC_CFG_NAME_LEN_TASK, TRC_CFG_NAME_LEN_QUEUE, ... + * @brief 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 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_KERNEL_PORT_SNAPSHOT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcSnapshotConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcSnapshotConfig.h index aa22293465..3a8eaceecc 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcSnapshotConfig.h +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/trcSnapshotConfig.h @@ -84,39 +84,6 @@ ******************************************************************************/ #define TRC_CFG_EVENT_BUFFER_SIZE 15000 -/******************************************************************************* - * 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 150 -#define TRC_CFG_NISR 90 -#define TRC_CFG_NQUEUE 90 -#define TRC_CFG_NSEMAPHORE 90 -#define TRC_CFG_NMUTEX 90 -#define TRC_CFG_NTIMER 250 -#define TRC_CFG_NEVENTGROUP 90 -#define TRC_CFG_NSTREAMBUFFER 50 -#define TRC_CFG_NMESSAGEBUFFER 50 - - /****************************************************************************** * TRC_CFG_INCLUDE_FLOAT_SUPPORT * diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/WIN32.vcxproj b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/WIN32.vcxproj index 1fdf1cd470..7f5d44435f 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/WIN32.vcxproj +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/WIN32.vcxproj @@ -130,10 +130,12 @@ + + @@ -157,4 +159,4 @@ - \ No newline at end of file + diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/WIN32.vcxproj.filters b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/WIN32.vcxproj.filters index d112c99f67..fb4c5b7f58 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/WIN32.vcxproj.filters +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/WIN32.vcxproj.filters @@ -80,6 +80,12 @@ FreeRTOS+\FreeRTOS+Trace + + FreeRTOS\Source + + + FreeRTOS\Source + diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/main.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/main.c index cecf3a9331..7c2d13f250 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/main.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/main.c @@ -1,6 +1,6 @@ /* * FreeRTOS V202112.00 - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -20,7 +20,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * https://www.FreeRTOS.org - * https://aws.amazon.com/freertos + * https://github.com/FreeRTOS * */ @@ -242,4 +242,19 @@ const unsigned long ulLongSleep = 1000UL; } /*-----------------------------------------------------------*/ +static uint32_t ulEntryTime = 0; +void vTraceTimerReset( void ) +{ + ulEntryTime = xTaskGetTickCount(); +} + +uint32_t uiTraceTimerGetFrequency( void ) +{ + return configTICK_RATE_HZ; +} + +uint32_t uiTraceTimerGetValue( void ) +{ + return ( xTaskGetTickCount() - ulEntryTime ); +} diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/Makefile b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/Makefile index 1e21f23e62..54f594e376 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/Makefile +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/Makefile @@ -18,6 +18,7 @@ INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/Include INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/linux/ INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-TCP/include/ INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/ +INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/config SOURCE_FILES := $(wildcard *.c) SOURCE_FILES += $(wildcard ${FREERTOS_DIR}/Source/*.c) @@ -70,11 +71,10 @@ SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/TimerDemo.c # Trace library. SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcKernelPort.c SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c -SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c -SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c +CFLAGS := -ggdb3 -O0 +CPPFLAGS := -DprojCOVERAGE_TEST=0 -D_DEFAULT_SOURCE -D_WINDOWS_ -DTRACE_ON_ENTER=0 -CFLAGS := -ggdb3 -O0 -DprojCOVERAGE_TEST=0 -D_WINDOWS_ LDFLAGS := -ggdb3 -O0 -pthread -lpcap OBJ_FILES = $(SOURCE_FILES:%.c=$(BUILD_DIR)/%.o) @@ -85,23 +85,16 @@ ${BIN} : $(BUILD_DIR)/$(BIN) ${BUILD_DIR}/${BIN} : ${OBJ_FILES} -mkdir -p ${@D} - $(CC) $^ $(CFLAGS) $(INCLUDE_DIRS) ${LDFLAGS} -o $@ - + $(CC) $^ ${LDFLAGS} -o $@ -include ${DEP_FILE} -${BUILD_DIR}/%.o : %.c +${BUILD_DIR}/%.o : %.c Makefile -mkdir -p $(@D) - $(CC) $(CFLAGS) ${INCLUDE_DIRS} -MMD -c $< -o $@ + $(CC) $(CFLAGS) ${CPPFLAGS} ${INCLUDE_DIRS} -MMD -c $< -o $@ .PHONY: clean clean: -rm -rf $(BUILD_DIR) - - - - - - diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/main.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/main.c index f0104d6acb..162068ab45 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/main.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/main.c @@ -51,6 +51,8 @@ #include #include #include +#include +#include /* FreeRTOS kernel includes. */ #include "FreeRTOS.h" @@ -59,6 +61,8 @@ /* Local includes. */ #include "console.h" +#include + #define ECHO_CLIENT_DEMO 0 #define mainSELECTED_APPLICATION ECHO_CLIENT_DEMO @@ -103,6 +107,10 @@ StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; /* Notes if the trace is running or not. */ static BaseType_t xTraceRunning = pdTRUE; +static clockid_t cid = CLOCK_THREAD_CPUTIME_ID; + +static uint32_t frequency; + /*-----------------------------------------------------------*/ int main( void ) @@ -118,7 +126,7 @@ int main( void ) configASSERT() is called. */ printf( "\r\nTrace started.\r\nThe trace will be dumped to disk if a call to configASSERT() fails.\r\n" ); printf( "\r\nThe trace will be dumped to disk if Enter is hit.\r\n" ); - uiTraceStart(); + traceSTART(); } #endif @@ -284,6 +292,7 @@ static void prvSaveTraceFile( void ) #if ( projCOVERAGE_TEST != 1 ) { FILE * pxOutputFile; + extern RecorderDataType * RecorderDataPtr; vTraceStop(); @@ -355,3 +364,57 @@ the stack and so not exists after this function exits. */ configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; } + +void vTraceTimerReset( void ) +{ + int xRet; + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 0; + + xRet = clock_settime( cid, &ts ); + if( xRet != 0 ) + { + printf( "Could not reset time: %s\n", strerror( errno ) ); + } +} + +uint32_t uiTraceTimerGetFrequency( void ) +{ + struct timespec res; + int xRet; + + res.tv_nsec = 0; + res.tv_sec = 0; + + xRet = clock_getres( cid, &res ); + if( xRet == 0 ) + { + // calculate frequency from timer definition + frequency = (uint64_t) 1000000000 / res.tv_nsec; + } + else + { + printf( "Could not get clock frequency: %s\n", strerror( errno ) ); + } + return frequency; +} + +uint32_t uiTraceTimerGetValue( void ) +{ + int xRet; + struct timespec tp; + uint32_t result = 0; + + xRet = clock_gettime( cid, &tp ); + if( xRet == 0 ) + { + result = tp.tv_nsec / frequency; + result += (tp.tv_sec * 1000000000) / frequency; + } + else + { + printf( "Could not get time: %s\n", strerror( errno ) ); + } + return result; +} diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcConfig.h index 30e0496587..53b1cdc9e6 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcConfig.h +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcConfig.h @@ -52,8 +52,6 @@ extern "C" { #endif -#include "trcPortDefines.h" - /****************************************************************************** * Include of processor header file * @@ -98,31 +96,6 @@ 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_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_4_0 /******************************************************************************* * TRC_CFG_SCHEDULING_ONLY @@ -295,6 +268,14 @@ extern "C" { *****************************************************************************/ #define TRC_CFG_MAX_ISR_NESTING 8 +#define TRC_CFG_CTRL_TASK_STACK_SIZE ( 1024 ) + +#define TRC_CFG_CTRL_TASK_PRIORITY 1 + +#define TRC_CFG_CTRL_TASK_DELAY 2 + +#define TRC_CFG_RECORDER_DATA_ATTRIBUTE + /* Specific configuration, depending on Streaming/Snapshot mode */ #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) #include "trcSnapshotConfig.h" diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcKernelPortConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcKernelPortConfig.h new file mode 100644 index 0000000000..b0c7d22164 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcKernelPortConfig.h @@ -0,0 +1,116 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Configuration parameters for the kernel port. + * More settings can be found in trcKernelPortStreamingConfig.h and + * trcKernelPortSnapshotConfig.h. + */ + +#ifndef TRC_KERNEL_PORT_CONFIG_H +#define TRC_KERNEL_PORT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def TRC_CFG_RECORDER_MODE + * @brief 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 + +/** + * @def TRC_CFG_FREERTOS_VERSION + * @brief 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 + * TRC_FREERTOS_VERSION_10_4_1 If using FreeRTOS v10.4.1 or later + */ +#define TRC_CFG_FREERTOS_VERSION TRC_FREERTOS_VERSION_10_4_1 + +/** + * @def TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_TIMER_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND + * @brief 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 */ + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_KERNEL_PORT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcSnapshotConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcSnapshotConfig.h index 45c920584c..d9948e972a 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcSnapshotConfig.h +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/trcSnapshotConfig.h @@ -84,39 +84,6 @@ ******************************************************************************/ #define TRC_CFG_EVENT_BUFFER_SIZE 32000 -/******************************************************************************* - * 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 150 -#define TRC_CFG_NISR 90 -#define TRC_CFG_NQUEUE 90 -#define TRC_CFG_NSEMAPHORE 90 -#define TRC_CFG_NMUTEX 90 -#define TRC_CFG_NTIMER 250 -#define TRC_CFG_NEVENTGROUP 90 -#define TRC_CFG_NSTREAMBUFFER 100 -#define TRC_CFG_NMESSAGEBUFFER 100 - - /****************************************************************************** * TRC_CFG_INCLUDE_FLOAT_SUPPORT * diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WIN32.vcxproj.user b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WIN32.vcxproj.user new file mode 100644 index 0000000000..88a550947e --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WIN32.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download/WIN32.vcxproj.user b/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download/WIN32.vcxproj.user new file mode 100644 index 0000000000..88a550947e --- /dev/null +++ b/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download/WIN32.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Demo/coreMQTT_Windows_Simulator/MQTT_Mutual_Auth/WIN32.vcxproj.user b/FreeRTOS-Plus/Demo/coreMQTT_Windows_Simulator/MQTT_Mutual_Auth/WIN32.vcxproj.user new file mode 100644 index 0000000000..88a550947e --- /dev/null +++ b/FreeRTOS-Plus/Demo/coreMQTT_Windows_Simulator/MQTT_Mutual_Auth/WIN32.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file 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 index 045203aded..4fae73e0f8 100644 --- 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 @@ -1,170 +1,136 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.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 */ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#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 /* 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 index 65d0cd54fe..66ce0e8780 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/aws_wifi.tzext.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/aws_wifi.tzext.h @@ -1,169 +1,135 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.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 */ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#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 /* 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/trcAssert.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcAssert.h new file mode 100644 index 0000000000..563b222437 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcAssert.h @@ -0,0 +1,143 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace assert APIs. + */ + +#ifndef TRC_ASSERT_H +#define TRC_ASSERT_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_assert_apis Trace Asserts APIs + * @ingroup trace_recorder_apis + * @{ + */ + +#ifndef TRC_CFG_USE_TRACE_ASSERT +#error "TRC_CFG_USE_TRACE_ASSERT is not defined. Please define it in trcConfig.h" +#endif + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +/* Standard assert */ +#define TRC_ASSERT(__condition) if (!(__condition)) { prvTraceAssertCreate(__FILE__, __LINE__); return TRC_FAIL; } + +#define TRC_ASSERT_ALWAYS_EVALUATE TRC_ASSERT + +/* Standard assert with custom on fail actions */ +#define TRC_ASSERT_CUSTOM_ON_FAIL(__condition, __custom_on_fail) if (!(__condition)) { prvTraceAssertCreate(__FILE__, __LINE__); __custom_on_fail; } + +#define TRC_ASSERT_CUSTOM_ON_FAIL_ALWAYS_EVALUATE TRC_ASSERT_CUSTOM_ON_FAIL + +#if (defined(TRC_CFG_TEST_MODE) && (TRC_CFG_TEST_MODE) == 1) + +/* Asserts that two types have an equal size. Condition passed to function to avoid compilers warning about unreachable code due to constant value. */ +#define TRC_ASSERT_EQUAL_SIZE(x, y) if (!prvTraceAssertCheckCondition((TraceBaseType_t)(sizeof(x) == sizeof(y)))) { prvTraceAssertCreate(__FILE__, __LINE__); return TRC_FAIL; } + +/** + * @brief Inlined condition check to get around some compiler warnings for unused variables. + * + * @param[in] condition The condition + */ +inline TraceBaseType_t prvTraceAssertCheckCondition(TraceBaseType_t condition) +{ + return condition; +} + +#else + +#define TRC_ASSERT_EQUAL_SIZE(x, y) + +#endif + +#define TRC_ASSERT_BUFFER_SIZE (sizeof(TraceEntryHandle_t)) + +typedef struct TraceAssertBuffer +{ + uint8_t buffer[TRC_ASSERT_BUFFER_SIZE]; +} TraceAssertBuffer_t; + +/** + * @internal Initializes assert system + * + * @param[in] pxBuffer The assert data buffer + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceAssertInitialize(TraceAssertBuffer_t *pxBuffer); + +/** + * @internal Creates an assert + * + * @param[in] szFilePath File name + * @param[in] uxLineNumber Line number + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +void prvTraceAssertCreate(const char* szFilePath, TraceUnsignedBaseType_t uxLineNumber); + +/** + * @brief Retrieves the assert and line number + * + * @param[out] pxFileNameStringHandle File name string handle + * @param[out] puxLineNumber Line number + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceAssertGet(TraceStringHandle_t* pxFileNameStringHandle, TraceUnsignedBaseType_t* puxLineNumber); + +#else /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +#define TRC_ASSERT(__condition) + +#define TRC_ASSERT_ALWAYS_EVALUATE(__condition) (void)(__condition) + +#define TRC_ASSERT_CUSTOM_ON_FAIL(__condition, __custom_on_fail) + +#define TRC_ASSERT_CUSTOM_ON_FAIL_ALWAYS_EVALUATE(__condition, __custom_on_fail) (__condition) + +#define TRC_ASSERT_EQUAL_SIZE(x, y) + +typedef struct TraceAssertBuffer +{ + uint32_t buffer[1]; +} TraceAssertBuffer_t; + +#define xTraceAssertInitialize(pxBuffer) ((void)pxBuffer, TRC_SUCCESS) + +#define xTraceAssertGet(pxFileNameStringHandle, puxLineNumber) ((void)pxFileNameStringHandle, (void)puxLineNumber, TRC_FAIL) + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_ASSERT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcCounter.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcCounter.h new file mode 100644 index 0000000000..086a5382c0 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcCounter.h @@ -0,0 +1,154 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace counter APIs. + */ + +#ifndef TRC_COUNTER_H +#define TRC_COUNTER_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_counter_apis Trace Counter APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @brief Sets trace counter callback. + * + * @param[in] xCallback Callback + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceCounterSetCallback(TraceCounterCallback_t xCallback); + +/** + * @brief Creates trace counter. + * + * @param[in] szName Name. + * @param[in] xInitialValue Initial value. + * @param[in] xLowerLimit Lower limit. + * @param[in] xUpperLimit Upper limit. + * @param[out] pxCounterHandle Uninitialized trace counter handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceCounterCreate(const char* szName, TraceBaseType_t xInitialValue, TraceBaseType_t xLowerLimit, TraceBaseType_t xUpperLimit, TraceCounterHandle_t* pxCounterHandle); + +/** + * @brief Adds value to trace counter. + * + * @param[in] xCounterHandle Initialized trace counter handle. + * @param[in] xValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceCounterAdd(TraceCounterHandle_t xCounterHandle, TraceBaseType_t xValue); + +/** + * @brief Sets trace counter value. + * + * @param[in] xCounterHandle Initialized trace counter handle. + * @param[in] xValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceCounterSet(TraceCounterHandle_t xCounterHandle, TraceBaseType_t xValue); + +/** + * @brief Gets trace counter value. + * + * @param[in] xCounterHandle Initialized trace counter handle. + * @param[out] pxValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceCounterGet(TraceCounterHandle_t xCounterHandle, TraceBaseType_t* pxValue); + +/** + * @brief Increases trace counter value. + * + * @param[in] xCounterHandle Initialized trace counter handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceCounterIncrease(TraceCounterHandle_t xCounterHandle); + +/** + * @brief Decreases trace counter value. + * + * @param[in] xCounterHandle Initialized trace counter handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceCounterDecrease(TraceCounterHandle_t xCounterHandle); + +/** + * @brief Gets trace counter upper limit. + * + * @param[in] xCounterHandle Initialized trace counter handle. + * @param[out] pxValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceCounterGetUpperLimit(TraceCounterHandle_t xCounterHandle, TraceBaseType_t* pxValue); + +/** + * @brief Gets trace counter lower limit. + * + * @param[in] xCounterHandle Initialized trace counter handle. + * @param[out] pxValue Value + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceCounterGetLowerLimit(TraceCounterHandle_t xCounterHandle, TraceBaseType_t* pxValue); + +/** + * @brief Gets trace counter name. + * + * @param[in] xCounterHandle Initialized trace counter handle. + * @param[out] pszName Name. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceCounterGetName(TraceCounterHandle_t xCounterHandle, const char** pszName); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_COUNTER_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcPortDefines.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcDefines.h similarity index 52% rename from FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcPortDefines.h rename to FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcDefines.h index 7144763826..2a7ddc525a 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcPortDefines.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcDefines.h @@ -1,138 +1,182 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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*/ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Some common defines for the trace recorder. + */ + +#ifndef TRC_DEFINES_H +#define TRC_DEFINES_H + +#define TRC_SUCCESS (0) +#define TRC_FAIL (1) + +#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 + +#define TRC_STATE_IN_STARTUP 0 +#define TRC_STATE_IN_TASKSWITCH 1 +#define TRC_STATE_IN_APPLICATION 2 + +/* Start options for vTraceEnable. */ +#define TRC_START_FROM_HOST 0 +#define TRC_START 1 +#define TRC_START_AWAIT_HOST 2 + +#define TRC_ACKNOWLEDGED (0xABC99123) + +/* 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_SNAPSHOT_MODE_RING_BUFFER (0x01) +#define TRC_SNAPSHOT_MODE_STOP_WHEN_FULL (0x02) + +#define TRC_RECORDER_BUFFER_ALLOCATION_STATIC (0x00) +#define TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC (0x01) +#define TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM (0x02) + +#define TRC_OPTION_BIT_SHIFT_IRQ_ORDER 0 +#define TRC_OPTION_BIT_SHIFT_BASE_SIZE 8 + +/******************************************************************************/ +/*** ERROR AND WARNING CODES (check using xTraceErrorGetLast) *****************/ +/******************************************************************************/ + +#define TRC_ERROR_NONE 0x00 + +#define TRC_ERROR_ASSERT 0x01 +#define TRC_ERROR_EVENT_CODE_TOO_LARGE 0x02 +#define TRC_ERROR_ISR_NESTING_OVERFLOW 0x03 +#define TRC_ERROR_DWT_NOT_SUPPORTED 0x04 +#define TRC_ERROR_DWT_CYCCNT_NOT_SUPPORTED 0x05 +#define TRC_ERROR_TZCTRLTASK_NOT_CREATED 0x06 +#define TRC_ERROR_STREAM_PORT_WRITE 0x07 + +#define TRC_WARNING_ENTRY_TABLE_SLOTS 0x08 +#define TRC_WARNING_ENTRY_SYMBOL_MAX_LENGTH 0x09 +#define TRC_WARNING_EVENT_SIZE_TRUNCATED 0x0A +#define TRC_WARNING_STREAM_PORT_READ 0x0B +#define TRC_WARNING_STREAM_PORT_WRITE 0x0C +#define TRC_WARNING_STREAM_PORT_INITIAL_BLOCKING 0x0D +#define TRC_WARNING_STACKMON_NO_SLOTS 0x0E + +/* Entry Option definitions */ +#define TRC_ENTRY_OPTION_EXCLUDED 0x00000001 +#define TRC_ENTRY_OPTION_HEAP 0x80000000 +#define TRC_ENTRY_OPTION_EXTENSION 0x40000000 +#define TRC_ENTRY_OPTION_STATE_MACHINE 0x20000000 +#define TRC_ENTRY_OPTION_STATE_MACHINE_STATE 0x10000000 +#define TRC_ENTRY_OPTION_INTERVAL 0x08000000 +#define TRC_ENTRY_OPTION_COUNTER 0x04000000 + +#define TRC_RECORDER_COMPONENT_CORE 0x00000001 +#define TRC_RECORDER_COMPONENT_ASSERT 0x00000002 +#define TRC_RECORDER_COMPONENT_BLOB 0x00000004 +#define TRC_RECORDER_COMPONENT_DIAGNOSTICS 0x00000008 +#define TRC_RECORDER_COMPONENT_ENTRY 0x00000010 +#define TRC_RECORDER_COMPONENT_ERROR 0x00000020 +#define TRC_RECORDER_COMPONENT_EVENT 0x00000040 +#define TRC_RECORDER_COMPONENT_EVENT_BUFFER 0x00000080 +#define TRC_RECORDER_COMPONENT_EXTENSION 0x00000100 +#define TRC_RECORDER_COMPONENT_HEAP 0x00000200 +#define TRC_RECORDER_COMPONENT_INTERNAL_EVENT_BUFFER 0x00000400 +#define TRC_RECORDER_COMPONENT_INTERVAL 0x00000800 +#define TRC_RECORDER_COMPONENT_ISR 0x00001000 +#define TRC_RECORDER_COMPONENT_MULTI_CORE_EVENT_BUFFER 0x00002000 +#define TRC_RECORDER_COMPONENT_OBJECT 0x00004000 +#define TRC_RECORDER_COMPONENT_PRINT 0x00008000 +#define TRC_RECORDER_COMPONENT_STACK_MONITOR 0x00010000 +#define TRC_RECORDER_COMPONENT_STATE_MACHINE 0x00020000 +#define TRC_RECORDER_COMPONENT_STATIC_BUFFER 0x00040000 +#define TRC_RECORDER_COMPONENT_STRING 0x00080000 +#define TRC_RECORDER_COMPONENT_TASK 0x00100000 +#define TRC_RECORDER_COMPONENT_TIMESTAMP 0x00200000 +#define TRC_RECORDER_COMPONENT_COUNTER 0x00400000 + +/* 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) */ +#define TRC_HARDWARE_PORT_ZEPHYR 19 /* Yes Zephyr */ +#define TRC_HARDWARE_PORT_XTensa_LX6 20 /* Yes ESP-IDF FreeRTOS */ +#define TRC_HARDWARE_PORT_XTensa_LX7 21 /* Yes ESP-IDF FreeRTOS */ +#define TRC_HARDWARE_PORT_Win64 22 /* Yes FreeRTOS on Win64 */ +#define TRC_HARDWARE_PORT_XMOS_XCOREAI 23 /* Yes FreeRTOS SMP */ +#define TRC_HARDWARE_PORT_RISCV_RV32I 24 /* Yes FreeRTOS */ +#define TRC_HARDWARE_PORT_CYCLONE_V_HPS 25 /* Yes FreeRTOS */ + +#endif /* TRC_PORTDEFINES_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcDiagnostics.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcDiagnostics.h new file mode 100644 index 0000000000..449e19f6c0 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcDiagnostics.h @@ -0,0 +1,145 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace diagnostic APIs. + */ + +#ifndef TRC_DIAGNOSTICS_H +#define TRC_DIAGNOSTICS_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRC_DIAGNOSTICS_COUNT 5 + +typedef enum TraceDiagnosticsType +{ + TRC_DIAGNOSTICS_ENTRY_SYMBOL_LONGEST_LENGTH = 0x00, + TRC_DIAGNOSTICS_ENTRY_SLOTS_NO_ROOM = 0x01, + TRC_DIAGNOSTICS_BLOB_MAX_BYTES_TRUNCATED = 0x02, + TRC_DIAGNOSTICS_STACK_MONITOR_NO_SLOTS = 0x03, + TRC_DIAGNOSTICS_ASSERTS_TRIGGERED = 0x04, +} TraceDiagnosticsType_t; + +typedef struct TraceDiagnosticsBuffer +{ + uint8_t buffer[sizeof(TraceBaseType_t) * (TRC_DIAGNOSTICS_COUNT)]; +} TraceDiagnosticsBuffer_t; + +/** + * @internal Initialize diagnostics + * + * @param[in] pxBuffer Diagnostics buffer + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceDiagnosticsInitialize(TraceDiagnosticsBuffer_t* pxBuffer); + +/** + * @brief Retrieve diagnostics value + * + * @param[in] xType Diagnostics type + * @param[out] pxValue Pointer to value + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceDiagnosticsGet(TraceDiagnosticsType_t xType, TraceBaseType_t* pxValue); + +/** + * @brief Set diagnostics value + * + * @param[in] xType Diagnostics type + * @param[in] xValue Value + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceDiagnosticsSet(TraceDiagnosticsType_t xType, TraceBaseType_t xValue); + +/** + * @brief Add to diagnostics value + * + * @param[in] xType Diagnostics type + * @param[in] xValue Value + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceDiagnosticsAdd(TraceDiagnosticsType_t xType, TraceBaseType_t xValue); + +/** + * @brief Increase diagnostics value + * + * @param[in] xType Diagnostics type + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceDiagnosticsIncrease(TraceDiagnosticsType_t xType); + +/** + * @brief Decrease diagnostics value + * + * @param[in] xType Diagnostics type + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceDiagnosticsDecrease(TraceDiagnosticsType_t xType); + +/** + * @brief Set a new diagnostics value if higher than previous value + * + * @param[in] xType Dagnostics type + * @param[in] xValue Value + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceDiagnosticsSetIfHigher(TraceDiagnosticsType_t xType, TraceBaseType_t xValue); + +/** + * @brief Set a new diagnostics value if lower than previous value + * + * @param[in] xType Dagnostics type + * @param[in] xValue Value + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceDiagnosticsSetIfLower(TraceDiagnosticsType_t xType, TraceBaseType_t xValue); + +/** + * @brief Check the diagnostics status + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceDiagnosticsCheckStatus(void); + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_DIAGNOSTICS_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcEntryTable.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcEntryTable.h new file mode 100644 index 0000000000..e022fbc8a4 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcEntryTable.h @@ -0,0 +1,258 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace entry table APIs. + */ + +#ifndef TRC_ENTRY_TABLE_H +#define TRC_ENTRY_TABLE_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_entry_table_apis Trace Entry Table APIs + * @ingroup trace_recorder_apis + * @{ + */ + +#define TRC_ENTRY_CREATE_WITH_ADDRESS(_pvAddress, _pxEntryHandle) (xTraceEntryCreate(_pxEntryHandle) == TRC_SUCCESS ? (((TraceEntry_t*)*(_pxEntryHandle))->pvAddress = (_pvAddress), TRC_SUCCESS) : TRC_FAIL) +#define TRC_ENTRY_SET_STATE(xEntryHandle, uiStateIndex, uxState) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(((TraceEntry_t*)(xEntryHandle))->xStates[uiStateIndex] = (uxState), TRC_SUCCESS) +#define TRC_ENTRY_SET_OPTIONS(xEntryHandle, uiMask) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(((TraceEntry_t*)(xEntryHandle))->uiOptions |= (uiMask), TRC_SUCCESS) +#define TRC_ENTRY_CLEAR_OPTIONS(xEntryHandle, uiMask) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(((TraceEntry_t*)(xEntryHandle))->uiOptions &= ~(uiMask), TRC_SUCCESS) +#define TRC_ENTRY_GET_ADDRESS(xEntryHandle, ppvAddress) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(ppvAddress) = ((TraceEntry_t*)(xEntryHandle))->pvAddress, TRC_SUCCESS) +#define TRC_ENTRY_GET_SYMBOL(xEntryHandle, pszSymbol) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(pszSymbol) = ((TraceEntry_t*)(xEntryHandle))->szSymbol, TRC_SUCCESS) +#define TRC_ENTRY_GET_STATE(xEntryHandle, uiStateIndex, puxState) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(puxState) = ((TraceEntry_t*)(xEntryHandle))->xStates[uiStateIndex], TRC_SUCCESS) +#define TRC_ENTRY_GET_OPTIONS(xEntryHandle, puiOptions) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(puiOptions) = ((TraceEntry_t*)(xEntryHandle))->uiOptions, TRC_SUCCESS) + +#define TRC_ENTRY_TABLE_SLOTS (TRC_CFG_ENTRY_SLOTS) +#define TRC_ENTRY_TABLE_STATE_COUNT (3) +#define TRC_ENTRY_TABLE_SYMBOL_LENGTH (TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH) +#define TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE ((((sizeof(char) * TRC_ENTRY_TABLE_SYMBOL_LENGTH) + (sizeof(uint32_t) - 1)) / sizeof(uint32_t)) * sizeof(uint32_t)) + +/** Trace Entry Structure */ +typedef struct TraceEntry +{ + void* pvAddress; /**< */ + TraceUnsignedBaseType_t xStates[TRC_ENTRY_TABLE_STATE_COUNT]; /**< */ + uint32_t uiOptions; /**< */ + char szSymbol[TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE]; /**< */ +} TraceEntry_t; + +#define TRC_ENTRY_TABLE_SIZE (sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + (sizeof(TraceEntry_t) * (TRC_ENTRY_TABLE_SLOTS))) + +/** Trace Entry Table Buffer Structure */ +typedef struct TraceEntryTableBuffer +{ + uint8_t buffer[(TRC_ENTRY_TABLE_SIZE)]; /**< */ +} TraceEntryTableBuffer_t; + +/** + * @internal Initialize trace entry table. + * + * This routine initializes the trace entry table which maps objects to + * symbolic identifiers, state information, and options. + * + * @param[in] pxBuffer Pointer to uninitialized trace entry table buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryTableInitialize(TraceEntryTableBuffer_t* pxBuffer); + +/** + * @brief Creates trace entry. + * + * @param[out] pxEntryHandle Pointer to uninitialized trace entry handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryCreate(TraceEntryHandle_t *pxEntryHandle); + +/** + * @brief Deletes trace entry. + * + * @param[in] xEntryHandle Pointer to initialized trace entry handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryDelete(TraceEntryHandle_t xEntryHandle); + +/** + * @brief Finds trace entry mapped to object address. + * + * @param[in] pvAddress Address of object. + * @param[out] pxEntryHandle Pointer to uninitialized trace entry handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryFind(void* pvAddress, TraceEntryHandle_t* pxEntryHandle); + +/** + * @brief Gets the number of entries in the trace entry table. + * + * @param[out] puiCount Count. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryGetCount(uint32_t* puiCount); + +/** + * @brief Gets trace table entry at index. + * + * @param[in] index Entry index. + * @param[out] pxEntryHandle Pointer to uninitialized trace entry handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryGetAtIndex(uint32_t index, TraceEntryHandle_t* pxEntryHandle); + +/** + * @brief Sets symbol for entry. + * + * @param[in] xEntryHandle Pointer to initialized trace entry handle. + * @param[out] szSymbol Pointer to symbol string, set by function + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntrySetSymbol(TraceEntryHandle_t xEntryHandle, const char* szSymbol); + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +/** + * @brief Creates trace entry mapped to memory address. + * + * @param[in] pvAddress Address. + * @param[out] pxEntryHandle Pointer to uninitialized trace entry handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryCreateWithAddress(void* pvAddress, TraceEntryHandle_t* pxEntryHandle); + +/** + * @brief Sets trace entry state. + * + * @param[in] xEntryHandle Pointer to initialized trace entry handle. + * @param[in] uiStateIndex Index of state (< TRC_ENTRY_TABLE_STATE_COUNT). + * @param[in] uxState State. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntrySetState(TraceEntryHandle_t xEntryHandle, uint32_t uiStateIndex, TraceUnsignedBaseType_t uxState); + +/** + * @brief Sets trace entry option(s). + * + * @param[in] xEntryHandle Pointer to initialized trace entry handle. + * @param[in] uiMask Option(s) set mask. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntrySetOptions(TraceEntryHandle_t xEntryHandle, uint32_t uiMask); + +/** + * @brief Clears trace entry option(s). + * + * @param[in] xEntryHandle Pointer to initialized trace entry handle. + * @param[in] uiMask Options(s) clear mask. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryClearOptions(TraceEntryHandle_t xEntryHandle, uint32_t uiMask); + +/** + * @brief Gets linked address for trace entry. + * + * @param[in] xEntryHandle Pointer to initialized trace entry handle. + * @param[out] ppvAddress Address. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryGetAddress(TraceEntryHandle_t xEntryHandle, void **ppvAddress); + +/** + * @brief Gets symbol for trace entry. + * + * @param[in] xEntryHandle Pointer to initialized trace entry handle. + * @param[out] pszSymbol Symbol. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryGetSymbol(TraceEntryHandle_t xEntryHandle, const char** pszSymbol); + +/** + * @brief Gets state for trace entry. + * + * @param[in] xEntryHandle Pointer to initialized trace entry handle. + * @param[in] uiStateIndex State index (< TRC_ENTRY_TABLE_STATE_COUNT). + * @param[out] puxState State. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryGetState(TraceEntryHandle_t xEntryHandle, uint32_t uiStateIndex, TraceUnsignedBaseType_t *puxState); + +/** + * @brief Gets options for trace entry. + * + * @param[in] xEntryHandle Pointer to initialized trace entry handle. + * @param[out] puiOptions Options. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEntryGetOptions(TraceEntryHandle_t xEntryHandle, uint32_t *puiOptions); + +#else + +#define xTraceEntryCreateWithAddress TRC_ENTRY_CREATE_WITH_ADDRESS + +#define xTraceEntrySetState TRC_ENTRY_SET_STATE +#define xTraceEntrySetOptions TRC_ENTRY_SET_OPTIONS +#define xTraceEntryClearOptions TRC_ENTRY_CLEAR_OPTIONS + +#define xTraceEntryGetAddress TRC_ENTRY_GET_ADDRESS +#define xTraceEntryGetSymbol TRC_ENTRY_GET_SYMBOL +#define xTraceEntryGetState TRC_ENTRY_GET_STATE +#define xTraceEntryGetOptions TRC_ENTRY_GET_OPTIONS + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_ENTRY_TABLE_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcError.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcError.h new file mode 100644 index 0000000000..414e078df3 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcError.h @@ -0,0 +1,99 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace error APIs. + */ + +#ifndef TRC_ERROR_H +#define TRC_ERROR_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_assert_apis Trace Asserts APIs + * @ingroup trace_recorder_apis + * @{ + */ + +#define TRC_ERROR_BUFFER_SIZE (sizeof(uint32_t) + sizeof(uint32_t) + sizeof(TraceStringHandle_t)) + +typedef struct TraceErrorBuffer +{ + uint32_t buffer[(TRC_ERROR_BUFFER_SIZE) / sizeof(uint32_t)]; +} TraceErrorBuffer_t; + +/** + * @internal Initializes the error system + * + * @param[in] pxBuffer Pointer to buffer + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceErrorInitialize(TraceErrorBuffer_t* pxBuffer); + +/** + * @brief Register a warning + * + * @param[in] uiErrorCode Label + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceWarning(uint32_t uiErrorCode); + +/** + * @brief Register an error + * + * @param[in] uiErrorCode Error code + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceError(uint32_t uiErrorCode); + +/** + * @brief Retrieve the string for the last error + * + * @param[out] pszError Error string pointer + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceErrorGetLast(const char** pszError); + +/** + * @brief Clears any errors + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceErrorClear(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_ERROR_H*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcEvent.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcEvent.h new file mode 100644 index 0000000000..16ac7830a2 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcEvent.h @@ -0,0 +1,615 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace event APIs. + */ + +#ifndef TRC_EVENT_H +#define TRC_EVENT_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_event_apis Trace Event APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @internal Macro helper for setting trace event parameter count. + */ +#define TRC_EVENT_SET_PARAM_COUNT(id, n) (((uint16_t)(id)) | ((((uint16_t)(n)) & 0xF) << 12)) + +/** + * @internal Macro helper for getting trace event parameter count. + */ +#define TRC_EVENT_GET_PARAM_COUNT(id) (((id) >> 12) & 0xF) + +#if (TRC_CFG_CORE_COUNT > 1) +#define TRC_EVENT_SET_EVENT_COUNT(c) (((TRC_CFG_GET_CURRENT_CORE() & 0xF) << 12) | ((uint16_t)(c) & 0xFFF)) +#else +#define TRC_EVENT_SET_EVENT_COUNT(c) (uint16_t)(c) +#endif + +/** + * @internal Macro helpder for setting base event data. + */ +#define SET_BASE_EVENT_DATA(pxEvent, eventId, paramCount, eventCount) \ + ( \ + (pxEvent)->EventID = TRC_EVENT_SET_PARAM_COUNT(eventId, paramCount), \ + (pxEvent)->EventCount = TRC_EVENT_SET_EVENT_COUNT(eventCount), \ + xTraceTimestampGet(&(pxEvent)->TS) \ + ) + +/** + * @internal Macro helper for resetting trace event data. + */ +#define RESET_EVENT_DATA(p) \ + ( \ + (p)->pvBlob = 0, \ + (p)->size = 0, \ + (p)->offset = 0 \ + ) + +/** + * @internal Macro optimization for getting trace event size. + */ +#define TRC_EVENT_GET_SIZE(pvAddress, puiSize) (*(uint32_t*)(puiSize) = sizeof(TraceBaseEvent_t) + (TRC_EVENT_GET_PARAM_COUNT(((TraceBaseEvent_t*)(pvAddress))->EventID)) * sizeof(uint32_t), TRC_SUCCESS) + +/** + * @internal Macro optimization for getting trace event data pointer with an offset. + */ +#define TRC_EVENT_GET_RAW_DATA(xEventHandle, uiOffset, uiSize, ppvData) ((void)(uiSize), *(void**)(ppvData) = (void*)&((uint8_t*)((TraceEventData_t*)(xEventHandle))->pvBlob)[uiOffset], TRC_SUCCESS) + +/** + * @internal Macro optimization for getting trace event payload pointer with an offset. + */ +#define TRC_EVENT_GET_PAYLOAD(xEventHandle, uiOffset, uiSize, ppvData) ((void)(uiSize), *(void**)(ppvData) = (void*)&((uint8_t*)((TraceEventData_t*)(xEventHandle))->pvBlob)[sizeof(TraceBaseEvent_t) + (uiOffset)], TRC_SUCCESS) + +/** + * @internal Macro optimization for getting trace event remaining payload size. + */ +#define TRC_EVENT_PAYLOAD_REMAINING(xEventHandle, puiValue) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(uint32_t*)(puiValue) = ((TraceEventData_t*)(xEventHandle))->size - ((TraceEventData_t*)(xEventHandle))->offset, TRC_SUCCESS) + +/** + * @internal Macro optimization for getting trace event used payload size. + */ +#define TRC_EVENT_PAYLOAD_USED(xEventHandle, puiValue) (*(uint32_t*)(puiValue) = ((TraceEventData_t*)(xEventHandle))->offset - sizeof(TraceBaseEvent_t), TRC_SUCCESS) + +/** + * @internal Macro optimization getting trace event payload size. + */ +#define TRC_EVENT_PAYLOAD_SIZE(xEventHandle, puiValue) (*(uint32_t*)(puiValue) = ((TraceEventData_t*)(xEventHandle))->size - sizeof(TraceBaseEvent_t), TRC_SUCCESS) + +/** + * @internal Macro optimization for adding a pointer address to trace event. + */ +#define TRC_EVENT_ADD_POINTER(xEventHandle, value) \ + TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3( \ + ((void**)((TraceEventData_t*)(xEventHandle))->pvBlob)[((TraceEventData_t*)(xEventHandle))->offset / sizeof(void*)] = (value), \ + ((TraceEventData_t*)(xEventHandle))->offset += sizeof(void*), \ + TRC_SUCCESS \ + ) + +/** + * @internal Macro optimization for adding a unsigned base type to trace event. + */ +#define TRC_EVENT_ADD_UNSIGNED_BASE_TYPE(xEventHandle, value) \ + TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3( \ + ((TraceUnsignedBaseType_t*)((TraceEventData_t*)(xEventHandle))->pvBlob)[((TraceEventData_t*)(xEventHandle))->offset / sizeof(TraceUnsignedBaseType_t)] = (value), \ + ((TraceEventData_t*)(xEventHandle))->offset += sizeof(TraceUnsignedBaseType_t), \ + TRC_SUCCESS \ + ) + +/** + * @internal Macro optimization for adding a 32-bit value to trace event. + */ +#define TRC_EVENT_ADD_32(xEventHandle, value) \ + TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3( \ + ((uint32_t*)((TraceEventData_t*)(xEventHandle))->pvBlob)[((TraceEventData_t*)(xEventHandle))->offset / sizeof(uint32_t)] = (value), \ + ((TraceEventData_t*)(xEventHandle))->offset += sizeof(uint32_t), \ + TRC_SUCCESS \ + ) + +/** + * @internal Macro optimization for adding a 16-bit value to trace event. + */ +#define TRC_EVENT_ADD_16(xEventHandle, value) \ + TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3( \ + ((uint16_t*)((TraceEventData_t*)(xEventHandle))->pvBlob)[((TraceEventData_t*)(xEventHandle))->offset / sizeof(uint16_t)] = (value), \ + ((TraceEventData_t*)(xEventHandle))->offset += sizeof(uint16_t), \ + TRC_SUCCESS \ + ) + +/** + * @internal Macro optimization for adding a 8-bit value to trace event. + */ +#define TRC_EVENT_ADD_8(xEventHandle, value) \ + TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3( \ + ((uint8_t*)((TraceEventData_t*)(xEventHandle))->pvBlob)[((TraceEventData_t*)(xEventHandle))->offset / sizeof(uint8_t)] = (value), \ + ((TraceEventData_t*)(xEventHandle))->offset += sizeof(uint8_t), \ + TRC_SUCCESS \ + ) + +/** + * @internal Macro optimization for beginning an offline trace event. + */ +#define TRC_EVENT_BEGIN_OFFLINE(uiEventCode, uiPayloadSize, pxEventHandle) \ + ( \ + (xTraceEventBeginRawOffline(sizeof(TraceBaseEvent_t) + (uiPayloadSize), pxEventHandle)) == TRC_SUCCESS ? \ + ( \ + pxTraceEventDataTable->coreEventData[TRC_CFG_GET_CURRENT_CORE()].eventCounter++, \ + SET_BASE_EVENT_DATA((TraceBaseEvent_t*)(((TraceEventData_t*)*(pxEventHandle))->pvBlob), \ + uiEventCode, \ + (((TraceEventData_t*)*(pxEventHandle))->size - sizeof(TraceBaseEvent_t)) / sizeof(uint32_t), \ + pxTraceEventDataTable->coreEventData[TRC_CFG_GET_CURRENT_CORE()].eventCounter), \ + ((TraceEventData_t*)*(pxEventHandle))->offset += sizeof(TraceBaseEvent_t), \ + TRC_SUCCESS \ + ) : TRC_FAIL \ + ) + +/** + * @internal Macro optimization for ending an offline trace event. + */ +#define TRC_EVENT_END_OFFLINE(xEventHandle) \ + TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4( \ + xTraceStreamPortCommit(((TraceEventData_t*)(xEventHandle))->pvBlob, \ + ((TraceEventData_t*)(xEventHandle))->size, &DUMMY_iTraceBytesCommitted), \ + RESET_EVENT_DATA((TraceEventData_t*)(xEventHandle)), \ + TRC_SUCCESS \ + ) + +/** + * @internal Trace Base Event Structure + */ +typedef struct { + uint16_t EventID; /**< */ + uint16_t EventCount; /**< */ + uint32_t TS; /**< */ +} TraceBaseEvent_t; + +/** + * @internal Trace Event Data Structure + */ +typedef struct TraceEventData +{ + void* pvBlob; /**< */ + uint32_t size; /**< */ + uint32_t offset; /**< */ +} TraceEventData_t; + +/** + * @internal Trace Core Event Data Structure + */ +typedef struct TraceCoreEventData +{ + TraceEventData_t eventData[(TRC_CFG_MAX_ISR_NESTING)+1]; /**< */ + uint32_t eventCounter; /**< */ +} TraceCoreEventData_t; + +/** + * @internal Trace Event Data Table Structure. + */ +typedef struct TraceEventDataTable +{ + TraceCoreEventData_t coreEventData[TRC_CFG_CORE_COUNT]; /**< Holds data about current event for each core/isr depth */ +} TraceEventDataTable_t; + +#define TRC_EVENT_DATA_BUFFER_SIZE (sizeof(TraceEventDataTable_t)) + +/** + * @internal Trace Event Data Buffer Structure. + */ +typedef struct TraceEventDataBuffer +{ + uint8_t buffer[TRC_EVENT_DATA_BUFFER_SIZE]; /**< */ +} TraceEventDataBuffer_t; + +extern TraceEventDataTable_t* pxTraceEventDataTable; + +/** + * @internal Initialize event trace system. + * + * @param[in] pxBuffer Pointer to memory that will be used by the event + * trace system. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventInitialize(TraceEventDataBuffer_t* pxBuffer); + +/** + * @brief Gets trace event size. + * + * @param[in] pvAddress Pointer to initialized trace event. + * @param[out] puiSize Size. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventGetSize(void* pvAddress, uint32_t* puiSize); + +/** + * @internal Begins a raw trace event offline. + * + * This routine begins a trace event with specified size. Must call xTraceEventEnd() + * to finalize event creation. Does not care about RecorderEnabled. + * + * @param[in] uiSize Size. + * @param[in] pxEventHandle Pointer to initialized trace event. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventBeginRawOffline(uint32_t uiSize, TraceEventHandle_t* pxEventHandle); + +/** + * @internal Begins a blocking trace event offline. + * + * This routine begins a trace event with specified size. Must call xTraceEventEnd() + * to finalize event creation. Does not care about RecorderEnabled. + * + * @param[in] uiSize Size. + * @param[in] pxEventHandle Pointer to initialized trace event. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventBeginRawOfflineBlocking(uint32_t uiSize, TraceEventHandle_t* pxEventHandle); + +/** + * @internal Begins a trace event offline. + * + * This routine begins a trace event with specified size. Must call xTraceEventEnd() + * to finalize event creation. Does not care about RecorderEnabled. + * + * @param[in] uiSize Size. + * @param[in] pxEventHandle Pointer to initialized trace event. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventBeginOffline TRC_EVENT_BEGIN_OFFLINE + +/** + * @brief Begins a trace event. + * + * This routine begins a trace event with specified size. Must call xTraceEventEnd() + * to finalize event creation. Does not care about RecorderEnabled. + * + * @param[in] uiSize Size. + * @param[in] pxEventHandle Pointer to initialized trace event. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventBegin(uiEventCode, uiTotalPayloadSize, pxEventHandle) \ + (xTraceIsRecorderEnabled() ? xTraceEventBeginOffline(uiEventCode, uiTotalPayloadSize, pxEventHandle) : TRC_FAIL) + +/** + * @internal Ends a trace event offline. + * + * This routine ends the event that was begun by calling on xTraceEventBegin(). + * Does not care about uiRecorderEnabled. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventEndOffline(TraceEventHandle_t xEventHandle); + +/** + * @internal Ends a blocking event offline. + * + * Ends the event that was begun by calling on xTraceEventBegin() + * + * @param[in] xEventHandle Pointer to initialized trace event. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventEndOfflineBlocking(TraceEventHandle_t xEventHandle); + +/** + * @brief Ends a trace event. + * + * This routine ends the event that was begun by calling on xTraceEventBegin(). + * Does not care about uiRecorderEnabled. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventEnd(xEventHandle) \ + (xTraceIsRecorderEnabled() == 0 ? TRC_FAIL : xTraceEventEndOffline(xEventHandle)) + +/** + * @brief Adds data to event payload. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] pvData Pointer to data. + * @param[in] uiSize Size. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventAddData(TraceEventHandle_t xEventHandle, void* pvData, uint32_t uiSize); + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +/** + * @brief Gets trace event data pointer with an offset. + * + * This routine gets a trace event data pointer with an offset. It also verfies + * that the size so it won't go outside its buffer. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] uiOffset Offset. + * @param[in] uiSize Size. + * @param[out] ppvData Data. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventGetRawData(TraceEventHandle_t xEventHandle, uint32_t uiOffset, uint32_t uiSize, void** ppvData); + +/** + * @brief Gets trace event payload pointer with an offset. + * + * This routine gets a trace event payload pointer with an offset. It also verifies + * that the size so it won't go outside its payload buffer. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] uiOffset Offset. + * @param[in] uiSize Size. + * @param[out] ppvData Data. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventGetPayload(TraceEventHandle_t xEventHandle, uint32_t uiOffset, uint32_t uiSize, void** ppvData); + +/** + * @brief Gets the amount of remaining trace event payload. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[out] puiValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventPayloadRemaining(TraceEventHandle_t xEventHandle, uint32_t* puiValue); + +/** + * @brief Gets the amount of used trace event payload. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[out] puiValue Value + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventPayloadUsed(TraceEventHandle_t xEventHandle, uint32_t* puiValue); + +/** + * @brief Gets trace event payload size. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[out] puiValue Value + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventPayloadSize(TraceEventHandle_t xEventHandle, uint32_t* puiValue); + +/** + * @brief Adds an unsigned base type value as trace event payload + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] uxValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventAddUnsignedBaseType(TraceEventHandle_t xEventHandle, TraceUnsignedBaseType_t uxValue); + +/** + * @brief Adds a pointer address as trace event payload + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] pvAddress Address. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventAddPointer(TraceEventHandle_t xEventHandle, void *pvAddress); + +/** + * @brief Adds an uint32_t as trace event payload + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] value Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventAdd32(TraceEventHandle_t xEventHandle, uint32_t value); + +/** + * @brief Adds an uint16_t as trace event payload + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] value Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventAdd16(TraceEventHandle_t xEventHandle, uint16_t value); + +/** + * @brief Adds an uint8_t as trace event payload. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] value Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventAdd8(TraceEventHandle_t xEventHandle, uint8_t value); + +#else /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/** + * @brief Gets trace event size. + * + * @param[in] pvAddress Pointer to initialized trace event. + * @param[out] puiSize Size. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventGetSize(pvAddress, puiSize) (*(uint32_t*)(puiSize) = sizeof(TraceBaseEvent_t) + (TRC_EVENT_GET_PARAM_COUNT(((TraceBaseEvent_t*)(pvAddress))->EventID)) * sizeof(uint32_t), TRC_SUCCESS) + +/** + * @brief Gets trace event data pointer with an offset. + * + * This routine gets a trace event data pointer with an offset. It also verfies + * that the size so it won't go outside its buffer. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] uiOffset Offset. + * @param[in] uiSize Size. + * @param[out] ppvData Data. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventGetRawData TRC_EVENT_GET_RAW_DATA + +/** + * @brief Gets trace event payload pointer with an offset. + * + * This routine gets a trace event payload pointer with an offset. It also verifies + * that the size so it won't go outside its payload buffer. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] uiOffset Offset. + * @param[in] uiSize Size. + * @param[out] ppvData Data. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventGetPayload TRC_EVENT_GET_PAYLOAD + +/** + * @brief Gets the amount of remaining trace event payload. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[out] puiValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventPayloadRemaining TRC_EVENT_PAYLOAD_REMAINING + +/** + * @brief Gets the amount of used trace event payload. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[out] puiValue Value + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventPayloadUsed TRC_EVENT_PAYLOAD_USED + +/** + * @brief Gets trace event payload size. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[out] puiValue Value + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventPayloadSize TRC_EVENT_PAYLOAD_SIZE + +/* Adds a pointer as event payload with no errors checks */ +#define xTraceEventAddPointer TRC_EVENT_ADD_POINTER + +/** + * @brief Adds an unsigned base type value as trace event payload + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] uxValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventAddUnsignedBaseType TRC_EVENT_ADD_UNSIGNED_BASE_TYPE + +/** + * @brief Adds an uint32_t as trace event payload + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] value Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventAdd32 TRC_EVENT_ADD_32 + +/** + * @brief Adds an uint16_t as trace event payload + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] value Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventAdd16 TRC_EVENT_ADD_16 + +/** + * @brief Adds an uint8_t as trace event payload. + * + * @param[in] xEventHandle Pointer to initialized trace event. + * @param[in] value Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceEventAdd8 TRC_EVENT_ADD_8 + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_EVENT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcEventBuffer.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcEventBuffer.h new file mode 100644 index 0000000000..9d70a7a805 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcEventBuffer.h @@ -0,0 +1,132 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace event buffer APIs. + */ + +#ifndef TRC_EVENT_BUFFER_H +#define TRC_EVENT_BUFFER_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_event_buffer_apis Trace Event Buffer APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @def TRC_EVENT_BUFFER_OPTION_SKIP + * @brief Buffer should skip new events when full + */ +#define TRC_EVENT_BUFFER_OPTION_SKIP (0U) + +/** + * @def TRC_EVENT_BUFFER_OPTION_OVERWRITE + * @brief Buffer should overwrite old events when full + */ +#define TRC_EVENT_BUFFER_OPTION_OVERWRITE (1U) + +/** + * @brief Trace Event Buffer Structure + */ +typedef struct TraceEventBuffer +{ + uint32_t uiHead; /**< Head index of buffer */ + uint32_t uiTail; /**< Tail index of buffer */ + uint32_t uiSize; /**< Buffer size */ + uint32_t uiOptions; /**< Options (skip/overwrite when full) */ + uint32_t uiDroppedEvents; /**< Nr of dropped events */ + uint32_t uiFree; /**< Nr of free bytes */ + uint32_t uiTimerWraparounds; /**< Nr of timer wraparounds */ + uint8_t* puiBuffer; /**< Trace Event Buffer: may be NULL */ +} TraceEventBuffer_t; + +/** + * @internal Initialize trace event buffer. + * + * This routine initializes a trace event buffer and assigns it a + * memory area based on the supplied buffer. + * + * Trace event buffer options specifies the buffer behavior regarding + * old data, the alternatives are TRC_EVENT_BUFFER_OPTION_SKIP and + * TRC_EVENT_BUFFER_OPTION_OVERWRITE (mutal exclusive). + * + * @param[out] pxTraceEventBuffer Pointer to uninitialized trace event buffer. + * @param[in] uiOptions Trace event buffer options. + * @param[in] puiBuffer Pointer to buffer that will be used by the trace event buffer. + * @param[in] uiSize Size of buffer + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventBufferInitialize(TraceEventBuffer_t * pxTraceEventBuffer, uint32_t uiOptions, + uint8_t *puiBuffer, uint32_t uiSize); + +/** + * @brief Pushes data into trace event buffer. + * + * This routine attempts to push data into the trace event buffer. + * + * @param[in] pxTraceEventBuffer Pointer to initialized trace event buffer. + * @param[in] pxData Pointer to data that should be pushed into trace event buffer. + * @param[in] uiSize Size of data. + * @param[out] piBytesWritten Bytes written. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventBufferPush(TraceEventBuffer_t *pxTraceEventBuffer, void *pxData, uint32_t uiSize, int32_t *piBytesWritten); + +/** + * @brief Transfer trace event buffer data through streamport. + * + * This routine will attempt to transfer all existing data in the trace event + * buffer through the streamport. New data pushed to the trace event buffer + * during the execution of this routine will not be transfered to + * + * @param[in] pxTraceEventBuffer Pointer to initialized trace event buffer. + * @param[out] piBytesWritten Bytes written. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventBufferTransfer(TraceEventBuffer_t* pxTraceEventBuffer, int32_t* piBytesWritten); + +/** + * @brief Clears all data from event buffer. + * + * @param[in] pxTraceEventBuffer Pointer to initialized trace event buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEventBufferClear(TraceEventBuffer_t* pxTraceEventBuffer); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_EVENT_BUFFER_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcExtension.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcExtension.h new file mode 100644 index 0000000000..0acb19c085 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcExtension.h @@ -0,0 +1,93 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace extension APIs. + */ + +#ifndef TRC_EXTENSION_H +#define TRC_EXTENSION_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_extension_apis Trace Extension APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @brief Creates trace extension. + * + * @param[in] szName Name. + * @param[in] uiMajor Major version. + * @param[in] uiMinor Minor version. + * @param[in] uiPatch Patch version. + * @param[in] uiEventCount Event count. + * @param[out] pxExtensionHandle Pointer to uninitialized extension handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceExtensionCreate(const char *szName, uint8_t uiMajor, uint8_t uiMinor, uint16_t uiPatch, uint32_t uiEventCount, TraceExtensionHandle_t *pxExtensionHandle); + +/** + * @brief Gets extension base event id. + * + * @param[in] xExtensionHandle Pointer to initialized extension handle. + * @param[out] puiBaseEventId Base event id. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceExtensionGetBaseEventId(TraceExtensionHandle_t xExtensionHandle, uint32_t *puiBaseEventId); + +/** + * @brief Gets extension event id. + * + * @param[in] xExtensionHandle Pointer to initialized extension handle. + * @param[in] uiLocalEventId Local event id. + * @param[out] puiGlobalEventId Global event id. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceExtensionGetEventId(TraceExtensionHandle_t xExtensionHandle, uint32_t uiLocalEventId, uint32_t *puiGlobalEventId); + +/** + * @brief Gets extension configuration name. + * + * @param[in] xExtensionHandle Pointer to initialized extension handle. + * @param[out] pszName Name. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceExtensionGetConfigName(TraceExtensionHandle_t xExtensionHandle, const char **pszName); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_EXTENSION_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcExtensions.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcExtensions.h deleted file mode 100644 index df5f0d8f20..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcExtensions.h +++ /dev/null @@ -1,422 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 e95170da71..febe7272fa 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h @@ -1,558 +1,714 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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*/ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The hardware abstraction layer for the trace recorder. + */ + +#ifndef TRC_HARDWARE_PORT_H +#define TRC_HARDWARE_PORT_H + +#include + + +#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 * TRC_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 */ +void vTraceTimerReset(void); +uint32_t uiTraceTimerGetFrequency(void); +uint32_t uiTraceTimerGetValue(void); + +#define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR +#define TRC_HWTC_COUNT ((TraceUnsignedBaseType_t)uiTraceTimerGetValue()) +#define TRC_HWTC_PERIOD 0 +#define TRC_HWTC_DIVISOR 1 +#define TRC_HWTC_FREQ_HZ ((TraceUnsignedBaseType_t)uiTraceTimerGetFrequency()) + +#define TRC_IRQ_PRIORITY_ORDER 1 + +#define TRC_PORT_SPECIFIC_INIT() vTraceTimerReset() + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win64) +/* This can be used as a template for any free-running 32-bit counter */ +void vTraceTimerReset(void); +uint32_t uiTraceTimerGetFrequency(void); +uint32_t uiTraceTimerGetValue(void); + +#define TRC_BASE_TYPE int64_t + +#define TRC_UNSIGNED_BASE_TYPE uint64_t + +#define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR +#define TRC_HWTC_COUNT ((TraceUnsignedBaseType_t)uiTraceTimerGetValue()) +#define TRC_HWTC_PERIOD 0 +#define TRC_HWTC_DIVISOR 1 +#define TRC_HWTC_FREQ_HZ ((TraceUnsignedBaseType_t)uiTraceTimerGetFrequency()) + +#define TRC_IRQ_PRIORITY_ORDER 1 + +#define TRC_PORT_SPECIFIC_INIT() vTraceTimerReset() + +#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 TRC_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 + + #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);} + + /************************************************************************** + * 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 xTraceHardwarePortInitCortexM(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() xTraceHardwarePortInitCortexM() + + #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) + #define TRACE_ALLOC_CRITICAL_SECTION() TraceBaseType_t __x_irq_status; + #define TRACE_ENTER_CRITICAL_SECTION() { __x_irq_status = TRC_KERNEL_PORT_SET_INTERRUPT_MASK(); } + #define TRACE_EXIT_CRITICAL_SECTION() { TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK(__x_irq_status); } + + #include + + #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 (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 1 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_MICROCHIP_PIC24_PIC32) + + #define TRACE_ALLOC_CRITICAL_SECTION() TraceBaseType_t __x_irq_status; + #define TRACE_ENTER_CRITICAL_SECTION() { __x_irq_status = TRC_KERNEL_PORT_SET_INTERRUPT_MASK(); } + #define TRACE_EXIT_CRITICAL_SECTION() { TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK(__x_irq_status); } + + #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 (TRC_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 (TRC_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 (TRC_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 (TRC_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 (TRC_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 (TRC_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 / TRC_TICK_RATE_HZ) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRC_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 / TRC_TICK_RATE_HZ) + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (TRC_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 + + #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR + #define TRC_HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 ) + #define TRC_HWTC_PERIOD (XTmrCtr_GetLoadReg( XPAR_TMRCTR_0_BASEADDR, 0) + 1) + #define TRC_HWTC_DIVISOR 16 + #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) + #define TRC_IRQ_PRIORITY_ORDER 0 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_ZyncUltraScaleR5) + + 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); } + + #include + + #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 * TRC_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 + #include + + #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);} + + #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 (TRC_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. + **************************************************************************/ + + 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); } + + /* 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 (TRC_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_CYCLONE_V_HPS) + #include "alt_clock_manager.h" + + 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); } + + #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR + #define TRC_HWTC_COUNT *((uint32_t *)0xFFFEC200) + #define TRC_HWTC_PERIOD 0 + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ (({ \ + uint32_t __freq; \ + alt_clk_freq_get( ALT_CLK_MPU_PERIPH, &__freq ); \ + __freq; \ + })) + #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_ZEPHYR) + #define TRACE_ALLOC_CRITICAL_SECTION() int key; + #define TRACE_ENTER_CRITICAL_SECTION() { key = irq_lock(); } + #define TRACE_EXIT_CRITICAL_SECTION() { irq_unlock(key); } + + #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR + #define TRC_HWTC_COUNT k_cycle_get_32() + #define TRC_HWTC_PERIOD (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC) + #define TRC_HWTC_DIVISOR 4 + #define TRC_HWTC_FREQ_HZ CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC + #define TRC_IRQ_PRIORITY_ORDER 0 // Lower IRQ priority values are more significant + + #define TRC_PORT_SPECIFIC_INIT() + +#elif ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XTensa_LX6) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XTensa_LX7)) + /** + * @note When running with SMP FreeRTOS we cannot use the CCOUNT register for timestamping, + * instead we use the external 40MHz timer for synchronized timestamping between the cores. + */ + #if CONFIG_FREERTOS_UNICORE == 1 + #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR + #define TRC_HWTC_COUNT ({ unsigned int __ccount; \ + __asm__ __volatile__("rsr.ccount %0" : "=a"(__ccount)); \ + __ccount; }) +#ifdef CONFIG_IDF_TARGET_ESP32 + #define TRC_HWTC_FREQ_HZ (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000) +#elif defined(CONFIG_IDF_TARGET_ESP32S2) + #define TRC_HWTC_FREQ_HZ (CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000) +#else + #error "Invalid IDF target, check your sdkconfig." +#endif + #define TRC_HWTC_PERIOD 0 + #define TRC_HWTC_DIVISOR 4 + #define TRC_IRQ_PRIORITY_ORDER 0 + #else + /** + * @brief Fetch core agnostic timestamp using the external 40MHz timer. This is used by tracerecorder + * when running with both cores. + * + * @return Ticks since the timer started + */ + uint32_t prvGetSMPTimestamp(); + + #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR + #define TRC_HWTC_COUNT prvGetSMPTimestamp() + #define TRC_HWTC_FREQ_HZ 40000000 + #define TRC_HWTC_PERIOD 0 + #define TRC_HWTC_DIVISOR 4 + #define TRC_IRQ_PRIORITY_ORDER 0 + #endif + + #if !defined(TRC_HWTC_FREQ_HZ) + #error "The XTensa LX6/LX7 trace hardware clock frequency is not defined." + #endif + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_RISCV_RV32I) + #define TRACE_ALLOC_CRITICAL_SECTION() unsigned int __irq_status; + #define TRACE_ENTER_CRITICAL_SECTION() __asm__ __volatile__("csrr %0, mstatus \n\t" \ + "csrci mstatus, 8 \n\t" \ + "andi %0, %0, 8 \n\t" \ + : "=r"(__irq_status)) + #define TRACE_EXIT_CRITICAL_SECTION() __asm__ __volatile__("csrr a1, mstatus \n\t" \ + "or %0, %0, a1 \n\t" \ + "csrs mstatus, %0 \n\t" \ + : \ + : "r" (__irq_status) \ + : "a1") + #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR + #define TRC_HWTC_COUNT ({ unsigned int __count; \ + __asm__ __volatile__("rdcycle %0" : "=r"(__count)); \ + __count; }) + #define TRC_HWTC_PERIOD 0 + #define TRC_HWTC_DIVISOR 1 + #define TRC_HWTC_FREQ_HZ 16000000 + #define TRC_IRQ_PRIORITY_ORDER 0 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XMOS_XCOREAI) + #define TRC_PORT_SPECIFIC_INIT() + #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR + #define TRC_HWTC_COUNT xscope_gettime() + #define TRC_HWTC_PERIOD (configCPU_CLOCK_HZ / configTICK_RATE_HZ ) + #define TRC_HWTC_DIVISOR 4 + #define TRC_HWTC_FREQ_HZ 100000000 + #define TRC_IRQ_PRIORITY_ORDER 0 + +#elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_POWERPC_Z4) + + /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ + + #define TRACE_ALLOC_CRITICAL_SECTION() TraceBaseType_t __x_irq_status; + #define TRACE_ENTER_CRITICAL_SECTION() { __x_irq_status = TRC_KERNEL_PORT_SET_INTERRUPT_MASK(); } + #define TRACE_EXIT_CRITICAL_SECTION() { TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK(__x_irq_status); } + + #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 + +#ifndef TRACE_ALLOC_CRITICAL_SECTION +#define TRACE_ALLOC_CRITICAL_SECTION() TRC_KERNEL_PORT_ALLOC_CRITICAL_SECTION() +#endif +#ifndef TRACE_ENTER_CRITICAL_SECTION + #define TRACE_ENTER_CRITICAL_SECTION() TRC_KERNEL_PORT_ENTER_CRITICAL_SECTION() +#endif +#ifndef TRACE_EXIT_CRITICAL_SECTION +#define TRACE_EXIT_CRITICAL_SECTION() TRC_KERNEL_PORT_EXIT_CRITICAL_SECTION() +#endif + +#endif /*TRC_SNAPSHOT_HARDWARE_PORT_H*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHeap.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHeap.h new file mode 100644 index 0000000000..bdff67b6e0 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHeap.h @@ -0,0 +1,135 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace heap APIs. + */ + +#ifndef TRC_HEAP_H +#define TRC_HEAP_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#ifndef TRC_USE_HEAPS +#define TRC_USE_HEAPS 1 +#endif + +#if (TRC_USE_HEAPS == 1) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_heap_apis Trace Heap APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @brief Creates trace heap. + * + * @param[in] szName Name. + * @param[in] uxCurrent Current level. + * @param[in] uxHighWaterMark High water mark + * @param[in] uxMax Maximum level. + * @param[out] pxHeapHandle Pointer to uninitialized trace heap handle. + * @return traceResult + */ +traceResult xTraceHeapCreate(const char *szName, TraceUnsignedBaseType_t uxCurrent, TraceUnsignedBaseType_t uxHighWaterMark, TraceUnsignedBaseType_t uxMax, TraceHeapHandle_t *pxHeapHandle); + +/** + * @brief Signals trace heap alloc. + * + * @param[in] xHeapHandle Pointer to initialized trace heap handle. + * @param[in] pvAddress Address. + * @param[in] uxSize Size. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceHeapAlloc(TraceHeapHandle_t xHeapHandle, void *pvAddress, TraceUnsignedBaseType_t uxSize); + +/** + * @brief Signals trace heap free. + * + * @param[in] xHeapHandle Pointer to initialized trace heap handle. + * @param[in] pvAddress Address. + * @param[in] uxSize Size. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceHeapFree(TraceHeapHandle_t xHeapHandle, void* pvAddress, TraceUnsignedBaseType_t uxSize); + +/** + * @brief Gets trace heap current allocation size. + * + * @param[in] xHeapHandle Pointer to initialized trace heap handle. + * @param[out] puxCurrent Current. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceHeapGetCurrent(TraceHeapHandle_t xHeapHandle, TraceUnsignedBaseType_t *puxCurrent); + +/** + * @brief Gets trace heap high water mark. + * + * @param[in] xHeapHandle Pointer to initialized trace heap handle. + * @param[out] puxHighWaterMark High water mark. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceHeapGetHighWaterMark(TraceHeapHandle_t xHeapHandle, TraceUnsignedBaseType_t *puxHighWaterMark); + +/** + * @brief Gets trace heap max size. + * + * @param[in] xHeapHandle Pointer to initialized trace heap handle. + * @param[out] puxMax Max. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceHeapGetMax(TraceHeapHandle_t xHeapHandle, TraceUnsignedBaseType_t *puxMax); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#else + +#define xTraceHeapCreate(szName, uxCurrent, uxHighWaterMark, uxMax, pxHeapHandle) ((void)szName, (void)uxCurrent, (void)uxHighWaterMark, (void)uxMax, pxHeapHandle != 0 ? TRC_SUCCESS : TRC_FAIL) + +#define xTraceHeapAlloc(xHeapHandle, pvAddress, uxSize) ((void)xHeapHandle, (void)pvAddress, (void)uxSize, TRC_SUCCESS) + +#define xTraceHeapFree(xHeapHandle, pvAddress, uxSize) ((void)xHeapHandle, (void)pvAddress, (void)uxSize, TRC_SUCCESS) + +#define xTraceHeapGetCurrent(xHeapHandle, puxCurrent) ((void)xHeapHandle, puxCurrent != 0 ? *puxCurrent = 0 : 0, puxCurrent != 0 ? TRC_SUCCESS : TRC_FAIL) + +#define xTraceHeapGetHighWaterMark(xHeapHandle, puxHighWaterMark) ((void)xHeapHandle, puxHighWaterMark != 0 ? *puxHighWaterMark = 0 : 0, puxHighWaterMark != 0 ? TRC_SUCCESS : TRC_FAIL) + +#define xTraceHeapGetMax(xHeapHandle, puxMax) ((void)xHeapHandle, puxMax != 0 ? *puxMax = 0 : 0, puxMax != 0 ? TRC_SUCCESS : TRC_FAIL) + +#endif /* (TRC_USE_HEAPS == 1) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_HEAP_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcISR.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcISR.h new file mode 100644 index 0000000000..8c95d54193 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcISR.h @@ -0,0 +1,226 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace ISR APIs. + */ + +#ifndef TRC_ISR_H +#define TRC_ISR_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_isr_apis Trace ISR APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @internal Trace ISR Core Info Structure + */ +typedef struct TraceISRCoreInfo +{ + TraceISRHandle_t handleStack[TRC_CFG_MAX_ISR_NESTING]; /**< */ + int32_t stackIndex; /**< */ + int32_t isPendingContextSwitch; /**< */ +} TraceISRCoreInfo_t; + +/** + * @internal Trace ISR Info Structure + */ +typedef struct TraceISRInfo +{ + TraceISRCoreInfo_t coreInfos[TRC_CFG_CORE_COUNT]; /* ISR handles */ +} TraceISRInfo_t; + +/* We expose this to enable faster access */ +extern TraceISRInfo_t* pxTraceISRInfo; + +#define TRACE_ISR_INFO_BUFFER_SIZE (sizeof(TraceISRInfo_t)) + +/** + * @internal Trace ISR Info Buffer + */ +typedef struct TraceISRInfoBuffer +{ + uint8_t buffer[(TRACE_ISR_INFO_BUFFER_SIZE)]; /**< */ +} TraceISRInfoBuffer_t; + +/** + * @internal Initialize ISR trace system. + * + * @param[in] pxBuffer Pointer to memory that will be used by the ISR + * trace system. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceISRInitialize(TraceISRInfoBuffer_t *pxBuffer); + +/** + * @brief Registers trace ISR. + * + * This routine stores a name and priority level for an Interrupt Service Routine, + * to allow for better visualization. Returns a TraceISRHandle_t used by + * xTraceISRBegin/xTraceISREnd. + * + * Example: + * #define PRIO_OF_ISR_TIMER1 3 // the hardware priority of the interrupt + * TraceISRHandle_t xISRTimer1Handle = 0; // The ID set by the recorder + * ... + * xTraceISRRegister("ISRTimer1", PRIO_OF_ISR_TIMER1, &xISRTimer1Handle); + * ... + * void ISR_handler() + * { + * xTraceISRBegin(xISRTimer1Handle); + * ... + * xTraceISREnd(0); + * } + * + * @param[in] szName Name. + * @param[in] uiPriority Priority. + * @param[out] pxISRHandle Pointer to uninitialized ISR trace handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceISRRegister(const char* szName, uint32_t uiPriority, TraceISRHandle_t* pxISRHandle); + +/** + * @brief Registers the beginning of an Interrupt Service Routine. + * + * This routine register the beginning of an ISR using a TraceISRHandle_t. + * See xTraceISRRegister for and example of using ISR tracing. + * + * @param[in] xISRHandle Pointer to initialized ISR trace handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceISRBegin(TraceISRHandle_t xISRHandle); + +/** + * @brief Registers the end of an Interrupt Service Routine. + * + * This routine register the end of an ISR using a TraceISRHandle_t. + * See xTraceISRRegister for and example of using ISR tracing. + * + * The parameter uxIsTaskSwitchRequired 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. + * + * @param[in] xIsTaskSwitchRequired Task switch required. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceISREnd(TraceBaseType_t xIsTaskSwitchRequired); + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +/** + * @brief Gets current trace ISR nesting level. + * + * This routine gets the current trace ISR nesting level for the + * CPU on which it is called. + * + * @param[out] puiValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceISRGetCurrentNesting(int32_t* puiValue); + +/** + * @brief + * + * @return int32_t + */ +int32_t xTraceISRGetCurrentNestingReturned(void); + +/** + * @brief Gets current ISR trace handle. + * + * @param[out] pxISRHandle ISR Handle. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceISRGetCurrent(TraceISRHandle_t* pxISRHandle); + +#else /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/** + * @brief Gets current trace ISR nesting level. + * + * This routine gets the current trace ISR nesting level for the + * CPU on which it is called. + * + * @param[out] puiValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceISRGetCurrentNesting(puiValue) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(puiValue) = pxTraceISRInfo->coreInfos[TRC_CFG_GET_CURRENT_CORE()].stackIndex, TRC_SUCCESS) + +/** + * @brief + * + * @return int32_t + */ +#define xTraceISRGetCurrentNestingReturned() (pxTraceISRInfo->coreInfos[TRC_CFG_GET_CURRENT_CORE()].stackIndex) + +/** + * @brief Gets current trace ISR nesting level. + * + * This routine gets the current trace ISR nesting level for the + * CPU on which it is called. + * + * @param[out] puiValue Value. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceISRGetCurrent(pxISRHandle) (xTraceISRGetCurrentNestingReturned() >= 0 ? (*(pxISRHandle) = pxTraceISRInfo->coreInfos[TRC_CFG_GET_CURRENT_CORE()].handleStack[xTraceISRGetCurrentNestingReturned()], TRC_SUCCESS) : TRC_FAIL) + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/** @internal Deprecated - Provides backwards-compability with older recorders for now, will be removed in the future */ +TraceISRHandle_t xTraceSetISRProperties(const char* szName, uint32_t uiPriority); + +/** @internal Deprecated - Provides backwards-compability with older recorders for now, will be removed in the future */ +#define xTraceGetCurrentISRNesting(puiValue) xTraceISRGetCurrentNesting(puiValue) + +/** @internal Deprecated - Provides backwards-compability with older recorders for now, will be removed in the future */ +#define vTraceStoreISRBegin(xISRHandle) xTraceISRBegin(xISRHandle) + +/** @internal Deprecated - Provides backwards-compability with older recorders for now, will be removed in the future */ +#define vTraceStoreISREnd(xIsTaskSwitchRequired) xTraceISREnd(xIsTaskSwitchRequired) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_ISR_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcInternalEventBuffer.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcInternalEventBuffer.h new file mode 100644 index 0000000000..9e7d57429b --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcInternalEventBuffer.h @@ -0,0 +1,107 @@ +/* + * Percepio Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * + * @brief Public internal event buffer APIs. + */ + +#ifndef TRC_INTERNAL_BUFFER_H +#define TRC_INTERNAL_BUFFER_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#ifndef TRC_USE_INTERNAL_BUFFER +#define TRC_USE_INTERNAL_BUFFER 1 +#endif + +#if (TRC_USE_INTERNAL_BUFFER == 1) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_internal_event_buffer_apis Trace Internal Event Buffer APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @internal Initializes the internal trace event buffer used by certain stream ports. + * + * @param[in] puiBuffer Pointer to previously allocated memory buffer + * @param[in] uiSize Size of buffer + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceInternalEventBufferInitialize(uint8_t* puiBuffer, uint32_t uiSize); + +/** + * @brief Pushes data to the internal trace event buffer. + * + * @param[in] pvData Pointer to data + * @param[in] uiSize Size of data + * @param[out] piBytesWritten Bytes written. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceInternalEventBufferPush(void *pvData, uint32_t uiSize, int32_t *piBytesWritten); + +/** + * @brief Transfers all internal trace event buffer data using the function + * xTraceStreamPortWriteData(...) as defined in trcStreamPort.h. + * + * This function is intended to be called by the periodic TzCtrl task with a + * suitable delay (e.g. 10-100 ms). + * + * In case of errors from the streaming interface, it registers a warning + * (TRC_WARNING_STREAM_PORT_WRITE) provided by xTraceErrorGetLast(). + * + * @param[out] piBytesWritten Bytes written. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceInternalEventBufferTransfer(int32_t *piBytesWritten); + +/** + * @brief Clears all trace events in the internal trace event buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceInternalEventBufferClear(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#else /* (TRC_USE_INTERNAL_BUFFER == 1)*/ + +#define xTraceInternalEventBufferInitialize(puiBuffer, uiSize) ((void)uiSize, puiBuffer != 0 ? TRC_SUCCESS : TRC_FAIL) +#define xTraceInternalEventBufferPush(pvData, uiSize, piBytesWritten) ((void)uiSize, (void)piBytesWritten, pvData != 0 ? TRC_SUCCESS : TRC_FAIL) +#define xTraceInternalEventBufferTransfer(piBytesWritten) ((void)piBytesWritten, TRC_SUCCESS) +#define xTraceInternalEventBufferClear() (void)(TRC_SUCCESS) + +#endif /* (TRC_USE_INTERNAL_BUFFER == 1)*/ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_INTERNAL_BUFFER_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcInterval.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcInterval.h new file mode 100644 index 0000000000..3f962f1cc9 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcInterval.h @@ -0,0 +1,86 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace interval APIs. + */ + +#ifndef TRC_INTERVAL_H +#define TRC_INTERVAL_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_interval_apis Trace Interval APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @brief Creates trace interval. + * + * @param[in] szName Name. + * @param[out] pxIntervalHandle Pointer to uninitialized trace interval. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceIntervalCreate(const char *szName, TraceIntervalHandle_t *pxIntervalHandle); + +/** + * @brief Starts trace interval. + * + * @param[in] xIntervalHandle Pointer to initialized trace interval. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceIntervalStart(TraceIntervalHandle_t xIntervalHandle); + +/** + * @brief Stops trace interval. + * + * @param[in] xIntervalHandle Pointer to initialized trace interval. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceIntervalStop(TraceIntervalHandle_t xIntervalHandle); + +/** + * @brief Gets trace interval state. + * + * @param[in] xIntervalHandle Pointer to initialized trace interval. + * @param[out] puxState State. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceIntervalGetState(TraceIntervalHandle_t xIntervalHandle, uint32_t *puxState); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_INTERVAL_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h index b44b359716..8b88195792 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcKernelPort.h @@ -1,2792 +1,2971 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 -#define TRC_FREERTOS_VERSION_10_4_1 TRC_FREERTOS_VERSION_10_4_0 - -/* 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 */ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * FreeRTOS specific definitions needed by the trace recorder + */ + +#ifndef TRC_KERNEL_PORT_H +#define TRC_KERNEL_PORT_H + +#include +#include /* Defines configUSE_TRACE_FACILITY */ + +#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 +#define TRC_FREERTOS_VERSION_10_4_1 TRC_FREERTOS_VERSION_10_4_0 + +/* 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 TraceKernelPortTickType_t TickType_t + #define TraceKernelPortTaskHandle_t TaskHandle_t +#endif + +#if (defined(TRC_USE_TRACEALYZER_RECORDER)) && (TRC_USE_TRACEALYZER_RECORDER == 1) + +#define TRC_PLATFORM_CFG "FreeRTOS" +#define TRC_PLATFORM_CFG_MAJOR 1 +#define TRC_PLATFORM_CFG_MINOR 0 +#define TRC_PLATFORM_CFG_PATCH 0 + +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) + +/* Required for stack monitoring */ +#undef INCLUDE_uxTaskGetStackHighWaterMark +#define INCLUDE_uxTaskGetStackHighWaterMark 1 + +#endif + +/* INCLUDE_xTaskGetCurrentTaskHandle must be set to 1 for tracing to work properly */ +#undef INCLUDE_xTaskGetCurrentTaskHandle +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) +#include + +#define TRC_KERNEL_PORT_BUFFER_SIZE (sizeof(TraceHeapHandle_t) + sizeof(void*)) +#elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) +#define TRC_KERNEL_PORT_BUFFER_SIZE (sizeof(TraceUnsignedBaseType_t)) +#endif + +/** + * @internal The kernel port data buffer + */ +typedef struct TraceKernelPortDataBuffer +{ + uint8_t buffer[TRC_KERNEL_PORT_BUFFER_SIZE]; +} TraceKernelPortDataBuffer_t; + +/** + * @internal Initializes the kernel port + * + * @param[in] pxBuffer Kernel port data buffer + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t* pxBuffer); + +/** + * @internal Enables the kernel port + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceKernelPortEnable(void); + +/** + * @internal Calls on FreeRTOS vTaskDelay(...) + * + * @param[in] uiTicks Tick count to delay + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceKernelPortDelay(uint32_t uiTicks); + +/** + * @internal Query if FreeRTOS scheduler is suspended + * + * @retval 1 Scheduler suspended + * @retval 0 Scheduler not suspended + */ +unsigned char xTraceKernelPortIsSchedulerSuspended(void); + +/** + * @brief Kernel specific way to properly allocate critical sections + */ +#define TRC_KERNEL_PORT_ALLOC_CRITICAL_SECTION() + +/** + * @brief Kernel specific way to properly allocate critical sections + */ +#define TRC_KERNEL_PORT_ENTER_CRITICAL_SECTION() portENTER_CRITICAL() + +/** + * @brief Kernel specific way to properly allocate critical sections + */ +#define TRC_KERNEL_PORT_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL() + +/** +* @brief Kernel specific way to set interrupt mask +*/ +#define TRC_KERNEL_PORT_SET_INTERRUPT_MASK() ((TraceBaseType_t)portSET_INTERRUPT_MASK_FROM_ISR()) + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) + +/** + * @brief Kernel specific way to clear interrupt mask + */ +#define TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK(xMask) portCLEAR_INTERRUPT_MASK_FROM_ISR((UBaseType_t)(xMask)) + +#else + +/** + * @brief Kernel specific way to clear interrupt mask + */ +#define TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK(xMask) portCLEAR_INTERRUPT_MASK_FROM_ISR((unsigned portBASE_TYPE)xMask) +#endif + +#if (TRC_CFG_SCHEDULING_ONLY == 0) + +/** + * @brief Set the queue name + * + * @param[in] pvQueue Queue pointer + * @param[in] szName Queue name + */ +void vTraceSetQueueName(void* pvQueue, const char* szName); + +/** + * @brief Set the semaphore name + * + * @param[in] pvSemaphore Semaphore pointer + * @param[in] szName Semaphore name + */ +void vTraceSetSemaphoreName(void* pvSemaphore, const char* szName); + +/** + * @brief Set the mutex name + * + * @param[in] pvMutex Mutex pointer + * @param[in] szName Mutex name + */ +void vTraceSetMutexName(void* pvMutex, const char* szName); + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) + +/** + * @brief Set the event group name + * + * @param[in] pvEventGroup Event group pointer + * @param[in] szName Event group name + */ +void vTraceSetEventGroupName(void* pvEventGroup, const char* szName); + +#else + +/** + * @brief Disabled by TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS + */ +#define vTraceSetEventGroupName(__pvEventGroup, __szName) ((void)(__pvEventGroup), (void)(__szName)) + +#endif + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) + +/** + * @brief Set the stream buffer name + * + * @param[in] pvStreamBuffer Stream buffer pointer + * @param[in] szName Stream buffer name + */ +void vTraceSetStreamBufferName(void* pvStreamBuffer, const char* szName); + +/** + * @brief Set the message buffer name + * + * @param[in] pvMessageBuffer Message buffer pointer + * @param[in] szName Message buffer name + */ +void vTraceSetMessageBufferName(void* pvMessageBuffer, const char* szName); + +#else + +/** + * @brief Disabled by TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS + */ +#define vTraceSetStreamBufferName(__pvStreamBuffer, __szName) ((void)(__pvStreamBuffer), (void)(__szName)) + +/** + * @brief Disabled by TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS + */ +#define vTraceSetMessageBufferName(__pvMessageBuffer, __szName) ((void)(__pvMessageBuffer), (void)(__szName)) + +#endif + +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) + + /** + * @internal Retrieves the unused stack for a task + * + * @param[in] pvTask Task pointer + * @param[out] puxUnusedStack The unused stack + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceKernelPortGetUnusedStack(void* pvTask, TraceUnsignedBaseType_t *puxUnusedStack); + +#endif + +#else + +/** + * @brief Disabled by TRC_CFG_SCHEDULING_ONLY + */ +#define vTraceSetQueueName(__pvQueue, __szName) ((void)(__pvQueue), (void)(__szName)) + +/** + * @brief Disabled by TRC_CFG_SCHEDULING_ONLY + */ +#define vTraceSetSemaphoreName(__pvSemaphore, __szName) ((void)(__pvSemaphore), (void)(__szName)) + +/** + * @brief Disabled by TRC_CFG_SCHEDULING_ONLY + */ +#define vTraceSetMutexName(__pvMutex, __szName) ((void)(__pvMutex), (void)(__szName)) + +/** + * @brief Disabled by TRC_CFG_SCHEDULING_ONLY + */ +#define vTraceSetEventGroupName(__pvEventGroup, __szName) ((void)(__pvEventGroup), (void)(__szName)) + +/** + * @brief Disabled by TRC_CFG_SCHEDULING_ONLY + */ +#define vTraceSetStreamBufferName(__pvStreamBuffer, __szName) ((void)(__pvStreamBuffer), (void)(__szName)) + +/** + * @brief Disabled by TRC_CFG_SCHEDULING_ONLY + */ +#define vTraceSetMessageBufferName(__pvMessageBuffer, __szName) ((void)(__pvMessageBuffer), (void)(__szName)) + +/** + * @brief Disabled by TRC_CFG_SCHEDULING_ONLY + */ +#define xTraceKernelPortGetUnusedStack(pvTask, puxUnusedStack) ((void)(pvTask), (void)(puxUnusedStack)) + +#endif + +#if (((TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) && (TRC_CFG_INCLUDE_ISR_TRACING == 1)) || (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)) + +/* Required for ISR tracing and Streaming */ +#undef INCLUDE_xTaskGetSchedulerState +#define INCLUDE_xTaskGetSchedulerState 1 + +#endif + +/** + * @internal Legacy ID used by Tracealyzer to identify FreeRTOS traces + */ +#define TRACE_KERNEL_VERSION 0x1AA1 + +/** + * @internal Kernel specific tick rate frequency definition + */ +#define TRC_TICK_RATE_HZ configTICK_RATE_HZ /* Defined in "FreeRTOS.h" */ + +/** + * @internal Kernel specific CPU clock frequency definition + */ +#define TRACE_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOSConfig.h" */ + +/** + * @internal Kernel specific malloc definition + */ +#define TRACE_MALLOC(size) pvPortMalloc(size) + +#if (defined(configUSE_TIMERS) && (configUSE_TIMERS == 1)) + +#undef INCLUDE_xTimerGetTimerDaemonTaskHandle +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 + +#endif + +#if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XMOS_XCOREAI) + +#undef TRC_CFG_CORE_COUNT +#define TRC_CFG_CORE_COUNT configNUM_CORES + +#undef TRC_CFG_GET_CURRENT_CORE +#define TRC_CFG_GET_CURRENT_CORE() rtos_core_id_get() + +#endif + +#if (TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_9_0_1) + +/** + * @brief 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) + +/** + * @brief Is receive actually a peek + */ +#define isQueueReceiveHookActuallyPeek xJustPeeking + +#elif (TRC_CFG_FREERTOS_VERSION > TRC_FREERTOS_VERSION_9_0_1) + +/** + * @brief Is never a peek for this FreeRTOS version + */ +#define isQueueReceiveHookActuallyPeek (__LINE__ < 0) /* instead of pdFALSE to fix a warning of "constant condition" */ + +#endif + +/* Helpers needed to correctly expand names */ +#define TZ__CAT2(a,b) a ## b +#define TZ__CAT(a,b) TZ__CAT2(a, b) + +/* + * The following xQueueGiveFromISR macro hacks make 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) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + +/** + * @internal Kernel specific way to get current task handle + */ +#define TRACE_GET_CURRENT_TASK() prvTraceGetCurrentTaskHandle() + +extern uint16_t CurrentFilterMask; +extern uint16_t CurrentFilterGroup; + +/** + * @internal Get specific queue type + * + * @param[in] pvQueue Queue handle + * + * @returns uint8_t Queue type + */ +uint8_t prvTraceGetQueueType(void* pvQueue); + +/** + * @internal Retrieve lower 16-bit of task number + * + * @param[in] pvTask Task handle + * + * @returns uint16_t Lower 16-bit of task number + */ +uint16_t prvTraceGetTaskNumberLow16(void* pvTask); + +/** + * @internal Retrieve upper 16-bit of task number + * + * @param[in] pvTask Task handle + * + * @returns uint16_t Upper 16-bit of task number + */ +uint16_t prvTraceGetTaskNumberHigh16(void* pvTask); + +/** + * @internal Set lower 16-bit of task number + * + * @param[in] pvTask Task handle + * @param[in] uiValue Value + */ +void prvTraceSetTaskNumberLow16(void* pvTask, uint16_t uiValue); + +/** + * @internal Set upper 16-bit of task number + * + * @param[in] pvTask Task handle + * @param[in] uiValue Value + */ +void prvTraceSetTaskNumberHigh16(void* pvTask, uint16_t uiValue); + +/** + * @internal Retrieve lower 16-bit of queue number + * + * @param[in] pvQueue Queue handle + * + * @returns uint16_t Lower 16-bit of queue number + */ +uint16_t prvTraceGetQueueNumberLow16(void* pvQueue); + +/** + * @internal Retrieve upper 16-bit of queue number + * + * @param[in] pvQueuevQueue handle + * + * @returns uint16_t Upper 16-bit of queue number + */ +uint16_t prvTraceGetQueueNumberHigh16(void* pvQueue); + + +/** + * @internal Set lower 16-bit of queue number + * + * @param[in] pvQueue Queue handle + * @param[in] uiValue Value + */ +void prvTraceSetQueueNumberLow16(void* pvQueue, uint16_t uiValue); + + +/** + * @internal Set upper 16-bit of queue number + * + * @param[in] pvQueue Queue handle + * @param[in] uiValue Value + */ +void prvTraceSetQueueNumberHigh16(void* pvQueue, uint16_t uiValue); + +#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +/** + * @internal Retrieve lower 16-bit of timer number + * + * @param[in] pvTimer Timer handle + * + * @returns uint16_t Lower 16-bit of timer number + */ +uint16_t prvTraceGetTimerNumberLow16(void* pvTimer); + +/** + * @internal Retrieve upper 16-bit of timer number + * + * @param[in] pvTimer Timer handle + * + * @returns uint16_t Upper 16-bit of timer number + */ +uint16_t prvTraceGetTimerNumberHigh16(void* pvTimer); + +/** + * @internal Set lower 16-bit of timer number + * + * @param[in] pvTimer Timer handle + * @param[in] uiValue Value + */ +void prvTraceSetTimerNumberLow16(void* pvTimer, uint16_t uiValue); + +/** + * @internal Set upper 16-bit of timer number + * + * @param[in] pvTimer Timer handle + * @param[in] uiValue Value + */ +void prvTraceSetTimerNumberHigh16(void* pvTimer, uint16_t uiValue); + +#endif + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +/** + * @internal Retrieve lower 16-bit of event group number + * + * @param[in] pvEventGroup Event group handle + * + * @returns uint16_t Lower 16-bit of event group number + */ +uint16_t prvTraceGetEventGroupNumberLow16(void* pvEventGroup); + +/** + * @internal Retrieve upper 16-bit of event group number + * + * @param[in] pvEventGroup Event group handle + * + * @returns uint16_t Upper 16-bit of event group number + */ +uint16_t prvTraceGetEventGroupNumberHigh16(void* pvEventGroup); + +/** + * @internal Set lower 16-bit of event group number + * + * @param[in] pvEventGroup Event group handle + * @param[in] uiValue Value + */ +void prvTraceSetEventGroupNumberLow16(void* pvEventGroup, uint16_t uiValue); + +/** + * @internal Set upper 16-bit of event group number + * + * @param[in] pvEventGroup Event group handle + * @param[in] uiValue Value + */ +void prvTraceSetEventGroupNumberHigh16(void* handle, uint16_t value); + +#endif + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +/** + * @internal Retrieve lower 16-bit of stream buffer number + * + * @param[in] pvStreamBuffer Stream buffer handle + * + * @returns uint16_t Lower 16-bit of stream buffer number + */ +uint16_t prvTraceGetStreamBufferNumberLow16(void* pvStreamBuffer); + +/** + * @internal Retrieve upper 16-bit of stream buffer number + * + * @param[in] pvStreamBuffer Stream buffer handle + * + * @returns uint16_t Upper 16-bit of stream buffer number + */ +uint16_t prvTraceGetStreamBufferNumberHigh16(void* pvStreamBuffer); + +/** + * @internal Set lower 16-bit of stream buffer number + * + * @param[in] pvStreamBuffer Stream buffer handle + * @param[in] uiValue Value + */ +void prvTraceSetStreamBufferNumberLow16(void* pvStreamBuffer, uint16_t uiValue); + +/** + * @internal Set upper 16-bit of stream buffer number + * + * @param[in] pvStreamBuffer Stream buffer handle + * @param[in] uiValue Value + */ +void prvTraceSetStreamBufferNumberHigh16(void* pvStreamBuffer, uint16_t uiValue); + +#endif + +/** + * @brief Retrieve filter of task + * + * @param[in] pxTask Task handle + * + * @returns uint16_t Task filter + */ +#define TRACE_GET_TASK_FILTER(pxTask) prvTraceGetTaskNumberHigh16((void*)pxTask) + +/** + * @brief Set filter of task + * + * @param[in] pxTask Task handle + * @param[in] group Group + */ +#define TRACE_SET_TASK_FILTER(pxTask, group) prvTraceSetTaskNumberHigh16((void*)pxTask, group) + +/** + * @brief Retrieve filter of queue + * + * @param[in] pxQueue Queue handle + * + * @returns uint16_t Queue filter + */ +#define TRACE_GET_QUEUE_FILTER(pxQueue) prvTraceGetQueueNumberHigh16((void*)pxQueue) + +/** + * @brief Set filter of queue + * + * @param[in] pxQueue Queue handle + * @param[in] group Group + */ +#define TRACE_SET_QUEUE_FILTER(pxQueue, group) prvTraceSetQueueNumberHigh16((void*)pxQueue, group) + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +/** + * @brief Retrieve filter of event group + * + * @param[in] pxEventGroup Queue handle + * + * @returns uint16_t Queue filter + */ +#define TRACE_GET_EVENTGROUP_FILTER(pxEventGroup) prvTraceGetEventGroupNumberHigh16((void*)pxEventGroup) + +/** + * @brief Set filter of event group + * + * @param[in] pxEventGroup Queue handle + * @param[in] group Group + */ +#define TRACE_SET_EVENTGROUP_FILTER(pxEventGroup, group) prvTraceSetEventGroupNumberHigh16((void*)pxEventGroup, group) + +#else + +/** + * @brief Disabled by TRC_CFG_FREERTOS_VERSION + */ +#define TRACE_GET_EVENTGROUP_FILTER(pxEventGroup) ((void)(pxEventGroup), 1) + +/** + * @brief Disabled by TRC_CFG_FREERTOS_VERSION + */ +#define TRACE_SET_EVENTGROUP_FILTER(pxEventGroup, group) ((void)(pxEventGroup), (void)(group)) + +#endif + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +/** + * @brief Retrieve filter of timer + * + * @param[in] pxEventGroup Timer handle + * + * @returns uint16_t Timer filter + */ +#define TRACE_GET_TIMER_FILTER(pxTimer) prvTraceGetTimerNumberHigh16((void*)pxTimer) + +/** + * @brief Set filter of timer + * + * @param[in] pxTimer Timer handle + * @param[in] group Group + */ +#define TRACE_SET_TIMER_FILTER(pxTimer, group) prvTraceSetTimerNumberHigh16((void*)pxTimer, group) + +#else + +/** + * @brief Disabled by TRC_CFG_FREERTOS_VERSION + */ +#define TRACE_GET_TIMER_FILTER(pxTimer) ((void)(pxTimer), 1) + +/** + * @brief Disabled by TRC_CFG_FREERTOS_VERSION + */ +#define TRACE_SET_TIMER_FILTER(pxTimer, group) ((void)(pxTimer), (void)(group)) + +#endif + +/** + * @brief Retrieve filter of stream buffer + * + * @param[in] pxStreamBuffer Stream buffer handle + * + * @returns uint16_t Timer filter + */ +#define TRACE_GET_STREAMBUFFER_FILTER(pxStreamBuffer) prvTraceGetStreamBufferNumberHigh16((void*)pxStreamBuffer) + +/** + * @brief Set filter of stream buffer + * + * @param[in] pxStreamBuffer Stream buffer handle + * @param[in] group Group + */ +#define TRACE_SET_STREAMBUFFER_FILTER(pxStreamBuffer, group) prvTraceSetStreamBufferNumberHigh16((void*)pxStreamBuffer, group) + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) + +/** + * @internal Get object filter + */ +#define TRACE_GET_OBJECT_FILTER(CLASS, pxObject) TRACE_GET_##CLASS##_FILTER(pxObject) + +/** + * @internal Set object filter + */ +#define TRACE_SET_OBJECT_FILTER(CLASS, pxObject, group) TRACE_SET_##CLASS##_FILTER(pxObject, group) + +#else + +/** + * @internal Disabled by TRC_CFG_FREERTOS_VERSION + */ +#define TRACE_GET_OBJECT_FILTER(CLASS, pxObject) 0xFFFF + +/** + * @internal Disabled by TRC_CFG_FREERTOS_VERSION + */ +#define TRACE_SET_OBJECT_FILTER(CLASS, pxObject, group) + +#endif + +/* 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; + +/** + * @internal Initialized the object property table + */ +traceResult xTraceKernelPortInitObjectPropertyTable(void); + +/** + * @internal Initialized the object handle stack + */ +traceResult xTraceKernelPortInitObjectHandleStack(void); + +/** + * @internal Retrieve error string + */ +const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass); + +/** + * @internal Retrieve current task handle + */ +void* prvTraceGetCurrentTaskHandle(void); + +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 != 0) \ + { \ + 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_OBJECT_CREATE_FAILED(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, TASK, NOT_USED), TRACE_GET_CLASS_TRACE_CLASS(TASK, NOT_USED)) + +/* 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) && (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 + +/* 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 + +#define traceTASK_DELAY_UNTIL() \ + trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \ + trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); + +#endif + +/* 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_OBJECT_CREATE_FAILED(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, QUEUE, queueType), TRACE_GET_CLASS_TRACE_CLASS(QUEUE, queueType)) + +/* 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 + +/* 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 + +#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_OBJECT_CREATE_FAILED(TIMER_CREATE_TRCFAILED, TRACE_GET_CLASS_TRACE_CLASS(TIMER, NOT_USED)) + +/* 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 + +#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 + +#endif + +#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_OBJECT_CREATE_FAILED(EVENT_GROUP_CREATE_TRCFAILED, TRACE_GET_CLASS_TRACE_CLASS(EVENTGROUP, NOT_USED)) + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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_OBJECT_CREATE_FAILED(TRACE_GET_CLASS_EVENT_CODE(CREATE_OBJ, TRCFAILED, STREAMBUFFER, xIsMessageBuffer), TRACE_GET_CLASS_TRACE_CLASS(STREAMBUFFER, xIsMessageBuffer)) + +#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 + +#endif + +#endif + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +TraceHeapHandle_t xTraceKernelPortGetSystemHeapHandle(void); + +/*************************************************************************/ +/* 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_WAIT 0xCA +#define PSF_EVENT_TASK_NOTIFY_WAIT_BLOCK 0xCB +#define PSF_EVENT_TASK_NOTIFY_WAIT_FAILED 0xCC +#define PSF_EVENT_TASK_NOTIFY_FROM_ISR 0xCD + +#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_FREE_FAILED 0xEA + +#define PSF_EVENT_UNUSED_STACK 0xEB + +#define PSF_EVENT_STATEMACHINE_STATE_CREATE 0xEC +#define PSF_EVENT_STATEMACHINE_CREATE 0xED +#define PSF_EVENT_STATEMACHINE_STATECHANGE 0xEE + +#define PSF_EVENT_INTERVAL_CREATE 0xEF +#define PSF_EVENT_INTERVAL_STATECHANGE 0xF0 + +#define PSF_EVENT_EXTENSION_CREATE 0xF1 + +#define PSF_EVENT_HEAP_CREATE 0xF2 + +#define PSF_EVENT_COUNTER_CREATE 0xF3 +#define PSF_EVENT_COUNTER_CHANGE 0xF4 +#define PSF_EVENT_COUNTER_LIMIT_EXCEEDED 0xF5 + +#define PSF_EVENT_MUTEX_TAKE_RECURSIVE_BLOCK 0xF6 + +#define TRC_EVENT_LAST_ID PSF_EVENT_COUNTER_LIMIT_EXCEEDED + +/*** 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 ) { uint32_t uiTraceTickCount; xTraceTimestampGetOsTickCount(&uiTraceTickCount); xTraceTimestampSetOsTickCount(uiTraceTickCount + (xCount)); } + +#if (TRC_CFG_INCLUDE_OSTICK_EVENTS == 1) + +#define OS_TICK_EVENT(uxSchedulerSuspended, xTickCount) if ((uxSchedulerSuspended) == (unsigned portBASE_TYPE) pdFALSE) { prvTraceStoreEvent_Param(PSF_EVENT_NEW_TIME, (uint32_t)(xTickCount)); } + +#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) { xTraceTimestampSetOsTickCount((xTickCount) + 1); } \ + OS_TICK_EVENT(uxSchedulerSuspended, (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) { xTraceTimestampSetOsTickCount(xTickCount + 1); } \ + OS_TICK_EVENT(uxSchedulerSuspended, xTickCount + 1) + +#else + +#define traceTASK_INCREMENT_TICK( xTickCount ) \ + if (uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdTRUE || uxMissedTicks == 0) { xTraceTimestampSetOsTickCount(xTickCount + 1); } \ + OS_TICK_EVENT(uxSchedulerSuspended, xTickCount + 1) + +#endif + +/* Called on each task-switch */ +#undef traceTASK_SWITCHED_IN +#define traceTASK_SWITCHED_IN() \ + xTraceTaskSwitch(pxCurrentTCB, pxCurrentTCB->uxPriority) + +/* Called for each task that becomes ready */ +#undef traceMOVED_TASK_TO_READY_STATE +#define traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ + xTraceTaskReady(pxTCB) + +#undef traceTASK_CREATE +#if TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0 + +#define traceTASK_CREATE(pxNewTCB) \ + if ((pxNewTCB) != 0) \ + { \ + xTraceTaskRegisterWithoutHandle((void*)(pxNewTCB), (pxNewTCB)->pcTaskName, (pxNewTCB)->uxPriority); \ + } + +#else + +#define traceTASK_CREATE(pxNewTCB) \ + if (pxNewTCB != 0) \ + { \ + xTraceTaskRegisterWithoutHandle((void*)pxNewTCB, (const char*)pcName, (uint32_t)uxPriority); \ + } + +#endif + +/* Called in vTaskCreate, if it fails (typically if the stack can not be allocated) */ +#undef traceTASK_CREATE_FAILED +#define traceTASK_CREATE_FAILED() \ + prvTraceStoreEvent_None(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 ) \ + xTraceTaskUnregisterWithoutHandle(pxTaskToDelete, (pxTaskToDelete)->uxPriority) + +#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() \ + prvTraceStoreEvent_Param(PSF_EVENT_LOWPOWER_BEGIN, xExpectedIdleTime) + +#undef traceLOW_POWER_IDLE_END +#define traceLOW_POWER_IDLE_END() \ + prvTraceStoreEvent_None(PSF_EVENT_LOWPOWER_END) + +#endif + +/* Called on vTaskSuspend */ +#undef traceTASK_SUSPEND +#define traceTASK_SUSPEND( pxTaskToSuspend ) \ + prvTraceStoreEvent_Handle(PSF_EVENT_TASK_SUSPEND, pxTaskToSuspend) + +/* Called on vTaskDelay - note the use of FreeRTOS variable xTicksToDelay */ +#undef traceTASK_DELAY +#define traceTASK_DELAY() \ + prvTraceStoreEvent_Param(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) \ + prvTraceStoreEvent_Param(PSF_EVENT_TASK_DELAY_UNTIL, (xTimeToWake)) + +#else + +#define traceTASK_DELAY_UNTIL() \ + prvTraceStoreEvent_Param(PSF_EVENT_TASK_DELAY_UNTIL, xTimeToWake) + +#endif + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) + +#define traceQUEUE_CREATE_HELPER() \ + case queueQUEUE_TYPE_MUTEX: \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_MUTEX_CREATE, (void*)pxNewQueue, "", 0); \ + break; \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_MUTEX_RECURSIVE_CREATE, (void*)pxNewQueue, "", 0); \ + break; + +#else + +#define traceQUEUE_CREATE_HELPER() + +#endif + +/* Called in xQueueCreate, and thereby for all other object based on queues, such as semaphores. */ +#undef traceQUEUE_CREATE +#define traceQUEUE_CREATE( pxNewQueue )\ + switch ((pxNewQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_QUEUE_CREATE, (void*)(pxNewQueue), "", (uint32_t)uxQueueLength); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_SEMAPHORE_BINARY_CREATE, (void*)(pxNewQueue), "", 0); \ + break; \ + traceQUEUE_CREATE_HELPER() \ + } + +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) + +#define traceQUEUE_CREATE_FAILED_HELPER() \ + case queueQUEUE_TYPE_MUTEX: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_MUTEX_CREATE_FAILED, 0, 0); \ + break; \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_MUTEX_RECURSIVE_CREATE_FAILED, 0, 0); \ + break; + +#else + +#define traceQUEUE_CREATE_FAILED_HELPER() + +#endif + +/* Called in xQueueCreate, if the queue creation fails */ +#undef traceQUEUE_CREATE_FAILED +#define traceQUEUE_CREATE_FAILED( queueType ) \ + switch (queueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_QUEUE_CREATE_FAILED, 0, uxQueueLength); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_BINARY_CREATE_FAILED, 0, 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 ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + xTraceObjectUnregisterWithoutHandle(PSF_EVENT_QUEUE_DELETE, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + xTraceObjectUnregisterWithoutHandle(PSF_EVENT_MUTEX_DELETE, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + xTraceObjectUnregisterWithoutHandle(PSF_EVENT_SEMAPHORE_DELETE, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + } + +/* 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() \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (void*)xHandle, "", (uint32_t)uxMaxCount) + +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_5_X) + +#define traceCREATE_COUNTING_SEMAPHORE() \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (void*)xHandle, "", uxInitialCount) + +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4_X) + +#define traceCREATE_COUNTING_SEMAPHORE() \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (void*)xHandle, "", uxCountValue) + +#else + +#define traceCREATE_COUNTING_SEMAPHORE() \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_SEMAPHORE_COUNTING_CREATE, (void*)pxHandle, "", uxCountValue) + +#endif + +#undef traceCREATE_COUNTING_SEMAPHORE_FAILED +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) + +#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxMaxCount) + +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_5_X) + +#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxInitialCount) + +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_7_4_X) + +#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxCountValue) + +#else + +#define traceCREATE_COUNTING_SEMAPHORE_FAILED() \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_COUNTING_CREATE_FAILED, 0, uxCountValue) + +#endif + + +/* 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 ) \ + switch (pxNewQueue->ucQueueType) \ + { \ + case queueQUEUE_TYPE_MUTEX: \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_MUTEX_CREATE, (void*)(pxNewQueue), "", 0); \ + break; \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_MUTEX_RECURSIVE_CREATE, (void*)(pxNewQueue), "", 0); \ + break; \ + } + +/* Called in xQueueCreateMutex when the operation fails (when memory allocation fails) */ +#undef traceCREATE_MUTEX_FAILED +#define traceCREATE_MUTEX_FAILED() \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_MUTEX_CREATE_FAILED, 0, 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 ) \ + prvTraceStoreEvent_Handle(PSF_EVENT_MUTEX_GIVE_RECURSIVE_FAILED, (void*)(pxMutex)) + +/* Called when a message is sent to a queue */ /* CS IS NEW ! */ +#undef traceQUEUE_SEND +#define traceQUEUE_SEND( pxQueue ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParam(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND : PSF_EVENT_QUEUE_SEND_FRONT, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting + 1); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_GIVE, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting + 1); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + prvTraceStoreEvent_Handle(PSF_EVENT_MUTEX_GIVE, (void*)(pxQueue)); \ + break; \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent_Handle(PSF_EVENT_MUTEX_GIVE_RECURSIVE, (void*)(pxQueue)); \ + break; \ + } + +#undef traceQUEUE_SET_SEND +#define traceQUEUE_SET_SEND( pxQueue ) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_QUEUE_SEND, (void*)(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 ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParam(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FAILED : PSF_EVENT_QUEUE_SEND_FRONT_FAILED, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_GIVE_FAILED, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent_Handle(PSF_EVENT_MUTEX_GIVE_FAILED, (void*)(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 ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParam(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_BLOCK : PSF_EVENT_QUEUE_SEND_FRONT_BLOCK, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_GIVE_BLOCK, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent_Handle(PSF_EVENT_MUTEX_GIVE_BLOCK, (void*)(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 ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParam(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FROMISR : PSF_EVENT_QUEUE_SEND_FRONT_FROMISR, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting + 1); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_GIVE_FROMISR, (void*)(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 ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParam(xCopyPosition == queueSEND_TO_BACK ? PSF_EVENT_QUEUE_SEND_FROMISR_FAILED : PSF_EVENT_QUEUE_SEND_FRONT_FROMISR_FAILED, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_GIVE_FROMISR_FAILED, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + } + +/* Called when a message is received from a queue */ +#undef traceQUEUE_RECEIVE +#define traceQUEUE_RECEIVE( pxQueue ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + if (isQueueReceiveHookActuallyPeek) \ + { \ + prvTraceStoreEvent_HandleParamParam(PSF_EVENT_QUEUE_PEEK, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting - 1); \ + } \ + else\ + { \ + prvTraceStoreEvent_HandleParamParam(PSF_EVENT_QUEUE_RECEIVE, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting - 1); \ + } \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + if (isQueueReceiveHookActuallyPeek) \ + { \ + prvTraceStoreEvent_HandleParamParam(PSF_EVENT_SEMAPHORE_PEEK, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting - 1); \ + } \ + else \ + { \ + prvTraceStoreEvent_HandleParamParam(PSF_EVENT_SEMAPHORE_TAKE, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting - 1); \ + } \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + prvTraceStoreEvent_HandleParam(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK : PSF_EVENT_MUTEX_TAKE, (void*)(pxQueue), xTicksToWait); \ + break; \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent_HandleParam(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK : PSF_EVENT_MUTEX_TAKE_RECURSIVE, (void*)(pxQueue), xTicksToWait); \ + break; \ + } + +/* Called when a receive operation on a queue fails (timeout) */ +#undef traceQUEUE_RECEIVE_FAILED +#define traceQUEUE_RECEIVE_FAILED( pxQueue ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParamParam(isQueueReceiveHookActuallyPeek ? PSF_EVENT_QUEUE_PEEK_FAILED : PSF_EVENT_QUEUE_RECEIVE_FAILED, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParamParam(isQueueReceiveHookActuallyPeek ? PSF_EVENT_SEMAPHORE_PEEK_FAILED : PSF_EVENT_SEMAPHORE_TAKE_FAILED, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + prvTraceStoreEvent_HandleParam(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK_FAILED : PSF_EVENT_MUTEX_TAKE_FAILED, (void*)(pxQueue), xTicksToWait); \ + break; \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent_HandleParam(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK_FAILED : PSF_EVENT_MUTEX_TAKE_RECURSIVE_FAILED, (void*)(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 ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParamParam(isQueueReceiveHookActuallyPeek ? PSF_EVENT_QUEUE_PEEK_BLOCK : PSF_EVENT_QUEUE_RECEIVE_BLOCK, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParamParam(isQueueReceiveHookActuallyPeek ? PSF_EVENT_SEMAPHORE_PEEK_BLOCK : PSF_EVENT_SEMAPHORE_TAKE_BLOCK, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + prvTraceStoreEvent_HandleParam(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK_BLOCK : PSF_EVENT_MUTEX_TAKE_BLOCK, (void*)(pxQueue), xTicksToWait); \ + break; \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent_HandleParam(isQueueReceiveHookActuallyPeek ? PSF_EVENT_MUTEX_PEEK_BLOCK : PSF_EVENT_MUTEX_TAKE_RECURSIVE_BLOCK, (void*)(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 ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParamParam(PSF_EVENT_QUEUE_PEEK_FAILED, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParamParam(PSF_EVENT_SEMAPHORE_PEEK_FAILED, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_MUTEX_PEEK_FAILED, (void*)(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 ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParamParam(PSF_EVENT_QUEUE_PEEK_BLOCK, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParamParam(PSF_EVENT_SEMAPHORE_PEEK_BLOCK, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_MUTEX_PEEK_BLOCK, (void*)(pxQueue), xTicksToWait); \ + break; \ + } + +#endif + +/* Called when a message is received in interrupt context, e.g., using xQueueReceiveFromISR */ +#undef traceQUEUE_RECEIVE_FROM_ISR +#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_QUEUE_RECEIVE_FROMISR, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting - 1); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_TAKE_FROMISR, (void*)(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 ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_QUEUE_RECEIVE_FROMISR_FAILED, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_SEMAPHORE_TAKE_FROMISR_FAILED, (void*)(pxQueue), (pxQueue)->uxMessagesWaiting); \ + break; \ + } + +/* Called on xQueuePeek */ +#undef traceQUEUE_PEEK +#define traceQUEUE_PEEK( pxQueue ) \ + switch ((pxQueue)->ucQueueType) \ + { \ + case queueQUEUE_TYPE_BASE: \ + prvTraceStoreEvent_HandleParamParam(PSF_EVENT_QUEUE_PEEK, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_BINARY_SEMAPHORE: \ + case queueQUEUE_TYPE_COUNTING_SEMAPHORE: \ + prvTraceStoreEvent_HandleParamParam(PSF_EVENT_SEMAPHORE_PEEK, (void*)(pxQueue), xTicksToWait, (pxQueue)->uxMessagesWaiting); \ + break; \ + case queueQUEUE_TYPE_MUTEX: \ + case queueQUEUE_TYPE_RECURSIVE_MUTEX: \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_MUTEX_PEEK, (void*)(pxQueue), xTicksToWait); \ + break; \ + } + +/* Called in vTaskPrioritySet */ +#undef traceTASK_PRIORITY_SET +#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) \ + xTraceTaskSetPriorityWithoutHandle(pxTask, uxNewPriority) + +/* Called in vTaskPriorityInherit, which is called by Mutex operations */ +#undef traceTASK_PRIORITY_INHERIT +#define traceTASK_PRIORITY_INHERIT( pxTask, uxNewPriority ) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_TASK_PRIO_INHERIT, (void*)(pxTask), uxNewPriority) + +/* Called in vTaskPriorityDisinherit, which is called by Mutex operations */ +#undef traceTASK_PRIORITY_DISINHERIT +#define traceTASK_PRIORITY_DISINHERIT( pxTask, uxNewPriority ) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_TASK_PRIO_DISINHERIT, (void*)(pxTask), uxNewPriority) + +/* Called in vTaskResume */ +#undef traceTASK_RESUME +#define traceTASK_RESUME( pxTaskToResume ) \ + prvTraceStoreEvent_Handle(PSF_EVENT_TASK_RESUME, (void*)(pxTaskToResume)) + +/* Called in vTaskResumeFromISR */ +#undef traceTASK_RESUME_FROM_ISR +#define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) \ + prvTraceStoreEvent_Handle(PSF_EVENT_TASK_RESUME_FROMISR, (void*)(pxTaskToResume)) + +#if (TRC_CFG_INCLUDE_MEMMANG_EVENTS == 1) + +#undef traceMALLOC +#define traceMALLOC( pvAddress, uiSize ) \ + if (xTraceIsRecorderEnabled()) \ + { \ + xTraceHeapAlloc(xTraceKernelPortGetSystemHeapHandle(), pvAddress, uiSize); \ + } + +#undef traceFREE +#define traceFREE( pvAddress, uiSize ) \ + if (xTraceIsRecorderEnabled()) \ + { \ + xTraceHeapFree(xTraceKernelPortGetSystemHeapHandle(), pvAddress, uiSize); \ + } + +#endif + +#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1) + +/* Called in timer.c - xTimerCreate */ +#undef traceTIMER_CREATE +#define traceTIMER_CREATE(tmr) \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_TIMER_CREATE, (void*)(tmr), (const char*)(tmr)->pcTimerName, (uint32_t)(tmr)->xTimerPeriodInTicks) + +#undef traceTIMER_CREATE_FAILED +#define traceTIMER_CREATE_FAILED() \ + prvTraceStoreEvent_None(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: \ + prvTraceStoreEvent_HandleParam((xReturn == pdPASS) ? PSF_EVENT_TIMER_RESET : PSF_EVENT_TIMER_RESET_FAILED, (void*)(tmr), xOptionalValue); \ + break; \ + case tmrCOMMAND_START_FROM_ISR: \ + prvTraceStoreEvent_HandleParam((xReturn == pdPASS) ? PSF_EVENT_TIMER_START_FROMISR : PSF_EVENT_TIMER_START_FROMISR_FAILED, (void*)(tmr), xOptionalValue); \ + break; \ + case tmrCOMMAND_RESET_FROM_ISR: \ + prvTraceStoreEvent_HandleParam((xReturn == pdPASS) ? PSF_EVENT_TIMER_RESET_FROMISR : PSF_EVENT_TIMER_RESET_FROMISR_FAILED, (void*)(tmr), xOptionalValue); \ + break; \ + case tmrCOMMAND_STOP_FROM_ISR: \ + prvTraceStoreEvent_HandleParam((xReturn == pdPASS) ? PSF_EVENT_TIMER_STOP_FROMISR : PSF_EVENT_TIMER_STOP_FROMISR_FAILED, (void*)(tmr), xOptionalValue); \ + break; \ + case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR: \ + prvTraceStoreEvent_HandleParam((xReturn == pdPASS) ? PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR : PSF_EVENT_TIMER_CHANGEPERIOD_FROMISR_FAILED, (void*)(tmr), xOptionalValue); \ + break; +#else + +#define traceTIMER_COMMAND_SEND_8_0_CASES(tmr) + +#endif + +/* 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) \ + switch(xCommandID) \ + { \ + case tmrCOMMAND_START: \ + prvTraceStoreEvent_Handle(((xReturn) == pdPASS) ? PSF_EVENT_TIMER_START : PSF_EVENT_TIMER_START_FAILED, (void*)(tmr)); \ + break; \ + case tmrCOMMAND_STOP: \ + prvTraceStoreEvent_Handle(((xReturn) == pdPASS) ? PSF_EVENT_TIMER_STOP : PSF_EVENT_TIMER_STOP_FAILED, (void*)(tmr)); \ + break; \ + case tmrCOMMAND_CHANGE_PERIOD: \ + prvTraceStoreEvent_HandleParam(((xReturn) == pdPASS) ? PSF_EVENT_TIMER_CHANGEPERIOD : PSF_EVENT_TIMER_CHANGEPERIOD_FAILED, (void*)(tmr), xOptionalValue); \ + break; \ + case tmrCOMMAND_DELETE: \ + xTraceObjectUnregisterWithoutHandle(((xReturn) == pdPASS) ? PSF_EVENT_TIMER_DELETE : PSF_EVENT_TIMER_DELETE_FAILED, (void*)(tmr), 0); \ + break; \ + traceTIMER_COMMAND_SEND_8_0_CASES(tmr) \ + } + +#undef traceTIMER_EXPIRED +#define traceTIMER_EXPIRED(tmr) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_TIMER_EXPIRED, (void*)(tmr), (uint32_t)((tmr)->pxCallbackFunction)) + +#endif + + +#if (TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS == 1) + +#undef tracePEND_FUNC_CALL +#define tracePEND_FUNC_CALL(func, arg1, arg2, ret) \ + prvTraceStoreEvent_Param(((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) \ + prvTraceStoreEvent_Param(((ret) == pdPASS) ? PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR : PSF_EVENT_TIMER_PENDFUNCCALL_FROMISR_FAILED, (uint32_t)(func)) + +#endif + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1) + +#undef traceEVENT_GROUP_CREATE +#define traceEVENT_GROUP_CREATE(eg) \ + xTraceObjectRegisterWithoutHandle(PSF_EVENT_EVENTGROUP_CREATE, (void*)(eg), 0, (uint32_t)(eg)->uxEventBits) + +#undef traceEVENT_GROUP_DELETE +#define traceEVENT_GROUP_DELETE(eg) \ + xTraceObjectUnregisterWithoutHandle(PSF_EVENT_EVENTGROUP_DELETE, (void*)(eg), (uint32_t)(eg)->uxEventBits) + +#undef traceEVENT_GROUP_CREATE_FAILED +#define traceEVENT_GROUP_CREATE_FAILED() \ + prvTraceStoreEvent_None(PSF_EVENT_EVENTGROUP_CREATE_FAILED) + +#undef traceEVENT_GROUP_SYNC_BLOCK +#define traceEVENT_GROUP_SYNC_BLOCK(eg, bitsToSet, bitsToWaitFor) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_EVENTGROUP_SYNC_BLOCK, (void*)(eg), bitsToWaitFor) + +#undef traceEVENT_GROUP_SYNC_END +#define traceEVENT_GROUP_SYNC_END(eg, bitsToSet, bitsToWaitFor, wasTimeout) \ + prvTraceStoreEvent_HandleParam(((wasTimeout) != pdTRUE) ? PSF_EVENT_EVENTGROUP_SYNC : PSF_EVENT_EVENTGROUP_SYNC_FAILED, (void*)(eg), bitsToWaitFor) + +#undef traceEVENT_GROUP_WAIT_BITS_BLOCK +#define traceEVENT_GROUP_WAIT_BITS_BLOCK(eg, bitsToWaitFor) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_EVENTGROUP_WAITBITS_BLOCK, (void*)(eg), bitsToWaitFor) + +#undef traceEVENT_GROUP_WAIT_BITS_END +#define traceEVENT_GROUP_WAIT_BITS_END(eg, bitsToWaitFor, wasTimeout) \ + prvTraceStoreEvent_HandleParam(((wasTimeout) != pdTRUE) ? PSF_EVENT_EVENTGROUP_WAITBITS : PSF_EVENT_EVENTGROUP_WAITBITS_FAILED, (void*)(eg), bitsToWaitFor) + +#undef traceEVENT_GROUP_CLEAR_BITS +#define traceEVENT_GROUP_CLEAR_BITS(eg, bitsToClear) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_EVENTGROUP_CLEARBITS, (void*)(eg), bitsToClear) + +#undef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR +#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR(eg, bitsToClear) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_EVENTGROUP_CLEARBITS_FROMISR, (void*)(eg), bitsToClear) + +#undef traceEVENT_GROUP_SET_BITS +#define traceEVENT_GROUP_SET_BITS(eg, bitsToSet) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_EVENTGROUP_SETBITS, (void*)(eg), bitsToSet) + +#undef traceEVENT_GROUP_SET_BITS_FROM_ISR +#define traceEVENT_GROUP_SET_BITS_FROM_ISR(eg, bitsToSet) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_EVENTGROUP_SETBITS_FROMISR, (void*)(eg), bitsToSet) + +#endif + +#undef traceTASK_NOTIFY +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) + +#define traceTASK_NOTIFY(index) \ + prvTraceStoreEvent_Handle(PSF_EVENT_TASK_NOTIFY, (void*)xTaskToNotify) + +#else + +#define traceTASK_NOTIFY() \ + prvTraceStoreEvent_Handle(PSF_EVENT_TASK_NOTIFY, (void*)xTaskToNotify) + +#endif + +#undef traceTASK_NOTIFY_FROM_ISR +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) + +#define traceTASK_NOTIFY_FROM_ISR(index) \ + prvTraceStoreEvent_Handle(PSF_EVENT_TASK_NOTIFY_FROM_ISR, (void*)xTaskToNotify) + +#else + +#define traceTASK_NOTIFY_FROM_ISR() \ + prvTraceStoreEvent_Handle(PSF_EVENT_TASK_NOTIFY_FROM_ISR, (void*)xTaskToNotify) + +#endif + +/* NOTIFY and NOTIFY_GIVE will be handled identically */ +#undef traceTASK_NOTIFY_GIVE_FROM_ISR +#define traceTASK_NOTIFY_GIVE_FROM_ISR traceTASK_NOTIFY_FROM_ISR + +#undef traceTASK_NOTIFY_WAIT +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) + +#define traceTASK_NOTIFY_WAIT(index) \ + prvTraceStoreEvent_HandleParam(pxCurrentTCB->ucNotifyState[index] == taskNOTIFICATION_RECEIVED ? PSF_EVENT_TASK_NOTIFY_WAIT : PSF_EVENT_TASK_NOTIFY_WAIT_FAILED, (void*)pxCurrentTCB, xTicksToWait) + +#elif (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0) + +#define traceTASK_NOTIFY_WAIT() \ + prvTraceStoreEvent_HandleParam(pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED ? PSF_EVENT_TASK_NOTIFY_WAIT : PSF_EVENT_TASK_NOTIFY_WAIT_FAILED, (void*)pxCurrentTCB, xTicksToWait) + +#else + +#define traceTASK_NOTIFY_WAIT() \ + prvTraceStoreEvent_HandleParam(pxCurrentTCB->eNotifyState == eNotified ? PSF_EVENT_TASK_NOTIFY_WAIT : PSF_EVENT_TASK_NOTIFY_WAIT_FAILED, (void*)pxCurrentTCB, xTicksToWait) + +#endif + +/* WAIT and TAKE will be handled identically */ +#undef traceTASK_NOTIFY_TAKE +#define traceTASK_NOTIFY_TAKE traceTASK_NOTIFY_WAIT + +#undef traceTASK_NOTIFY_WAIT_BLOCK +#if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_4_0) + +#define traceTASK_NOTIFY_WAIT_BLOCK(index) \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_TASK_NOTIFY_WAIT_BLOCK, (void*)pxCurrentTCB, xTicksToWait) + +#else + +#define traceTASK_NOTIFY_WAIT_BLOCK() \ + prvTraceStoreEvent_HandleParam(PSF_EVENT_TASK_NOTIFY_WAIT_BLOCK, (void*)pxCurrentTCB, xTicksToWait) + +#endif + +/* WAIT_BLOCK and TAKE_BLOCK will be handled identically */ +#undef traceTASK_NOTIFY_TAKE_BLOCK +#define traceTASK_NOTIFY_TAKE_BLOCK traceTASK_NOTIFY_WAIT_BLOCK + +#undef traceQUEUE_REGISTRY_ADD +#define traceQUEUE_REGISTRY_ADD(object, name) \ + xTraceObjectSetNameWithoutHandle(object, (const char*)(name)); + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1) + +#undef traceSTREAM_BUFFER_CREATE +#define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) \ + xTraceObjectRegisterWithoutHandle((xIsMessageBuffer) == 1 ? PSF_EVENT_MESSAGEBUFFER_CREATE : PSF_EVENT_STREAMBUFFER_CREATE, (void*)(pxStreamBuffer), "", (uint32_t)xBufferSizeBytes) + +#undef traceSTREAM_BUFFER_CREATE_FAILED +#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) \ + prvTraceStoreEvent_HandleParam((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 ) \ + xTraceObjectUnregisterWithoutHandle(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_DELETE : PSF_EVENT_STREAMBUFFER_DELETE, (void*)(xStreamBuffer), prvBytesInBuffer(xStreamBuffer)); + +#undef traceSTREAM_BUFFER_RESET +#define traceSTREAM_BUFFER_RESET( xStreamBuffer ) \ + prvTraceStoreEvent_HandleParam(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RESET : PSF_EVENT_STREAMBUFFER_RESET, (void*)(xStreamBuffer), 0) + +#undef traceSTREAM_BUFFER_SEND +#define traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ) \ + prvTraceStoreEvent_HandleParam(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND : PSF_EVENT_STREAMBUFFER_SEND, (void*)(xStreamBuffer), prvBytesInBuffer(xStreamBuffer)) + +#undef traceBLOCKING_ON_STREAM_BUFFER_SEND +#define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) \ + prvTraceStoreEvent_Handle(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_BLOCK : PSF_EVENT_STREAMBUFFER_SEND_BLOCK, (void*)(xStreamBuffer)) + +#undef traceSTREAM_BUFFER_SEND_FAILED +#define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) \ + prvTraceStoreEvent_Handle(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FAILED : PSF_EVENT_STREAMBUFFER_SEND_FAILED, (void*)(xStreamBuffer)) + +#undef traceSTREAM_BUFFER_RECEIVE +#define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) \ + prvTraceStoreEvent_HandleParam(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE: PSF_EVENT_STREAMBUFFER_RECEIVE, (void*)(xStreamBuffer), prvBytesInBuffer(xStreamBuffer)) + +#undef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE +#define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) \ + prvTraceStoreEvent_Handle(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_BLOCK: PSF_EVENT_STREAMBUFFER_RECEIVE_BLOCK, (void*)(xStreamBuffer)) + +#undef traceSTREAM_BUFFER_RECEIVE_FAILED +#define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) \ + prvTraceStoreEvent_Handle(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FAILED: PSF_EVENT_STREAMBUFFER_RECEIVE_FAILED, (void*)(xStreamBuffer)) + +#undef traceSTREAM_BUFFER_SEND_FROM_ISR +#define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ) \ + if ( (xReturn) > ( size_t ) 0 ) \ + { \ + prvTraceStoreEvent_HandleParam(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR : PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR, (void*)(xStreamBuffer), prvBytesInBuffer(xStreamBuffer)); \ + } \ + else \ + { \ + prvTraceStoreEvent_Handle(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_SEND_FROM_ISR_FAILED : PSF_EVENT_STREAMBUFFER_SEND_FROM_ISR_FAILED, (void*)(xStreamBuffer)); \ + } + +#undef traceSTREAM_BUFFER_RECEIVE_FROM_ISR +#define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) \ + if ( (xReceivedLength) > ( size_t ) 0 ) \ + { \ + prvTraceStoreEvent_HandleParam(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR : PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR, (void*)(xStreamBuffer), prvBytesInBuffer(xStreamBuffer)); \ + } \ + else \ + { \ + prvTraceStoreEvent_Handle(prvGetStreamBufferType(xStreamBuffer) > 0 ? PSF_EVENT_MESSAGEBUFFER_RECEIVE_FROM_ISR_FAILED : PSF_EVENT_STREAMBUFFER_RECEIVE_FROM_ISR_FAILED, (void*)(xStreamBuffer)); \ + } + +#endif + +#endif + +#endif + +#else + +/* 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 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_KERNEL_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcMultiCoreEventBuffer.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcMultiCoreEventBuffer.h new file mode 100644 index 0000000000..7b1bc349d0 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcMultiCoreEventBuffer.h @@ -0,0 +1,143 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @internal Public trace multicore event buffer APIs. + */ + +#ifndef TRC_MULTI_CORE_EVENT_BUFFER_H +#define TRC_MULTI_CORE_EVENT_BUFFER_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_multi_core_event_buffer_apis Trace Multi-Core Event Buffer APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @brief Trace Multi-Core Event Buffer Structure + */ +typedef struct TraceMultiCoreEventBuffer +{ + TraceEventBuffer_t *xEventBuffer[TRC_CFG_CORE_COUNT]; /**< */ +} TraceMultiCoreEventBuffer_t; + +/** + * @internal Initialize multi-core event buffer. + * + * This routine initializes a multi-core trace event buffer and assignts it + * a memory area based on the supplied buffer. + * + * Trace event buffer options specifies the buffer behavior regarding + * old data, the alternatives are TRC_EVENT_BUFFER_OPTION_SKIP and + * TRC_EVENT_BUFFER_OPTION_OVERWRITE (mutal exclusive). + * + * @param[out] pxTraceMultiCoreEventBuffer Pointer to unitialized multi-core trace event buffer. + * @param[in] uiOptions Trace event buffer options. + * @param[in] puiBuffer Pointer to buffer that will be used by the multi-core trace event buffer. + * @param[in] uiSize Size of buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceMultiCoreEventBufferInitialize(TraceMultiCoreEventBuffer_t* pxTraceMultiCoreEventBuffer, uint32_t uiOptions, + uint8_t* puiBuffer, uint32_t uiSize); + + + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +/** + * @brief Pushes data into multi-core trace event buffer. + * + * This routine attempts to push data into the multi-core trace event buffer. Selection + * of which core the data is pushed for is managed automatically through the + * TRC_CFG_GET_CURRENT_CORE macro which is defined on an RTOS basis. + * + * @param[in] pxTraceMultiCoreEventBuffer Pointer to initialized multi-core event buffer. + * @param[in] pvData Pointer to data should be pushed into multi-core event buffer. + * @param[in] uiSize Size of data that should be pushed into multi-core trace event buffer. + * @param[out] piBytesWritten Pointer to variable which the routine will write the number + * of bytes that was pushed into the multi-core trace event buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceMultiCoreEventBufferPush(TraceMultiCoreEventBuffer_t* pxTraceMultiCoreEventBuffer, void* pvData, uint32_t uiSize, int32_t* piBytesWritten); + +#else + +/** + * @brief Pushes data into multi-core trace event buffer. + * + * This routine attempts to push data into the multi-core trace event buffer. Selection + * of which core the data is pushed for is managed automatically through the + * TRC_CFG_GET_CURRENT_CORE macro which is defined on an RTOS basis. + * + * @param[in] pxTraceMultiCoreEventBuffer Pointer to initialized multi-core event buffer. + * @param[in] pvData Pointer to data should be pushed into multi-core event buffer. + * @param[in] uiSize Size of data that should be pushed into multi-core trace event buffer. + * @param[out] piBytesWritten Pointer to variable which the routine will write the number + * of bytes that was pushed into the multi-core trace event buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceMultiCoreEventBufferPush(pxTraceMultiCoreEventBuffer, pvData, uiSize, piBytesWritten) xTraceEventBufferPush((pxTraceMultiCoreEventBuffer)->xEventBuffer[TRC_CFG_GET_CURRENT_CORE()], pvData, uiSize, piBytesWritten) + +#endif + +/** + * @brief Transfer multi-core trace event buffer data through streamport. + * + * This routine will attempt to transfer all existing data in the multi-core trace event + * buffer through the streamport. New data pushed to the trace event buffer + * during the execution of this routine will not be transfered to + * + * @param[in] pxTraceMultiCoreEventBuffer Pointer to initialized multi-core event buffer. + * @param[out] piBytesWritten Pointer to variable which the routine will write the number + * of bytes that was pushed into the multi-core trace event buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceMultiCoreEventBufferTransfer(TraceMultiCoreEventBuffer_t* pxTraceMultiCoreEventBuffer, int32_t* piBytesWritten); + +/** + * @brief Clears all data from event buffer. + * + * @param[in] pxTraceMultiCoreEventBuffer Pointer to initialized multi-core trace event buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceMultiCoreEventBufferClear(TraceMultiCoreEventBuffer_t* pxTraceMultiCoreEventBuffer); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_MULTI_CORE_EVENT_BUFFER_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcObject.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcObject.h new file mode 100644 index 0000000000..4e3a673f13 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcObject.h @@ -0,0 +1,202 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace object APIs. + */ + +#ifndef TRC_OBJECT_H +#define TRC_OBJECT_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_object_apis Trace Object APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @brief Registers trace object. + * + * @param[in] uiEventCode Event code. + * @param[in] pvObject Object. + * @param[in] szName Name. + * @param[in] uxStateCount State count. + * @param[in] uxStates States. + * @param[in] uxOptions Options. + * @param[out] pxObjectHandle Pointer to uninitialized trace object. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceObjectRegisterInternal(uint32_t uiEventCode, void* pvObject, const char* szName, TraceUnsignedBaseType_t uxStateCount, TraceUnsignedBaseType_t uxStates[], TraceUnsignedBaseType_t uxOptions, TraceObjectHandle_t* pxObjectHandle); + +/** + * @brief Registers trace object. + * + * @param[in] uiEventCode Event code. + * @param[in] pvObject Object. + * @param[in] szName Name. + * @param[in] uxState State. + * @param[out] pxObjectHandle Pointer to uninitialized trace object. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceObjectRegister(uint32_t uiEventCode, void *pvObject, const char* szName, TraceUnsignedBaseType_t uxState, TraceObjectHandle_t *pxObjectHandle); + +/** + * @brief Unregisters trace object. + * + * @param[in] xObjectHandle Pointer to initialized trace object. + * @param[in] uiEventCode Event code. + * @param[in] uxState State. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceObjectUnregister(TraceObjectHandle_t xObjectHandle, uint32_t uiEventCode, TraceUnsignedBaseType_t uxState); + +/** + * @brief Sets trace object name. + * + * @param[in] xObjectHandle Pointer to initialized trace object. + * @param[in] szName Name. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceObjectSetName(TraceObjectHandle_t xObjectHandle, const char *szName); + +/** + * @brief Sets trace object state. + * + * @param[in] xObjectHandle Pointer to initialized trace object. + * @param[in] uxState State. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceObjectSetState(xObjectHandle, uxState) xTraceObjectSetSpecificState(xObjectHandle, 0, uxState) + +/** + * @brief Sets trace object specific state state. + * + * @param[in] xObjectHandle Pointer to initialized trace object. + * @param[in] uiIndex State Index. + * @param[in] uxState State. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceObjectSetSpecificState(xObjectHandle, uiIndex, uxState) xTraceEntrySetState((TraceEntryHandle_t)(xObjectHandle), uiIndex, uxState) + +/** + * @brief Sets trace object options. + * + * @param[in] xObjectHandle Pointer to initialized trace object. + * @param[in] uiOptions Options. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceObjectSetOptions(xObjectHandle, uiOptions) xTraceEntrySetOptions((TraceEntryHandle_t)(xObjectHandle), uiOptions) + +/** + * @brief Registers trace object without trace object handle. + * + * @param[in] uiEventCode Event code. + * @param[in] pvObject Object. + * @param[in] szName Name. + * @param[in] uxState State. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceObjectRegisterWithoutHandle(uint32_t uiEventCode, void* pvObject, const char* szName, TraceUnsignedBaseType_t uxState); + +/** + * @brief Unregisters trace object without trace object handle. + * + * @param[in] uiEventCode Event code. + * @param[in] pvObject Object. + * @param[in] uxState State. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceObjectUnregisterWithoutHandle(uint32_t uiEventCode, void* pvObject, TraceUnsignedBaseType_t uxState); + +/** + * @brief Set trace object name without trace object handle. + * + * @param[in] pvObject Object. + * @param[in] szName Name. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceObjectSetNameWithoutHandle(void* pvObject, const char* szName); + +/** + * @brief Set trace object state without trace object handle. + * + * @param[in] pvObject Object. + * @param[in] uxState State. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceObjectSetStateWithoutHandle(pvObject, uxState) xTraceObjectSetSpecificStateWithoutHandle(pvObject, 0, uxState) + +/** + * @brief Sets trace object specific state without trace object + * handle. + * + * @param[in] pvObject Object. + * @param[in] uiIndex State index. + * @param[in] uxState State. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceObjectSetSpecificStateWithoutHandle(void* pvObject, uint32_t uiIndex, TraceUnsignedBaseType_t uxState); + +/** + * @brief Sets trace object options without trace object handle. + * + * @param[in] pvObject Object. + * @param[in] uiOptions Options. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceObjectSetOptionsWithoutHandle(void* pvObject, uint32_t uiOptions); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_OBJECT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcPrint.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcPrint.h new file mode 100644 index 0000000000..67574decb3 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcPrint.h @@ -0,0 +1,207 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace print APIs. + */ + +#ifndef TRC_PRINT_H +#define TRC_PRINT_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_print_apis Trace Print APIs + * @ingroup trace_recorder_apis + * @{ + */ + +#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) + +/** @internal */ +#define TRC_PRINT_BUFFER_SIZE (sizeof(TraceStringHandle_t) + sizeof(TraceStringHandle_t)) + +/** + * @internal Trace Print Buffer Structure + */ +typedef struct TracePrintBuffer +{ + uint32_t buffer[(TRC_PRINT_BUFFER_SIZE) / sizeof(uint32_t)]; +} TracePrintBuffer_t; + +/** + * @internal Initialize print trace system. + * + * @param[in] pxBuffer Pointer to memory that will be used by the print + * trace system. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTracePrintInitialize(TracePrintBuffer_t* pxBuffer); + +/** + * @brief Generate "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 xTraceStringRegister(). + * + * Example: + * + * TraceStringHandle_t xChannel = xTraceStringRegister("MyChannel"); + * ... + * xTracePrint(xChannel, "Hello World!"); + * + * @param[in] xChannel Channel. + * @param[in] szString String. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTracePrint(TraceStringHandle_t xChannel, const char* szString); + +/** + * @brief Wrapper for vTracePrintF for printing to default channel. + * + * Wrapper for vTracePrintF, 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 xTraceConsoleChannelPrintF + * ... + * LogString("My value is: %d", myValue); + * + * @param[in] szFormat Format + * @param[in] ... + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceConsoleChannelPrintF(const char* szFormat, ...); + +/** + * @brief Generates "User Events" with formatted text and data. + * + * 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 xTraceStringRegister(). + * + * Example: + * + * TraceStringHandle_t adc_uechannel = xTraceStringRegister("ADC User Events"); + * ... + * xTracePrintF(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). + * + * @param[in] xChannel Channel. + * @param[in] szFormat Format. + * @param[in] ... + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTracePrintF(TraceStringHandle_t xChannel, const char* szFormat, ...); + +/** + * @brief Generates "User Events" with formatted text and data. + * + * @param[in] xChannel Channel. + * @param[in] szFormat Format. + * @param[in] xVL Variable list arguments. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceVPrintF(TraceStringHandle_t xChannel, const char* szFormat, va_list xVL); + +#else /* (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) */ + +typedef struct TracePrintBuffer +{ + uint32_t buffer[1]; +} TracePrintBuffer_t; + +#define xTracePrintInitialize(p) ((void)p, p != 0 ? TRC_SUCCESS : TRC_FAIL) + +#define xTracePrint(c, s) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3((void)c, (void)s, TRC_SUCCESS) + +#define xTracePrintF(c, s, ...) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3((void)c, (void)s, TRC_SUCCESS) + +#define xTraceConsoleChannelPrintF(s, ...) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2((void)s, TRC_SUCCESS) + +#define xTraceVPrintF(c, s, v) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4((void)c, (void)s, (void)v, TRC_SUCCESS) + +#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + + +#endif /* TRC_PRINT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcRecorder.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcRecorder.h index 3dfbdba76f..a91c010d72 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcRecorder.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcRecorder.h @@ -1,1905 +1,1880 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 */ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef TRC_RECORDER_H +#define TRC_RECORDER_H + +/** + * @file + * + * @brief The public API of the Percepio trace recorder. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Trace Recorder APIs + * @defgroup trace_recorder_apis Trace Recorder APIs + * @{ + * @} + */ + +#define TRC_ACKNOWLEDGED (0xABC99123) + +#include +#include +#include +#include + +#ifndef TRC_CFG_TEST_MODE +#define TRC_CFG_TEST_MODE 0 +#endif + +/* Unless defined by the kernel port, we assume there is no support for + * the classic snapshot mode and default to streaming mode where + * the new RingBuffer snapshot mode provides snapshot functionality. + */ +#ifndef TRC_CFG_RECORDER_MODE +#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_STREAMING +#endif + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) +#include +#include + +/* Calls xTraceError if the _assert condition is false. For void functions, +where no return value is to be provided. */ +#define TRC_ASSERT_VOID(_assert, _err) if (! (_assert)){ prvTraceError(_err); return; } + +/* Calls xTraceError if the _assert condition is false. For non-void functions, +where a return value is to be provided. */ +#define TRC_ASSERT_RET(_assert, _err, _return) if (! (_assert)){ prvTraceError(_err); return _return; } + +typedef uint8_t traceUBChannel; +typedef uint8_t traceObjectClass; + +#undef traceHandle +#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 +#include + +/* Not yet available in snapshot mode */ +#define vTraceConsoleChannelPrintF(fmt, ...) (void) +#define xTraceConsoleChannelPrintF(fmt, ...) (void) +#define prvTraceStoreEvent_None(...) +#define prvTraceStoreEvent_Handle(...) +#define prvTraceStoreEvent_Param(...) +#define prvTraceStoreEvent_HandleParam(...) +#define prvTraceStoreEvent_ParamParam(...) +#define prvTraceStoreEvent_HandleParamParam(...) +#define prvTraceStoreEvent_ParamParamParam(...) + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) */ + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) +#include +#include + +/* Unless specified in trcConfig.h we assume this is a single core target */ +#ifndef TRC_CFG_CORE_COUNT +#define TRC_CFG_CORE_COUNT 1 +#endif + +/* Unless specified in trcConfig.h we assume this is a single core target */ +#ifndef TRC_CFG_GET_CURRENT_CORE +#define TRC_CFG_GET_CURRENT_CORE() 0 +#endif + +/* Unless specified in trcConfig.h or trcKernelPortConfig.h we assume + * GCC statement expressions aren't supported. */ +#ifndef TRC_CFG_USE_GCC_STATEMENT_EXPR +#define TRC_CFG_USE_GCC_STATEMENT_EXPR 0 +#endif + +/* Backwards compatibility */ +typedef TraceISRHandle_t traceHandle; + +/* Maximum event size */ +#define TRC_MAX_BLOB_SIZE (16 * sizeof(uint32_t)) + +/* Platform name length */ +#define TRC_PLATFORM_CFG_LENGTH 8 + +/* Header size */ +#define TRC_HEADER_BUFFER_SIZE (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + (sizeof(char) * (TRC_PLATFORM_CFG_LENGTH)) + sizeof(uint16_t) + sizeof(uint8_t) + sizeof(uint8_t)) + +typedef struct TraceHeaderBuffer +{ + uint8_t buffer[TRC_HEADER_BUFFER_SIZE]; +} TraceHeaderBuffer_t; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +/******************************************************************************/ +/*** Common API - both Snapshot and Streaming mode ****************************/ +/******************************************************************************/ + +/** + * @brief + * + * Initializes the recorder data. xTraceInitialize() or xTraceEnable(...) + * must be called before any attempts at adding trace data/information. + * See xTraceEnable(...) for more information. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceInitialize(void); + +/** + * @brief + * + * This function enables tracing. + * To use the trace recorder, the startup must call xTraceInitialize() or + * xTraceEnable(...) 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 xTraceInitialize() + * 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 trcStreamPort.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 xTraceEnable with + * this option from the startup code, you start tracing at this point and capture + * the early events. + * + * TRC_START_FROM_HOST: For streaming mode only. Initializes the trace recorder + * if necessary and creates a task that waits for a Start command from + * Tracealyzer ("Start Recording" button). This call is not blocking. + * + * @example Usage examples + * + * Snapshot trace, from startup: + * + * xTraceEnable(TRC_START); // Will call xTraceInitialize() + * + * + * Snapshot trace, from a later point: + * + * xTraceInitialize(); + * + * ... + * xTraceEnable(TRC_START); // e.g., in task context, at some relevant event + * + * Streaming trace, from startup (can only be used with certain stream ports): + * + * xTraceInitialize(); + * + * xTraceEnable(TRC_START); + * + * Streaming trace, from startup: + * + * xTraceEnable(TRC_START_AWAIT_HOST); // Blocks! + * + * + * Streaming trace, from a later point: + * + * xTraceInitialize(); + * + * xTraceEnable(TRC_START); + * + * Streaming trace, system executes normally until host starts tracing: + * + * xTraceInitialize(); + * + * xTraceEnable(TRC_START_FROM_HOST) + * + * @param[in] uiStartOption Start option. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceEnable(uint32_t uiStartOption); + +/** + * @brief Disables tracing. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceDisable(void); + +/** + * @brief + * + * For snapshot mode only: 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 trcKernelPortConfig.h for certain kernels. + * + * @param[in] filterGroup Filter group + */ +void vTraceSetFilterGroup(uint16_t filterGroup); + +/** + * @brief + * + * For snapshot mode only: 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. + * + * @param[in] filterMask Filter mask + */ +void vTraceSetFilterMask(uint16_t filterMask); + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + +#include + +/** + * @brief Returns lower 16 bits of a value + * + * @param[in] value The starting value + */ +#define TRACE_GET_LOW16(value) ((uint16_t)((value) & 0x0000FFFF)) + +/** + * @brief Returns upper 16 bits + * + * @param[in] value The starting value + */ +#define TRACE_GET_HIGH16(value) ((uint16_t)(((value) >> 16) & 0x0000FFFF)) + +/** + * @brief Sets lower 16 bits + * + * @param[in] current The starting value + * @param[in] value The value to set + */ +#define TRACE_SET_LOW16(current, value) (((current) & 0xFFFF0000) | (value)) + +/** + * @brief Sets upper 16 bits + * + * @param[in] current The starting value + * @param[in] value The value to set + */ +#define TRACE_SET_HIGH16(current, value) (((current) & 0x0000FFFF) | (((uint32_t)(value)) << 16)) + +#if defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) +/** + * @brief Adds a task to the stack monitor + * + * @param[in] task The task + */ +void prvAddTaskToStackMonitor(void* task); + +/** + * @brief Remove a task from the stack monitor + * + * @param[in] task The task + */ +void prvRemoveTaskFromStackMonitor(void* task); + +/** + * @brief Reports on the current stack usage + */ +void prvReportStackUsage(void); + +#else /* defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ + +#define prvAddTaskToStackMonitor(task) +#define prvRemoveTaskFromStackMonitor(task) +#define prvReportStackUsage() + +#endif /* defined (TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ + +/** + * @brief Query if recorder is enabled + * + * @retval 1 if recorder is enabled + * @retval 0 if recorder is disabled + */ +uint32_t xTraceIsRecorderEnabled(void); + +/** + * @brief + * + * @retval 1 if recorder is initialized + * @retval 0 if recorder isn't initialized + */ +uint32_t xTraceIsRecorderInitialized(void); + +/** + * @brief + * + * 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. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTaskInstanceFinishedNow(void); + +/** + * @brief + * + * 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. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTaskInstanceFinishedNext(void); + +/** + * @brief Registers a string and returns a handle that can be used when tracing + * + * @param[in] label Label + * @param[out] pxString String handle + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStringRegister(const char* label, TraceStringHandle_t* pxString); + +/** + * @brief Registers a string and returns a handle that can be used when tracing + * + * @deprecated Backwards compatibility + * + * @param[in] name Name. + * + * @return TraceStringHandle_t String handle + */ +TraceStringHandle_t xTraceRegisterString(const char* name); + +#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) +/** + * @brief + * + * 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 xTraceStringRegister(). + * + * Example: + * + * TraceStringHandle_t adc_uechannel; + * xTraceStringRegister("ADC User Events", &adc_uechannel); + * ... + * xTracePrintF(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 xTraceStringRegister and use the returned TraceStringHandle_t as + * the argument. In snapshot you simply provide a char* as argument. + * + * Snapshot: xTracePrintF(myChn, "my string: %s", str); + * Streaming: xTracePrintF(myChn, "my string: %s", strTraceString); + * + * 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. + * + * @param[in] chn Channel. + * @param[in] fmt Formatting. + * @param[in] ... + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTracePrintF(TraceStringHandle_t chn, const char* fmt, ...); +#else +#define xTracePrintF(chn, fmt, ...) ((void)(chn), (void)(fmt), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#endif + +#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) +/** + * @brief + * + * xTracePrintF variant that accepts a va_list. + * See xTracePrintF documentation for further details. + * + * @param[in] eventLabel + * @param[in] formatStr + * @param[in] vl + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceVPrintF(TraceStringHandle_t eventLabel, const char* formatStr, va_list vl); +#else +#define xTraceVPrintF(chn, formatStr, vl) ((void)(chn), (void)(formatStr), (void)(vl), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#endif + +#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) +/** + * @brief A faster version of xTracePrintF, that only allows for logging a string. + * + * Example: + * + * TraceStringHandle_t chn; + * xTraceStringRegister("MyChannel", &chn); + * ... + * xTracePrint(chn, "Hello World!"); + * + * @param[in] chn Channel. + * @param[in] str String. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTracePrint(TraceStringHandle_t chn, const char* str); +#else +#define xTracePrint(chn, str) ((void)(chn), (void)(str), TRC_SUCCESS) +#endif + +/******************************************************************************/ +/*** Extended API for Snapshot mode *******************************************/ +/******************************************************************************/ + +/** + * @brief Trace stop callback type. + */ +typedef void(*TRACE_STOP_HOOK)(void); + +/** + * @brief Sets a function to be called when the recorder is stopped. + * + * @note Snapshot mode only! + * + * @param[in] stopHookFunction + */ +void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction); + +/** + * @brief + * + * Resets the recorder. + * + * Only necessary if a restart is desired - this is not + * needed in the startup initialization. + * + * @note 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) \ + if ((pxTCB) != 0) \ + { \ + 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)); \ + } \ + else \ + { \ + /* pxTCB is null */ \ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + { \ + prvTraceStoreKernelCall(SERVICE, TRACE_CLASS_TASK, 0); \ + } \ + } + +/* 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 setup a task in the object table */ +#undef trcKERNEL_HOOKS_OBJECT_CREATE_FAILED +#define trcKERNEL_HOOKS_OBJECT_CREATE_FAILED(SERVICE, TRACE_CLASS)\ + if (TRACE_GET_OBJECT_FILTER(TASK, TRACE_GET_CURRENT_TASK()) & CurrentFilterMask) \ + { \ + prvTraceStoreKernelCall(SERVICE, TRACE_CLASS, 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)); + +/* This macro will create an event to indicate that the task has been resumed from ISR */ +#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 +/** + * @brief Dynamically enables ready events + * + * @param[in] flag Flag + */ +void prvTraceSetReadyEventsEnabled(uint32_t flag); + +/** + * @brief Stores a Task Ready event + * + * @param[in] handle Task handle + */ +void prvTraceStoreTaskReady(traceHandle handle); +#else +#define prvTraceSetReadyEventsEnabled(status) (void)status; +#endif + +/** + * @brief Stores a Low Power mode event + * + * @param[in] flag Flag + */ +void prvTraceStoreLowPower(uint32_t flag); + +/** + * @brief Stores a Task Switch event + * + * @param[in] task_handle Task + */ +void prvTraceStoreTaskswitch(traceHandle task_handle); + +#if (TRC_CFG_SCHEDULING_ONLY == 0) + +/** + * @brief Stores a Kernel Service call event with an Object handle parameter + * + * @param[in] eventcode Event code + * @param[in] objectClass Object class + * @param[in] objectNumber Object handle + */ +void prvTraceStoreKernelCall(uint32_t eventcode, traceObjectClass objectClass, uint32_t objectNumber); + +/** + * @brief Stores a Kernel Service call event with only a numeric parameter + * + * @param[in] evtcode Event code + * @param[in] param Parameter + */ +void prvTraceStoreKernelCallWithNumericParamOnly(uint32_t evtcode, uint32_t param); + +/** + * @brief Stores a Kernel Service call event with an Object handle and a numeric parameter + * + * @param[in] evtcode Event code + * @param[in] objectClass Object class + * @param[in] objectNumber Object handle + * @param[in] param Parameter + */ +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 + +/** + * @brief Flags a task instance as finished + * + * @param[in] handle Task handle + */ +void prvTraceSetTaskInstanceFinished(traceHandle handle); + +/** + * @brief Set priority + * + * @param[in] objectclass Object class + * @param[in] id Object handle + * @param[in] value Value + */ +void prvTraceSetPriorityProperty(uint8_t objectclass, traceHandle id, uint8_t value); + +/** + * @brief Get priority + * + * @param[in] objectclass Object class + * @param[in] id Object handle + * + * @return uint8_t Value + */ +uint8_t prvTraceGetPriorityProperty(uint8_t objectclass, traceHandle id); + +/** + * @brief Set object state + * + * @param[in] objectclass Object class + * @param[in] id Object handle + * @param[in] value Value + */ +void prvTraceSetObjectState(uint8_t objectclass, traceHandle id, uint8_t value); + +/** + * @brief Mark object as used + * + * @param[in] objectclass Object class + * @param[in] handle Object handle + */ +void prvMarkObjectAsUsed(traceObjectClass objectclass, traceHandle handle); + +/** + * @brief Stores the name of an object because it is being deleted + * + * @param[in] evtcode Event code + * @param[in] handle Object handle + * @param[in] objectclass Object class + */ +void prvTraceStoreObjectNameOnCloseEvent(uint8_t evtcode, traceHandle handle, + traceObjectClass objectclass); + +/** + * @brief Stores the property of an object because it is being deleted + * + * @param[in] evtcode Event code + * @param[in] handle Object handle + * @param[in] objectclass Object class + */ +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)*/ + +/** + * @brief + * + * 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. + * + * @return void* Buffer pointer + */ +void* xTraceGetTraceBuffer(void); + +/** + * @brief + * + * Gets the size of the recorder data structure. For use together with + * xTraceGetTraceBuffer if you wish to implement an own store/upload solution, + * e.g., in case a debugger connection is not available for uploading the data. + * + * @return uint32_t Buffer size + */ +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)) && (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) + +/** + * @brief Register a channel and fixed format string for use with the separate User Event Buffer functions + * + * @param[in] channel Channel name handle + * @param[in] formatStr Format string that will be used for all events on this channel + * + * @return traceUBChannel Channel handle + */ +traceUBChannel xTraceRegisterUBChannel(TraceStringHandle_t channel, TraceStringHandle_t formatStr); + +/** + * @brief Creates a User Event using the channel, previously set format string and data parameters + * + * @param[in] channel Channel + * @param[in] ... + */ +void vTraceUBData(traceUBChannel channel, ...); + +/** + * @brief Creates a User Event using the channel and previously set string + * + * @param[in] channel Channel + */ +void vTraceUBEvent(traceUBChannel channel); +#else +#define xTraceRegisterChannelFormat(eventLabel, formatStr) ((void)(eventLabel), (void)(formatStr), 0) +#define vTraceUBData(label, ...) (void)(label) +#endif /*(TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 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 + +/** + * @brief Object handle stack struct. + * + * 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 +{ + uint16_t indexOfNextAvailableHandle[ TRACE_NCLASSES ]; /**< For each object class, the index of the next handle to allocate */ + uint16_t lowestIndexOfClass[ TRACE_NCLASSES ]; /**< The lowest index of this class (constant) */ + uint16_t highestIndexOfClass[ TRACE_NCLASSES ]; /**< The highest index of this class (constant) */ + uint16_t handleCountWaterMarksOfClass[ TRACE_NCLASSES ]; /**< The highest use count for this class (for statistics) */ + traceHandle objectHandles[ TRACE_KERNEL_OBJECT_COUNT ]; /**< The free object handles - a set of stacks within this array */ +} objectHandleStackType; + +extern objectHandleStackType objectHandleStacks; + +/** + * @brief Object property table struct + * + * 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) ]; /**< */ + + /* Allocation size rounded up to the closest multiple of 2 */ + uint8_t TotalPropertyBytesPerClass[ 4*((TRACE_NCLASSES+3)/4) ]; /**< */ + + /* */ + 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; + +/** + * @brief Symbol table 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 +{ + TraceStringHandle_t name; + TraceStringHandle_t 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 /* (TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER == 1) */ + +/******************************************************************************* + * 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 7 */ + 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; + + /* The maximum amount of heap memory that was allocated */ + uint32_t heapMemMaxUsage; + + /* The amount of heap memory used */ + 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 */ + +/** + * @brief Signals a trace error + * + * @param[in] msg Message + */ +void prvTraceError(const char* msg); + +/** + * @brief + * + * 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. + * + * @param[out] puiTimestamp Timestamp + */ +void prvTracePortGetTimeStamp(uint32_t *puiTimestamp); + +/** + * @brief Reserve an object handle + * + * @param[in] objectclass Object class + * + * @return traceHandle + */ +traceHandle prvTraceGetObjectHandle(traceObjectClass objectclass); + +/** + * @brief Free an object handle + * + * @param[in] objectclass Object class + * @param[in] handle Handle + */ +void prvTraceFreeObjectHandle(traceObjectClass objectclass, + traceHandle handle); + +/* Private function. Use the public functions in trcKernelPort.h */ + +/** + * @brief Set the object name + * + * @param[in] objectclass Object class + * @param[in] handle Handle + * @param[in] name Name + */ +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 + +typedef RecorderDataType TraceRecorderDataBuffer_t; + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)*/ + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#ifndef TRC_EXTERNAL_BUFFERS +#define TRC_EXTERNAL_BUFFERS 0 +#endif + +typedef struct TraceRecorderData +{ + uint32_t uiSessionCounter; + uint32_t uiRecorderEnabled; + uint32_t uiTraceSystemState; + + TraceAssertBuffer_t xAssertBuffer; +#if (TRC_EXTERNAL_BUFFERS == 0) + TraceHeaderBuffer_t xHeaderBuffer; + TraceEntryTableBuffer_t xEntryTableBuffer; + TraceTimestampBuffer_t xTimestampBuffer; +#endif + TraceStreamPortBuffer_t xStreamPortBuffer; + TraceStaticBufferBuffer_t xStaticBufferBuffer; + TraceEventDataBuffer_t xEventDataBuffer; + TracePrintBuffer_t xPrintBuffer; + TraceErrorBuffer_t xErrorBuffer; + TraceISRInfoBuffer_t xISRInfoBuffer; + TraceKernelPortDataBuffer_t xKernelPortBuffer; + TraceTaskInfoBuffer_t xTaskInfoBuffer; + TraceStackMonitorBuffer_t xStackMonitorBuffer; + TraceDiagnosticsBuffer_t xDiagnosticsBuffer; +} TraceRecorderData_t; + +extern TraceRecorderData_t* pxTraceRecorderData; +extern uint32_t RecorderInitialized; + +#define TRC_RECORDER_DATA_BUFFER_SIZE (sizeof(TraceRecorderData_t)) + +typedef struct TraceRecorderDataBuffer +{ + uint8_t buffer[(TRC_RECORDER_DATA_BUFFER_SIZE)]; +} TraceRecorderDataBuffer_t; + +/** + * @brief Initializes the header data + * + * @param[in] pxBuffer Pointer to header buffer + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceHeaderInitialize(TraceHeaderBuffer_t* pxBuffer); + +/** + * @brief Query if recorder is enabled + * + * @retval 1 Recorder enabled + * @retval 0 Recorder not enabled + */ +#define xTraceIsRecorderEnabled() (xTraceIsRecorderInitialized() & pxTraceRecorderData->uiRecorderEnabled) + +/** + * @brief Query if recorder initialized + * + * @retval 1 Recorder initialized + * @retval 0 Recorder not initialized + */ +#define xTraceIsRecorderInitialized() xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_CORE) + +/** + * @brief Flag component as initialized + * + * @param[in] uiComponentBit Component bit + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceSetComponentInitialized(uiComponentBit) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(RecorderInitialized |= (uiComponentBit), TRC_SUCCESS) + +/** + * @brief Query if component is initialized + * + * @param[in] uiComponentBit Component bit + * + * @retval 1 Component initialized + * @retval 0 Component not initialized + */ +#define xTraceIsComponentInitialized(uiComponentBit) ((RecorderInitialized & (uiComponentBit)) ? 1 : 0) + +/** + * @brief Set the trace state + * + * @param[in] uiState State + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceStateSet(uiState) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(pxTraceRecorderData->uiTraceSystemState = (uiState), TRC_SUCCESS) + +/** + * @brief Query the trace state + * + * @param[out] puiState State + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceStateGet(puiState) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(puiState) = pxTraceRecorderData->uiTraceSystemState, TRC_SUCCESS) + +/** + * @brief Call this function periodically + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTzCtrl(void); + +/******************************************************************************/ +/*** INTERNAL STREAMING FUNCTIONS *********************************************/ +/******************************************************************************/ + +/** + * @brief Stores an event without parameters + * + * @param[in] _eventID Event id + */ +#define prvTraceStoreEvent_None(_eventID) \ + { \ + TraceEventHandle_t _xEventHandle = 0; \ + if (xTraceEventBegin(_eventID, 0, &_xEventHandle) == TRC_SUCCESS) \ + { \ + xTraceEventEnd(_xEventHandle); \ + } \ + } + +/** + * @brief Stores an event with a handle parameter + * + * @param[in] _eventID Event id + * @param[in] _handle Handle + */ +#define prvTraceStoreEvent_Handle(_eventID, _handle) \ + { \ + TraceEventHandle_t _xEventHandle = 0; \ + if (xTraceEventBegin(_eventID, sizeof(void*), &_xEventHandle) == TRC_SUCCESS) \ + { \ + xTraceEventAddPointer(_xEventHandle, (void*)(_handle)); \ + xTraceEventEnd(_xEventHandle); \ + } \ + } + +/** + * @brief Stores an event with one 32-bit parameter + * + * @param[in] _eventID Event id + * @param[in] _param1 Param + */ +#define prvTraceStoreEvent_Param(_eventID, _param1) \ + { \ + TraceEventHandle_t _xEventHandle = 0; \ + if (xTraceEventBegin(_eventID, sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \ + { \ + xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \ + xTraceEventEnd(_xEventHandle); \ + } \ + } + +/** + * @brief Stores an event with a handle and one 32-bit parameter + * + * @param[in] _eventID Event id + * @param[in] _handle Handle + * @param[in] _param1 Param + */ +#define prvTraceStoreEvent_HandleParam(_eventID, _handle, _param1) \ + { \ + TraceEventHandle_t _xEventHandle = 0; \ + if (xTraceEventBegin(_eventID, sizeof(void*) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \ + { \ + xTraceEventAddPointer(_xEventHandle, (void*)(_handle)); \ + xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \ + xTraceEventEnd(_xEventHandle); \ + } \ + } + +/** + * @brief Stores an event with two 32-bit parameters + * + * @param[in] _eventID Event id + * @param[in] _param1 Param 1 + * @param[in] _param2 Param 2 + */ +#define prvTraceStoreEvent_ParamParam(_eventID, _param1, _param2) \ + { \ + TraceEventHandle_t _xEventHandle = 0; \ + if (xTraceEventBegin(_eventID, sizeof(uint32_t) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \ + { \ + xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \ + xTraceEventAdd32(_xEventHandle, (uint32_t)(_param2)); \ + xTraceEventEnd(_xEventHandle); \ + } \ + } + +/** + * @brief Stores an event with a handle and two 32-bit parameters + * + * @param[in] _eventID Event id + * @param[in] _handle Handle + * @param[in] _param1 Param 1 + * @param[in] _param2 Param 2 + */ +#define prvTraceStoreEvent_HandleParamParam(_eventID, _handle, _param1, _param2) \ + { \ + TraceEventHandle_t _xEventHandle = 0; \ + if (xTraceEventBegin(_eventID, sizeof(void*) + sizeof(uint32_t) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \ + { \ + xTraceEventAddPointer(_xEventHandle, (void*)(_handle)); \ + xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \ + xTraceEventAdd32(_xEventHandle, (uint32_t)(_param2)); \ + xTraceEventEnd(_xEventHandle); \ + } \ + } + +/** + * @brief Stores an event with three 32-bit parameters + * + * @param[in] _eventID Event id + * @param[in] _param1 Param 1 + * @param[in] _param2 Param 2 + * @param[in] _param3 Param 3 + */ +#define prvTraceStoreEvent_ParamParamParam(_eventID, _param1, _param2, _param3) \ + { \ + TraceEventHandle_t _xEventHandle = 0; \ + if (xTraceEventBegin(_eventID, sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t), &_xEventHandle) == TRC_SUCCESS) \ + { \ + xTraceEventAdd32(_xEventHandle, (uint32_t)(_param1)); \ + xTraceEventAdd32(_xEventHandle, (uint32_t)(_param2)); \ + xTraceEventAdd32(_xEventHandle, (uint32_t)(_param3)); \ + xTraceEventEnd(_xEventHandle); \ + } \ + } + +/** + * @brief Snapshot mode only. Trace stop hook. + * + * @param[in] x + */ +#define vTraceSetStopHook(x) (void)(x) + +/** + * @brief Snapshot mode only. Initialize timestamps. + */ +#define vTraceInitTimestamps() + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) +/** + * @brief Set the recorder data buffer + * + * @param[in] pxBuffer Pointer to the recorder data buffer + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceSetBuffer(TraceRecorderDataBuffer_t *pxBuffer); +#else +#define xTraceSetBuffer(p) (TRC_SUCCESS) +#endif + +/** + * @brief Retrieve the event buffer and event buffer size + * + * @param[out] ppvBuffer Pointer where event buffer pointer will be written + * @param[out] puiSize Event buffer size + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceGetEventBuffer(void** ppvBuffer, TraceUnsignedBaseType_t * puiSize); + +#else /* when TRC_USE_TRACEALYZER_RECORDER == 0 */ + +#define xTraceInitialize() (TRC_SUCCESS) +#define xTraceEnable(x) ((void)(x), TRC_SUCCESS) +#define xTraceDisable() (TRC_SUCCESS) +#define xTraceStringRegister(x, y) ((void)(x), (void)y, TRC_SUCCESS) /* Comma operator in parenthesis is used to avoid "unused variable" compiler warnings and return 0 in a single statement */ +#define xTracePrint(chn, ...) ((void)(chn), TRC_SUCCESS) +#define xTracePrintF(chn, fmt, ...) ((void)(chn), (void)(fmt), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#define xTraceVPrintF(chn, formatStr, vl) ((void)(chn), (void)(formatStr), (void)(vl), TRC_SUCCESS) /* Comma operator is used to avoid "unused variable" compiler warnings in a single statement */ +#define xTraceTaskInstanceFinishedNow() +#define xTraceTaskInstanceFinishedNext() +#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 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 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 vTraceConsoleChannelPrintF(fmt, ...) (void)(fmt) + +#ifndef TRC_ALLOC_CUSTOM_BUFFER +#define TRC_ALLOC_CUSTOM_BUFFER(bufname) +#endif + +#define xTraceIsRecorderEnabled() (0) +#define xTraceIsRecorderInitialized() (0) + +#define xTraceSetBuffer(p) (TRC_SUCCESS) +#define xTraceGetEventBuffer(p) (TRC_FAIL) + +#define vTraceSetStopHook(x) (void)(x) + +#define TraceRecorderDataBuffer_t uint32_t + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +/** + * @deprecated Backwards compatibility. Use xTraceInitialize instead. + */ +#define vTraceInitialize (void)xTraceInitialize + +/** + * @deprecated Backwards compatibility. Use xTraceEnable instead. + */ +#define vTraceEnable (void)xTraceEnable + +/** + * @deprecated Backwards compatibility. Use xTraceDisable instead. + */ +#define vTraceStop (void)xTraceDisable + +/** + * @deprecated Backwards compatibility. Use xTraceTaskInstanceFinishedNow instead. + */ +#define vTraceInstanceFinishedNow (void)xTraceTaskInstanceFinishedNow + +/** + * @deprecated Backwards compatibility. Use xTraceTaskInstanceFinishedNext instead. + */ +#define vTraceInstanceFinishedNext (void)xTraceTaskInstanceFinishedNext + +/** + * @deprecated Backwards compatibility. Use xTracePrintF instead. + */ +#define vTracePrintF (void)xTracePrintF + +/** + * @deprecated Backwards compatibility. Use xTraceVPrintF instead. + */ +#define vTraceVPrintF (void)xTraceVPrintF + +/** + * @deprecated Backwards compatibility. Use xTracePrint instead. + */ +#define vTracePrint (void)xTracePrint + +/** + * @deprecated Backwards compatibility. Use xTraceSetBuffer instead. + */ +#define vTraceSetRecorderDataBuffer(pxBuffer) xTraceSetBuffer((TraceRecorderDataBuffer_t*)(pxBuffer)) + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_RECORDER_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcStackMonitor.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcStackMonitor.h new file mode 100644 index 0000000000..c5b9c5f6fc --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcStackMonitor.h @@ -0,0 +1,135 @@ +/* +* Percepio Trace Recorder SDK for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace stack monitor APIs. + */ + +#ifndef TRC_STACK_MONITOR_H +#define TRC_STACK_MONITOR_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_stack_monitor_apis Trace Stack Monitor APIs + * @ingroup trace_recorder_apis + * @{ + */ + +#if (((TRC_CFG_ENABLE_STACK_MONITOR) == 1) && ((TRC_CFG_SCHEDULING_ONLY) == 0)) + +#define TRACE_STACK_MONITOR_BUFFER_SIZE ((sizeof(void*) + sizeof(TraceUnsignedBaseType_t)) * (TRC_CFG_STACK_MONITOR_MAX_TASKS) + sizeof(uint32_t)) + +/** + * @internal Trace Stack Monitor Buffer Structure + */ +typedef struct TraceStackMonitorBuffer +{ + uint32_t buffer[(TRACE_STACK_MONITOR_BUFFER_SIZE) / sizeof(uint32_t)]; +} TraceStackMonitorBuffer_t; + +/** + * @internal Initialize trace stack monitor system. + * + * @param[in] pxBuffer Pointer to memory that will be used by the trace + * stack monitor system. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStackMonitorInitialize(TraceStackMonitorBuffer_t* pxBuffer); + +/** + * @brief Adds task/thread to trace stack monitor. + * + * @param[in] pvTask Task/Thread. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStackMonitorAdd(void* pvTask); + +/** + * @brief Removes task/thread from trace stack monitor. + * + * @param[in] pvTask Task/Thread. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStackMonitorRemove(void* pvTask); + +/** + * @brief Gets trace stack monitor tread/task at index. + * + * @param[in] uiIndex Index. + * @param[in] ppvTask Task/Thread. + * @param[out] puxLowWaterMark Low water mark. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStackMonitorGetAtIndex(uint32_t uiIndex, void** ppvTask, TraceUnsignedBaseType_t* puxLowWaterMark); + +/** + * @brief Performs trace stack monitor reporting. + * + * This routine performs a trace stack monitor check and report + * for TRC_CFG_STACK_MONITOR_MAX_REPORTS number of registered + * tasks/threads. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStackMonitorReport(void); + +#else /* (((TRC_CFG_ENABLE_STACK_MONITOR) == 1) && ((TRC_CFG_SCHEDULING_ONLY) == 0)) */ + +typedef struct TraceStackMonitorBuffer +{ + uint32_t buffer[1]; +} TraceStackMonitorBuffer_t; + +#define xTraceStackMonitorInitialize(pxBuffer) ((void)pxBuffer, TRC_SUCCESS) + +#define xTraceStackMonitorDiagnosticsGet(xType, puiValue) ((void)xType, puiValue != 0 ? *puiValue = 0 : 0, puiValue != 0 ? TRC_SUCCESS : TRC_FAIL) + +#define xTraceStackMonitorDiagnosticsSet(xType, uiValue) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3((void)xType, (void)uiValue, TRC_SUCCESS) + +#define xTraceStackMonitorAdd(pvTask) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2((void)pvTask, TRC_SUCCESS) + +#define xTraceStackMonitorRemove(pvTask) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2((void)pvTask, TRC_SUCCESS) + +#define xTraceStackMonitorGetAtIndex(uiIndex, ppvTask, puxLowWaterMark) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4((void)uiIndex, (void)ppvTask, (void)puxLowWaterMark, TRC_SUCCESS) + +#define xTraceStackMonitorReport() TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(TRC_SUCCESS) + +#endif /* (((TRC_CFG_ENABLE_STACK_MONITOR) == 1) && ((TRC_CFG_SCHEDULING_ONLY) == 0)) */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_STACK_MONITOR_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcStateMachine.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcStateMachine.h new file mode 100644 index 0000000000..f5f68400c7 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcStateMachine.h @@ -0,0 +1,78 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace state machine APIs. + */ + +#ifndef TRC_STATE_MACHINE_H +#define TRC_STATE_MACHINE_H + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_state_machine_apis Trace State Machine APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @brief Creates trace state machine. + * + * @param[in] szName Name. + * @param[out] pxStateMachineHandle Pointer to uninitialized trace state machine. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStateMachineCreate(const char *szName, TraceStateMachineHandle_t *pxStateMachineHandle); + +/** + * @brief Creates trace state machine state. + * + * @param[in] xStateMachineHandle Pointer to initialized trace state machine. + * @param[in] szName Name. + * @param[out] pxStateHandle Pointer to uninitialized trace state machine state. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStateMachineStateCreate(TraceStateMachineHandle_t xStateMachineHandle, const char *szName, TraceStateMachineStateHandle_t *pxStateHandle); + +/** + * @brief Sets trace state machine state. + * + * @param[in] xStateMachineHandle Pointer to initialized trace state machine. + * @param[in] xStateHandle Pointer to initialized trace state machine state. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStateMachineSetState(TraceStateMachineHandle_t xStateMachineHandle, TraceStateMachineStateHandle_t xStateHandle); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_STATE_MACHINE_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcStaticBuffer.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcStaticBuffer.h new file mode 100644 index 0000000000..4a7fa72a7d --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcStaticBuffer.h @@ -0,0 +1,112 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace static buffer APIs. + */ + +#ifndef TRC_STATIC_BUFFER_H +#define TRC_STATIC_BUFFER_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_static_buffer_apis Trace Static Buffer APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/* A buffer type that is maximum size */ +typedef uint8_t TraceStaticBuffer_t[TRC_MAX_BLOB_SIZE]; + +/** + * @internal Trace Core Static Buffer Core Structure + */ +typedef struct TraceCoreStaticBufferCore +{ + TraceStaticBuffer_t dummyEvents[(TRC_CFG_MAX_ISR_NESTING)+1]; /**< */ +} TraceCoreStaticBuffer_t; + +/** + * @internal Trace Static Buffer Table Structure + */ +typedef struct TraceStaticBufferTable +{ + TraceCoreStaticBuffer_t coreDummyEvents[TRC_CFG_CORE_COUNT]; /**< Temporary buffers used for event or blob creation. */ +} TraceStaticBufferTable_t; + +#define TRC_STATIC_BUFFER_BUFFER_SIZE (sizeof(TraceStaticBufferTable_t)) + +/** + * @internal Trace Static Buffer Buffer Structure + */ +typedef struct TraceStaticBufferBuffer +{ + uint8_t buffer[TRC_STATIC_BUFFER_BUFFER_SIZE]; /**< */ +} TraceStaticBufferBuffer_t; + +extern TraceStaticBufferTable_t* pxTraceStaticBufferTable; + +/** + * @internal Initialize trace static buffer. + * + * @param[in] pxBuffer Pointer to memory that will be used by the + * trace static buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStaticBufferInitialize(TraceStaticBufferBuffer_t* pxBuffer); + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +/** + * @brief Gets trace static buffer. + * + * @param[out] ppvBuffer Buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStaticBufferGet(void **ppvBuffer); + +#else /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/** + * @brief Gets trace static buffer. + * + * @param[out] ppvBuffer Buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceStaticBufferGet(ppvBuffer) (*ppvBuffer = (void*)&pxTraceStaticBufferTable->coreDummyEvents[TRC_CFG_GET_CURRENT_CORE()].dummyEvents[xTraceISRGetCurrentNestingReturned() + 1], TRC_SUCCESS) + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_STATIC_BUFFER_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcString.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcString.h new file mode 100644 index 0000000000..5f2ed69464 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcString.h @@ -0,0 +1,76 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace string APIs. + */ + +#ifndef TRC_STRING_H +#define TRC_STRING_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_string_apis Trace String APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @brief Registers a trace string. + * + * This routine registers a strings in the recorder, e.g. for names of user + * event channels. + * + * Example: + * TraceStringHandle_t myEventHandle; + * xTraceStringRegister("MyUserEvent", &myEventHandle); + * ... + * xTracePrintF(myEventHandle, "My value is: %d", myValue); + * + * @param[in] szString String. + * @param[out] pString Pointer to uninitialized trace string. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStringRegister(const char *szString, TraceStringHandle_t* pString); + +/** + * @brief Registers a trace string. + * + * @deprecated Remains for backward compability with pre v4.6 versions + * of the recorder. + * + * @param[in] name Name. + * + * @return TraceStringHandle_t + */ +TraceStringHandle_t xTraceRegisterString(const char *name); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_STRING_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTask.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTask.h new file mode 100644 index 0000000000..e063527dca --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTask.h @@ -0,0 +1,243 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace task APIs. + */ + +#ifndef TRC_TASK_H +#define TRC_TASK_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_task_apis Trace Task APIs + * @ingroup trace_recorder_apis + * @{ + */ + +#ifndef TRC_CFG_ENABLE_STACK_MONITOR +#define TRC_CFG_ENABLE_STACK_MONITOR 0 +#endif + +/** + * @internal Trace Task Info Structure + */ +typedef struct TraceTaskInfo +{ + void* coreTasks[TRC_CFG_CORE_COUNT]; +} TraceTaskInfo_t; + +extern TraceTaskInfo_t* pxTraceTaskInfo; + +#define TRACE_TASK_INFO_BUFFER_SIZE (sizeof(TraceTaskInfo_t)) + +/** + * @internal Trace Task Info Buffer Structure + */ +typedef struct TraceTaskInfoBuffer +{ + uint8_t buffer[TRACE_TASK_INFO_BUFFER_SIZE]; +} TraceTaskInfoBuffer_t; + +/** + * @internal Initialize trace task system. + * + * @param[in] pxBuffer Pointer to memory that will be used by the + * trace task system. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTaskInitialize(TraceTaskInfoBuffer_t* pxBuffer); + +/** + * @brief Register trace task in the trace. + * + * @param[in] pvTask Task. + * @param[in] szName Name. + * @param[in] uxPriority Priority. + * @param[out] pxTaskHandle Pointer to uninitialized trace task. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTaskRegister(pvTask, szName, uxPriority, pxTaskHandle) ((((pvTask) != 0) && (xTraceObjectRegister(PSF_EVENT_TASK_CREATE, pvTask, szName, uxPriority, (TraceObjectHandle_t*)(pxTaskHandle)) == TRC_SUCCESS)) ? (xTraceStackMonitorAdd(pvTask), TRC_SUCCESS) : TRC_FAIL) + +/** + * @brief Unregister trace task from trace. + * + * @param[in] xTaskHandle Pointer to initialized trace task. + * @param[in] uxPriority Priority. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTaskUnregister(TraceTaskHandle_t xTaskHandle, TraceUnsignedBaseType_t uxPriority); + +/** + * @brief Sets trace task name. + * + * @param[in] pvTask Task. + * @param[in] szName Name. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTaskSetName xTraceObjectSetName + +/** + * @brief Sets trace task priority. + * + * @param[in] xTaskHandle Pointer to initialized trace task. + * @param[in] uxPriority Priority. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTaskSetPriority(TraceTaskHandle_t xTaskHandle, TraceUnsignedBaseType_t uxPriority); + +/** + * @brief Registers trace task without trace task handle. + * + * @param[in] pvTask Task. + * @param[in] szName Name. + * @param[in] uxPriority Priority. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTaskRegisterWithoutHandle(pvTask, szName, uxPriority) ((((pvTask) != 0) && (xTraceObjectRegisterWithoutHandle(PSF_EVENT_TASK_CREATE, pvTask, szName, uxPriority) == TRC_SUCCESS)) ? (xTraceStackMonitorAdd(pvTask), TRC_SUCCESS) : TRC_FAIL) + +/** + * @brief Unregisters trace task without trace task handle. + * + * @param[in] pvTask Task. + * @param[in] uxPriority Priority. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTaskUnregisterWithoutHandle(pvTask, uxPriority) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(xTraceStackMonitorRemove(pvTask), xTraceObjectUnregisterWithoutHandle(PSF_EVENT_TASK_DELETE, pvTask, uxPriority)) + +/** + * @brief Sets trace task name without trace task handle. + * + * @param[in] pvTask Task. + * @param[in] szName Name. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTaskSetNameWithoutHandle xTraceObjectSetNameWithoutHandle + +/** + * @brief Sets trace task priority without trace task handle. + * + * @param[in] pvTask Task. + * @param[in] uxPriority Priority. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTaskSetPriorityWithoutHandle(void* pvTask, TraceUnsignedBaseType_t uxPriority); + +/** + * @brief Registers trace task switch event. + * + * @param[in] pvTask Task. + * @param[in] uxPriority Priority. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTaskSwitch(void* pvTask, TraceUnsignedBaseType_t uxPriority); + +#if (TRC_CFG_INCLUDE_READY_EVENTS == 1) +/** + * @brief Registers trace task ready event. + * + * @param[in] pvTask Task. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTaskReady(void* pvTask); +#else +#define xTraceTaskReady(p) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2((void)p, TRC_SUCCESS) +#endif + +/** + * @brief Sets current trace task. + * + * @param[in] pvTask Task. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTaskSetCurrent(pvTask) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(pxTraceTaskInfo->coreTasks[TRC_CFG_GET_CURRENT_CORE()] = (pvTask), TRC_SUCCESS) + +/** + * @brief Gets current trace task. + * + * @param[out] ppvTask Task. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTaskGetCurrent(ppvTask) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(ppvTask) = pxTraceTaskInfo->coreTasks[TRC_CFG_GET_CURRENT_CORE()], TRC_SUCCESS) + +/** + * @brief Registers trace task instance finished event. + * + * This routine creates a trace event that ends the current task instance at + * this very instant. This makes the viewer split the current fragment at + * this point and begin a new actor instance, even if no task-switch has + * occurred + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTaskInstanceFinishedNow(void); + +/** + * @brief Marks the current trace 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. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTaskInstanceFinishedNext(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_TASK_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTimestamp.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTimestamp.h new file mode 100644 index 0000000000..481d135d8b --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTimestamp.h @@ -0,0 +1,253 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +/** + * @file + * + * @brief Public trace timestamp APIs. + */ + +#ifndef TRC_TIMESTAMP_H +#define TRC_TIMESTAMP_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup trace_timestamp_apis Trace Timestamp APIs + * @ingroup trace_recorder_apis + * @{ + */ + +/** + * @brief Trace Timestamp Structure + */ +typedef struct TraceTimestamp +{ + uint32_t type; /**< Timer type (direction) */ + TraceUnsignedBaseType_t frequency; /**< Timer Frequency */ + uint32_t period; /**< Timer Period */ + uint32_t wraparounds; /**< Nr of timer wraparounds */ + uint32_t osTickHz; /**< RTOS tick frequency */ + uint32_t latestTimestamp; /**< Latest timestamp */ + uint32_t osTickCount; /**< RTOS tick count */ +} TraceTimestamp_t; + +extern TraceTimestamp_t* pxTraceTimestamp; + +#define TRC_TIMESTAMP_RECORD_SIZE (sizeof(TraceTimestamp_t)) + +/** + * @internal Trace Timestamp Buffer Structure + */ +typedef struct TraceTimestampBuffer +{ + uint32_t buffer[(TRC_TIMESTAMP_RECORD_SIZE) / sizeof(uint32_t)]; +} TraceTimestampBuffer_t; + +/** + * @internal Initialize trace timestamp system. + * + * @param[in] pxBuffer Pointer to memory that will be used by the + * trace timestamp system. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTimestampInitialize(TraceTimestampBuffer_t *pxBuffer); + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +/** + * @brief Gets current trace timestamp. + * + * @param[out] puiTimestamp Timestamp. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTimestampGet(uint32_t* puiTimestamp); + +/** + * @brief Gets trace timestamp wraparounds. + * + * @param[out] puiTimerWraparounds Timer wraparounds. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTimestampGetWraparounds(uint32_t* puiTimerWraparounds); + +/** + * @brief Sets trace timestamp frequency. + * + * @param[in] uxFrequency Frequency. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTimestampSetFrequency(TraceUnsignedBaseType_t uxFrequency); + +/** + * @brief Gets trace timestamp frequency. + * + * @param[out] puxFrequency Frequency. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTimestampGetFrequency(TraceUnsignedBaseType_t* puxFrequency); + +/** + * @brief Sets trace timestamp period. + * + * @param[in] uiPeriod Period. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTimestampSetPeriod(uint32_t uiPeriod); + +/** + * @brief Gets trace timestamp period. + * + * @param[out] puiPeriod Period. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTimestampGetPeriod(uint32_t* puiPeriod); + +/** + * @brief Sets trace timestamp OS tick count. + * + * @param[in] uiOsTickCount OS tick count. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTimestampSetOsTickCount(uint32_t uiOsTickCount); + +/** + * @brief Gets trace timestamp OS tick count. + * + * @param[in] puiOsTickCount + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceTimestampGetOsTickCount(uint32_t *puiOsTickCount); + +#else /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/** + * @brief Gets current trace timestamp. + * + * @param[out] puiTimestamp Timestamp. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#if ((TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_INCR) || (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR)) +#define xTraceTimestampGet(puiTimestamp) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4(*(puiTimestamp) = TRC_HWTC_COUNT, (*(puiTimestamp) < pxTraceTimestamp->latestTimestamp) ? pxTraceTimestamp->wraparounds++ : 0, pxTraceTimestamp->latestTimestamp = *(puiTimestamp), TRC_SUCCESS) +#elif ((TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_DECR) || (TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR)) +#define xTraceTimestampGet(puiTimestamp) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4(*(puiTimestamp) = TRC_HWTC_COUNT, (*(puiTimestamp) > pxTraceTimestamp->latestTimestamp) ? pxTraceTimestamp->wraparounds++ : 0, pxTraceTimestamp->latestTimestamp = *(puiTimestamp), TRC_SUCCESS) +#elif ((TRC_HWTC_TYPE == TRC_OS_TIMER_INCR) || (TRC_HWTC_TYPE == TRC_OS_TIMER_DECR)) +#define xTraceTimestampGet(puiTimestamp) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4(*(puiTimestamp) = ((TRC_HWTC_COUNT) & 0x00FFFFFFU) + ((pxTraceTimestamp->osTickCount & 0x000000FFU) << 24), pxTraceTimestamp->wraparounds = pxTraceTimestamp->osTickCount, pxTraceTimestamp->latestTimestamp = *(puiTimestamp), TRC_SUCCESS) +#endif + +/** + * @brief Gets trace timestamp wraparounds. + * + * @param[out] puiTimerWraparounds Timer wraparounds. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTimestampGetWraparounds(puiTimerWraparounds) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(puiTimerWraparounds) = pxTraceTimestamp->wraparounds, TRC_SUCCESS) + +/** + * @brief Sets trace timestamp frequency. + * + * @param[in] uxFrequency Frequency. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTimestampSetFrequency(uxFrequency) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(pxTraceTimestamp->frequency = uxFrequency, TRC_SUCCESS) + +/** + * @brief Sets trace timestamp period. + * + * @param[in] uiPeriod Period. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTimestampSetPeriod(uiPeriod) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(pxTraceTimestamp->period = uiPeriod, TRC_SUCCESS) + +/** + * @brief Sets trace timestamp OS tick count. + * + * @param[in] uiOsTickCount OS tick count. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTimestampSetOsTickCount(uiOsTickCount) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(pxTraceTimestamp->osTickCount = uiOsTickCount, TRC_SUCCESS) + +/** + * @brief Gets trace timestamp frequency. + * + * @param[out] puxFrequency Frequency. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTimestampGetFrequency(puxFrequency) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(puxFrequency) = pxTraceTimestamp->frequency, TRC_SUCCESS) + +/** + * @brief Gets trace timestamp period. + * + * @param[out] puiPeriod Period. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTimestampGetPeriod(puiPeriod) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(puiPeriod) = pxTraceTimestamp->period, TRC_SUCCESS) + +/** + * @brief Gets trace timestamp OS tick count. + * + * @param[in] puiOsTickCount + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +#define xTraceTimestampGetOsTickCount(puiOsTickCount) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(puiOsTickCount) = pxTraceTimestamp->osTickCount, TRC_SUCCESS) + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /* TRC_TIMESTAMP_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTypes.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTypes.h new file mode 100644 index 0000000000..98aee91baf --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcTypes.h @@ -0,0 +1,69 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The common types. +*/ + +#ifndef TRC_TYPES_H +#define TRC_TYPES_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRC_BASE_TYPE +#define TRC_BASE_TYPE int32_t +#endif + +#ifndef TRC_UNSIGNED_BASE_TYPE +#define TRC_UNSIGNED_BASE_TYPE uint32_t +#endif + +typedef TRC_UNSIGNED_BASE_TYPE TraceUnsignedBaseType_t; + +typedef TRC_BASE_TYPE TraceBaseType_t; + +typedef TraceUnsignedBaseType_t traceResult; + +typedef TraceUnsignedBaseType_t TraceEventHandle_t; + +typedef TraceUnsignedBaseType_t TraceISRHandle_t; + +typedef TraceUnsignedBaseType_t TraceEntryHandle_t; + +typedef TraceUnsignedBaseType_t TraceTaskHandle_t; + +typedef TraceUnsignedBaseType_t TraceObjectHandle_t; + +typedef TraceUnsignedBaseType_t TraceExtensionHandle_t; + +typedef TraceUnsignedBaseType_t TraceHeapHandle_t; + +typedef TraceUnsignedBaseType_t TraceIntervalHandle_t; + +typedef TraceUnsignedBaseType_t TraceStateMachineHandle_t; + +typedef TraceUnsignedBaseType_t TraceStateMachineStateHandle_t; + +typedef TraceUnsignedBaseType_t TraceStringHandle_t; + +typedef TraceUnsignedBaseType_t TraceCounterHandle_t; + +typedef void (*TraceCounterCallback_t)(TraceCounterHandle_t xCounterHandle); + +/* DEPRECATED. Backwards compatibility */ +typedef TraceStringHandle_t traceString; + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_TYPES_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcUtility.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcUtility.h new file mode 100644 index 0000000000..225b6ccf3d --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcUtility.h @@ -0,0 +1,51 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The interface for trace utility functions. +*/ + +#ifndef TRC_UTILITY_H +#define TRC_UTILITY_H + +#ifndef TRC_MEMCPY +#define TRC_MEMCPY(dst, src, size) \ + { \ + uint32_t __i; \ + for (__i = 0; __i < size; __i++) { \ + ((uint8_t*)(dst))[__i] = ((uint8_t*)(src))[__i]; \ + } \ + } +#endif + +#define TRC_STRCAT(dst, dst_size, pDstLength, src) \ + { \ + TraceUnsignedBaseType_t uxTRC_STRCAT_INDEX = 0; \ + while (*(pDstLength) < (dst_size)) \ + { \ + dst[*(pDstLength)] = src[uxTRC_STRCAT_INDEX]; \ + if (dst[*(pDstLength)] == 0) \ + break; \ + (*(pDstLength))++; \ + uxTRC_STRCAT_INDEX++; \ + } \ + } + +#if (defined(TRC_CFG_USE_GCC_STATEMENT_EXPR) && TRC_CFG_USE_GCC_STATEMENT_EXPR == 1) || __GNUC__ + #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(e1) ({e1;}) + #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(e1, e2) ({e1; e2;}) + #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3(e1, e2, e3) ({e1; e2; e3;}) + #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4(e1, e2, e3, e4) ({e1; e2; e3; e4;}) + #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_5(e1, e2, e3, e4, e5) ({e1; e2; e3; e4; e5;}) +#else + #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(e1) (e1) + #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(e1, e2) (e1, e2) + #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_3(e1, e2, e3) (e1, e2, e3) + #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4(e1, e2, e3, e4) (e1, e2, e3, e4) + #define TRC_COMMA_EXPR_TO_STATEMENT_EXPR_5(e1, e2, e3, e4, e5) (e1, e2, e3, e4, e5) +#endif + +#endif /* TRC_UTILITY_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/LICENSE.md b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/LICENSE.md new file mode 100644 index 0000000000..29f81d812f --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/LICENSE.md @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/LICENSE.spdx b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/LICENSE.spdx new file mode 100644 index 0000000000..c46cd90f96 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/LICENSE.spdx @@ -0,0 +1,10 @@ +SPDXVersion: SPDX-2.2 +DataLicense: CC0-1.0 +Creator: Organization: Percepio AB () +PackageName: TraceRecorderSource +PackageOriginator: Percepio AB +PackageDownloadLocation: git+https://github.com/percepio/TraceRecorderSource.git +PackageLicenseDeclared: Apache-2.0 +PackageCopyrightText: Copyright 2021 Percepio AB +PackageSummary: Trace Recorder +PackageDescription: A generic software Trace Recorder that can generate trace events and transmit or store them. \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/README.md b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/README.md new file mode 100644 index 0000000000..eaea655958 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/README.md @@ -0,0 +1,5 @@ +Trace Recorder source code for use with Percepio's Tracealyzer. + +Read more at https://percepio.com/tracealyzer/ and https://percepio.com/gettingstarted. + +Repository at https://github.com/percepio/TraceRecorderSource diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcConfig.h index 9ccf57449f..3e10709b4b 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcConfig.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcConfig.h @@ -1,412 +1,320 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 - * TRC_FREERTOS_VERSION_10_4_1 If using FreeRTOS v10.4.1 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 */ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Main configuration parameters for the trace recorder library. + * More settings can be found in trcStreamingConfig.h and trcSnapshotConfig.h. + */ + +#ifndef TRC_CONFIG_H +#define TRC_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * 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." + +/** + * @def TRC_CFG_HARDWARE_PORT + * @brief 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 + +/** + * @def TRC_CFG_SCHEDULING_ONLY + * @brief 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 + +/** + * @def TRC_CFG_INCLUDE_MEMMANG_EVENTS + * @brief 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 + +/** + * @def TRC_CFG_INCLUDE_USER_EVENTS + * @brief 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 xTraceErrorGetLast + * or by putting breakpoints in xTraceError and xTraceWarning. + * + * Default value is 1. + */ +#define TRC_CFG_INCLUDE_USER_EVENTS 1 + +/** + * @def TRC_CFG_INCLUDE_ISR_TRACING + * @brief 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 + +/** + * @def TRC_CFG_INCLUDE_READY_EVENTS + * @brief 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 + +/** + * @def TRC_CFG_INCLUDE_OSTICK_EVENTS + * @brief 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 + +/** + * @def TRC_CFG_ENABLE_STACK_MONITOR + * @brief 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 + +/** + * @def TRC_CFG_STACK_MONITOR_MAX_TASKS + * @brief 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 + +/** + * @def TRC_CFG_STACK_MONITOR_MAX_REPORTS + * @brief 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 + +/** + * @def TRC_CFG_CTRL_TASK_PRIORITY + * @brief 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 + +/** + * @def TRC_CFG_CTRL_TASK_DELAY + * @brief 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 2 + +/** + * @def TRC_CFG_CTRL_TASK_STACK_SIZE + * @brief 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 1024 + +/** + * @def TRC_CFG_RECORDER_BUFFER_ALLOCATION + * @brief 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 + +/** + * @def TRC_CFG_MAX_ISR_NESTING + * @brief 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 + +/** + * @def TRC_CFG_ISR_TAILCHAINING_THRESHOLD + * @brief 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 + +/** + * @def TRC_CFG_RECORDER_DATA_INIT + * @brief Macro which states wether the recorder data should have an initial value. + * + * In very specific cases where traced objects are created before main(), + * the recorder will need to be started even before that. In these cases, + * the recorder data would be initialized by vTraceEnable(TRC_INIT) but could + * then later be overwritten by the initialization value. + * If this is an issue for you, set TRC_CFG_RECORDER_DATA_INIT to 0. + * The following code can then be used before any traced objects are created: + * + * extern uint32_t RecorderEnabled; + * RecorderEnabled = 0; + * xTraceInitialize(); + * + * After the clocks are properly initialized, use vTraceEnable(...) to start + * the tracing. + * + * Default value is 1. + */ +#define TRC_CFG_RECORDER_DATA_INIT 1 + +/** + * @def TRC_CFG_RECORDER_DATA_ATTRIBUTE + * @brief When setting TRC_CFG_RECORDER_DATA_INIT to 0, you might also need to make + * sure certain recorder data is placed in a specific RAM section to avoid being + * zeroed out after initialization. Define TRC_CFG_RECORDER_DATA_ATTRIBUTE as + * that attribute. + * + * Example: + * #define TRC_CFG_RECORDER_DATA_ATTRIBUTE __attribute__((section(".bss.trace_recorder_data"))) + * + * Default value is empty. + */ +#define TRC_CFG_RECORDER_DATA_ATTRIBUTE + +/** + * @def TRC_CFG_USE_TRACE_ASSERT + * @brief Enable or disable debug asserts. Information regarding any assert that is + * triggered will be in trcAssert.c. + */ +#define TRC_CFG_USE_TRACE_ASSERT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* _TRC_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcKernelPortConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcKernelPortConfig.h new file mode 100644 index 0000000000..08443bf249 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcKernelPortConfig.h @@ -0,0 +1,116 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Configuration parameters for the kernel port. + * More settings can be found in trcKernelPortStreamingConfig.h and + * trcKernelPortSnapshotConfig.h. + */ + +#ifndef TRC_KERNEL_PORT_CONFIG_H +#define TRC_KERNEL_PORT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def TRC_CFG_RECORDER_MODE + * @brief 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_STREAMING + +/** + * @def TRC_CFG_FREERTOS_VERSION + * @brief 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 + * TRC_FREERTOS_VERSION_10_4_1 If using FreeRTOS v10.4.1 or later + */ +#define TRC_CFG_FREERTOS_VERSION TRC_FREERTOS_VERSION_10_4_1 + +/** + * @def TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_TIMER_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND + * @brief 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 */ + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_KERNEL_PORT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcKernelPortSnapshotConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcKernelPortSnapshotConfig.h new file mode 100644 index 0000000000..9b1b1f4118 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcKernelPortSnapshotConfig.h @@ -0,0 +1,69 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Kernel port configuration parameters for snapshot mode. + */ + +#ifndef TRC_KERNEL_PORT_SNAPSHOT_CONFIG_H +#define TRC_KERNEL_PORT_SNAPSHOT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def TRC_CFG_NTASK, TRC_CFG_NISR, TRC_CFG_NQUEUE, TRC_CFG_NSEMAPHORE... + * @brief 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 + +/** + * @def TRC_CFG_NAME_LEN_TASK, TRC_CFG_NAME_LEN_QUEUE, ... + * @brief 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 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_KERNEL_PORT_SNAPSHOT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcKernelPortStreamingConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcKernelPortStreamingConfig.h new file mode 100644 index 0000000000..4cbc5bfb87 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcKernelPortStreamingConfig.h @@ -0,0 +1,24 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Kernel port configuration parameters for streaming mode. + */ + +#ifndef TRC_KERNEL_PORT_STREAMING_CONFIG_H +#define TRC_KERNEL_PORT_STREAMING_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Nothing yet */ + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_KERNEL_PORT_STREAMING_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 f585bcba87..888532ded2 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcSnapshotConfig.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcSnapshotConfig.h @@ -1,377 +1,245 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Configuration parameters for trace recorder library in snapshot mode. + * Read more at http://percepio.com/2016/10/05/rtos-tracing/ + */ + +#ifndef TRC_SNAPSHOT_CONFIG_H +#define TRC_SNAPSHOT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def TRC_CFG_SNAPSHOT_MODE + * @brief 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 + +/** + * @def TRC_CFG_EVENT_BUFFER_SIZE + * @brief 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 + +/** + * @def TRC_CFG_INCLUDE_FLOAT_SUPPORT + * @brief 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 + +/** + * @def TRC_CFG_SYMBOL_TABLE_SIZE + * @brief 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 + +/****************************************************************************** + *** 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. + *****************************************************************************/ + +/** + * @def TRC_CFG_HEAP_SIZE_BELOW_16M + * @brief 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 + +/** + * @def TRC_CFG_USE_IMPLICIT_IFE_RULES + * @brief 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 xTraceTaskInstanceFinishedNow and xTraceTaskInstanceFinishedNext. + * + * 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 xTraceTaskInstanceFinishedNow/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 xTraceTaskInstanceFinishedNow or + * xTraceTaskInstanceFinishedNext 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. + */ +#define TRC_CFG_USE_IMPLICIT_IFE_RULES 1 + +/** + * @def TRC_CFG_USE_16BIT_OBJECT_HANDLES + * @brief 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 + +/** + * @def TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER + * @brief 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: + * TraceStringHandle_t chn1; + * TraceStringHandle_t fmt1; + * xTraceStringRegister("Channel 1", &chn1); + * xTraceStringRegister("Event!", &fmt1); + * traceUBChannel UBCh1 = xTraceRegisterUBChannel(chn1, fmt1); + * + * TraceStringHandle_t chn2; + * TraceStringHandle_t fmt2; + * xTraceStringRegister("Channel 2", &chn2); + * xTraceStringRegister("X: %d, Y: %d", &fmt2); + * 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 xTracePrintF. + * 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") + * xTracePrintF(chn2, "%Z: %d", value1); + * + * // Finds the existing UB channel + * xTracePrintF(chn2, "%Z: %d", value2); + */ +#define TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER 0 + +/** + * @def TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE + * @brief 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 + +/** + * @def TRC_CFG_UB_CHANNELS + * @brief 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 + +#ifdef __cplusplus +} +#endif + +#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 641244995a..3e0cc3c7ee 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcStreamingConfig.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config/trcStreamingConfig.h @@ -1,144 +1,51 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 */ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Configuration parameters for the trace recorder library in streaming mode. + * Read more at http://percepio.com/2016/10/05/rtos-tracing/ + */ + +#ifndef TRC_STREAMING_CONFIG_H +#define TRC_STREAMING_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def TRC_CFG_ENTRY_SLOTS + * @brief The maximum number of objects and symbols that can be stored. This includes: + * - Task names + * - Named ISRs (vTraceSetISRProperties) + * - Named kernel objects (vTraceStoreKernelObjectName) + * - User event channels (xTraceStringRegister) + * + * 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_ENTRY_SLOTS 50 + +/** + * @def TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH + * @brief The maximum length of symbol names, including: + * - Task names + * - Named ISRs (vTraceSetISRProperties) + * - Named kernel objects (vTraceStoreKernelObjectName) + * - User event channel names (xTraceStringRegister) + * + * 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_ENTRY_SYMBOL_MAX_LENGTH 32 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAMING_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/extras/TraceRecorderInit/TraceRecorderInit.cpp b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/extras/TraceRecorderInit/TraceRecorderInit.cpp new file mode 100644 index 0000000000..148ffc4b94 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/extras/TraceRecorderInit/TraceRecorderInit.cpp @@ -0,0 +1,55 @@ +/* + * Percepio Trace Recorder Initialization v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * This file should only be included in a project if there is a need to + * initialize the Trace Recorder before main() has been called. + * An example of this scenario is if you have a global object instance that has + * a constructor that creates an object that should be traced. + * This file will make it easier to initiate the recorder correctly. + * + * Usage: + * Add a call to TraceRecorderInit::Initialize() wherever a traced object is + * created before the Trace Recorder is normally initialized. This will ensure + * the Trace Recorder is initialized only once. + * + * Set TRC_CFG_RECORDER_DATA_PTR_INIT to 0 in trcSnapshotConfig.h to ensure + * RecorderInitialized isn't initialized to 0 after the recorder has been + * already initialized. + * + * Finally, call vTraceEnable(TRC_START) after hardware is initialized to + * start gathering trace events. + */ + +#include +#include + +extern "C" uint32_t RecorderInitialized; + +/* Public */ +bool TraceRecorderInit::Initialize() +{ + /* Lazy initialization, and constructor is only run once ensuring that we only initialize the recorder once */ + static TraceRecorderInit instance; + + return instance.IsInitialized(); +} + +/* Private */ +TraceRecorderInit::TraceRecorderInit() +{ + RecorderInitialized = 0; + xTraceInitialize(); +} + +TraceRecorderInit::~TraceRecorderInit() +{ +} + +bool TraceRecorderInit::IsInitialized() +{ + return RecorderInitialized != 0; +} diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/extras/TraceRecorderInit/include/TraceRecorderInit.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/extras/TraceRecorderInit/include/TraceRecorderInit.h new file mode 100644 index 0000000000..18c6efd4f5 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/extras/TraceRecorderInit/include/TraceRecorderInit.h @@ -0,0 +1,38 @@ +/* + * Percepio Trace Recorder Initialization v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * This file should only be included in a project if there is a need to + * initialize the Trace Recorder before main() has been called. + * An example of this scenario is if you have a global object instance that has + * a constructor that creates an object that should be traced. + * This file will make it easier to initiate the recorder correctly. + * + * Usage: + * Add a call to TraceRecorderInit::Initialize() wherever a traced object is + * created before the Trace Recorder is normally initialized. This will ensure + * the Trace Recorder is initialized only once. + * + * Set TRC_CFG_RECORDER_DATA_PTR_INIT to 0 in trcSnapshotConfig.h to ensure + * RecorderInitialized isn't initialized to 0 after the recorder has been + * already initialized. + * + * Finally, call vTraceEnable(TRC_START) after hardware is initialized to + * start gathering trace events. + */ + +#pragma once + +class TraceRecorderInit +{ +public: + static bool Initialize(); +private: + TraceRecorderInit(); + ~TraceRecorderInit(); + + bool IsInitialized(); +}; diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/extras/TraceRecorderInit/readme.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/extras/TraceRecorderInit/readme.txt new file mode 100644 index 0000000000..4a565b53fa --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/extras/TraceRecorderInit/readme.txt @@ -0,0 +1,30 @@ +Percepio Trace Recorder Initialization v4.6.0 +Copyright 2021 Percepio AB +www.percepio.com + +This folder contains files that should only be included in a project +if there is a need to initialize the Trace Recorder before main() +has been called. + +An example of this scenario is if you have a global object instance that has +a constructor that creates an object that should be traced. +TraceRecorderInit will make it easier to initiate the recorder correctly. + +Usage: +Add a call to TraceRecorderInit::Initialize() wherever a traced object +is created before the Trace Recorder is normally initialized, or simply +as early as absloutely possible. This will ensure the Trace Recorder is +initialized only once. + +Set TRC_CFG_RECORDER_DATA_INIT to 0 in trcConfig.h to ensure +recorder data isn't initialized cleared after the recorder has been +already initialized. + +It is possible that you also need to make sure certain recorder data isn't +cleared when RAM sections are initialized. Create a RAM section that isn't +cleared, then set the appropriate attribute in TRC_CFG_RECORDER_DATA_ATTRIBUTE. +This attribute will then be set for all necessary recorder data that should +not be cleared. + +After the hardware and clocks are properly initialized, use +vTraceEnable(TRC_START) to start the tracing. 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 index 8774f20f55..c59413e4c7 100644 --- 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 @@ -1,22 +1,21 @@ -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 +Tracealyzer Stream Port for Amazon FreeRTOS TCP/WIFI +Percepio AB +www.percepio.com +---------------------------------------------------- + +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 +trcStreamPort.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 trcStreamPort.h. + +To use this stream port, make sure that include/trcStreamPort.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 +trcStreamPort.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/ 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/trcStreamPort.h similarity index 66% rename from FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/include/trcStreamingPort.h rename to FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/include/trcStreamPort.h index 545f06c7ab..ddf6f6d951 100644 --- 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/trcStreamPort.h @@ -1,161 +1,127 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 */ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 trcStreamPort.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/ + */ + +#ifndef TRC_STREAM_PORT_H +#define TRC_STREAM_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_STREAM_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/trcStreamPort.c similarity index 69% rename from FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/trcStreamingPort.c rename to FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/trcStreamPort.c index 36bfd83409..1f05fe3669 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/trcStreamingPort.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/AFR_WIFI_LOCAL/trcStreamPort.c @@ -1,191 +1,157 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 trcStreamPort.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/ + */ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +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 = 0; + +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 != 0) + *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/Keil-uVision-Tracealyzer-ITM-Exporter.ini b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/Keil-uVision-Tracealyzer-ITM-Exporter.ini index 5e2c8b99b4..45d015e129 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/Keil-uVision-Tracealyzer-ITM-Exporter.ini +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/Keil-uVision-Tracealyzer-ITM-Exporter.ini @@ -1,8 +1,11 @@ -/************************************************************ -* Percepio Tracealyzer - ITM Trace Exporter for Keil uVision -* Copyright (c) 2018, Percepio AB. -* https://percepio.com -************************************************************/ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + */ FUNC void tzSetEnable(int enable) { @@ -49,4 +52,4 @@ FUNC void tzSetEnable(int enable) tzSetEnable(1); DEFINE BUTTON "Start Recording", "tzSetEnable(1)"; -DEFINE BUTTON "Stop Recording", "tzSetEnable(0)"; \ No newline at end of file +DEFINE BUTTON "Stop Recording", "tzSetEnable(0)"; 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 be48c6df38..e98d14637b 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,32 +1,34 @@ -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 +Tracealyzer Stream Port for ARM Cortex-M ITM +Percepio AB +www.percepio.com +-------------------------------------------- + +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 +trcStreamPort.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 + +To setup Lauterbach TRACE32 for ITM tracing with a uTrace, +see Percepio Application Note PA-033, https://percepio.com/apn/PA033-TRACE32%20ITM%20Streaming.pdf + +Learn 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 + - Percepio Application Note PA-033 (Lauterbach), https://percepio.com/apn/PA033-TRACE32%20ITM%20Streaming.pdf + - 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 diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/Trace32-cmm-scripts.zip b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/Trace32-cmm-scripts.zip new file mode 100644 index 0000000000..611bbad29d Binary files /dev/null and b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/Trace32-cmm-scripts.zip differ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/config/trcStreamPortConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/config/trcStreamPortConfig.h new file mode 100644 index 0000000000..3218b896fd --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/config/trcStreamPortConfig.h @@ -0,0 +1,35 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The configuration for trace streaming ("stream ports"). + */ + +#ifndef TRC_STREAM_PORT_CONFIG_H +#define TRC_STREAM_PORT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * TRC_CFG_STREAM_PORT_ITM_PORT + * + * Valid 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_STREAM_PORT_ITM_PORT 1 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAM_PORT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/include/trcStreamPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/include/trcStreamPort.h new file mode 100644 index 0000000000..0ca76adf11 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/include/trcStreamPort.h @@ -0,0 +1,113 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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). + */ + +#ifndef TRC_STREAM_PORT_H +#define TRC_STREAM_PORT_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if (!defined(TRC_CFG_STREAM_PORT_ITM_PORT) || (TRC_CFG_STREAM_PORT_ITM_PORT) < 0) || ((TRC_CFG_STREAM_PORT_ITM_PORT) > 31) +#error "Invalid ITM port defined in trcStreamPortConfig.h." +#endif + +/* Important for the ITM port - no RAM buffer, direct writes. In most other ports this can be skipped (default is 1) */ +#define TRC_USE_INTERNAL_BUFFER 0 + +typedef struct TraceStreamPortBuffer +{ + uint8_t buffer[sizeof(TraceUnsignedBaseType_t)]; +} TraceStreamPortBuffer_t; + +traceResult prvTraceItmWrite(void* ptrData, uint32_t size, int32_t* ptrBytesWritten); +traceResult prvTraceItmRead(void* ptrData, uint32_t uiSize, int32_t* piBytesRead); + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer); + +#define xTraceStreamPortAllocate(uiSize, ppvData) ((void)uiSize, xTraceStaticBufferGet(ppvData)) + +#define xTraceStreamPortCommit(pvData, uiSize, piBytesCommitted) prvTraceItmWrite(pvData, uiSize, piBytesCommitted) + +#define xTraceStreamPortWriteData(pvData, uiSize, piBytesWritten) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4((void)pvData, (void)uiSize, (void)piBytesWritten, TRC_SUCCESS) + +#define xTraceStreamPortReadData(pvData, uiSize, piBytesRead) prvTraceItmRead(pvData, uiSize, piBytesRead) + +#define xTraceStreamPortOnEnable(uiStartOption) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2((void)(uiStartOption), TRC_SUCCESS) + +#define xTraceStreamPortOnDisable() TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(TRC_SUCCESS) + +#define xTraceStreamPortOnTraceBegin() TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(TRC_SUCCESS) + +#define xTraceStreamPortOnTraceEnd() TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(TRC_SUCCESS) + +#ifdef __cplusplus +} +#endif + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + +#endif /* TRC_STREAM_PORT_H */ 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 deleted file mode 100644 index 95fa38836f..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/include/trcStreamingPort.h +++ /dev/null @@ -1,137 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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/trcStreamPort.c similarity index 51% rename from FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/trcStreamingPort.c rename to FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/trcStreamPort.c index e014eba3d5..43c8787d96 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/trcStreamingPort.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/ARM_ITM/trcStreamPort.c @@ -1,169 +1,161 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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). + */ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +typedef struct TraceStreamPortFile +{ + uint8_t buffer[sizeof(TraceUnsignedBaseType_t)]; +} TraceStreamPortFile_t; + +static TraceStreamPortFile_t* pxStreamPortFile; + +/* This will be set by the debugger when there is data to be read */ +volatile int32_t tz_host_command_bytes_to_read = 0; + +/* This will be filled with data from the debugger */ +volatile char tz_host_command_data[32]; + +/* 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). */ + +#define itm_write_32(__data) \ +{\ + if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) && /* Trace enabled? */ \ + (ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled? */ \ + (ITM->TER & (1UL << (TRC_CFG_STREAM_PORT_ITM_PORT)))) /* ITM port enabled? */ \ + { \ + while (ITM->PORT[TRC_CFG_STREAM_PORT_ITM_PORT].u32 == 0) { /* Do nothing */ } /* Block until room in ITM FIFO - This stream port is always in "blocking mode", since intended for high-speed ITM! */ \ + ITM->PORT[TRC_CFG_STREAM_PORT_ITM_PORT].u32 = __data; /* Write the data */ \ + } \ +} + +/* This is assumed to execute from within the recorder, with interrupts disabled */ +traceResult prvTraceItmWrite(void* ptrData, uint32_t size, int32_t* ptrBytesWritten) +{ + uint32_t* ptr32 = (uint32_t*)ptrData; + + TRC_ASSERT(size % 4 == 0); + TRC_ASSERT(ptrBytesWritten != 0); + + *ptrBytesWritten = 0; + + while (*ptrBytesWritten < (int32_t)size) + { + itm_write_32(*ptr32); + ptr32++; + *ptrBytesWritten += 4; + } + + return TRC_SUCCESS; +} + +/* This reads "command" data from a RAM buffer, written by a host macro in the debugger */ +traceResult prvTraceItmRead(void* ptrData, uint32_t uiSize, int32_t* piBytesRead) +{ + int32_t i; + uint8_t* bytesBuffer = (uint8_t*)ptrData; + + TRC_ASSERT(piBytesRead != 0); + + /* Check if the debugger has updated tz_host_command_bytes_to_read */ + if (tz_host_command_bytes_to_read > 0) + { + if (tz_host_command_bytes_to_read != (int32_t)uiSize) + { + /* Sanity check. */ + return TRC_FAIL; + } + + *piBytesRead = (int32_t)tz_host_command_bytes_to_read; + + /* Read the bytes */ + for (i = 0; i < tz_host_command_bytes_to_read; i++) + { + bytesBuffer[i] = tz_host_command_data[i]; + } + + /* Reset */ + tz_host_command_bytes_to_read = 0; + } + + return TRC_SUCCESS; +} + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortFile_t); + + TRC_ASSERT(pxBuffer != 0); + + pxStreamPortFile = (TraceStreamPortFile_t*)pxBuffer; + + return TRC_SUCCESS; +} + +#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 c88517ef1d..f662085188 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,18 @@ -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 +Tracealyzer Stream Port for Files +Percepio AB +www.percepio.com +------------------------------------------------- + +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 +trcStreamPort.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/trcStreamPort.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 +trcStreamPort.h are included by mistake! + +See also http://percepio.com/2016/10/05/rtos-tracing. diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/config/trcStreamPortConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/config/trcStreamPortConfig.h new file mode 100644 index 0000000000..2f95a16522 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/config/trcStreamPortConfig.h @@ -0,0 +1,39 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The configuration for trace streaming ("stream ports"). + */ + +#ifndef TRC_STREAM_PORT_CONFIG_H +#define TRC_STREAM_PORT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Default file name */ +#ifndef TRC_CFG_STREAM_PORT_TRACE_FILE +#define TRC_CFG_STREAM_PORT_TRACE_FILE "trace.psf" +#endif + +/* This define will determine whether to use the internal buffer or not. +If file writing creates additional trace events (i.e. it uses semaphores or mutexes), +then the internal buffer must be enabled to avoid infinite recursion. */ +#define TRC_CFG_STREAM_PORT_USE_INTERNAL_BUFFER 0 + +/******************************************************************************* +* Configuration Macro: TRC_CFG_STREAM_PORT_BUFFER_SIZE +* +* Specifies the size of the internal buffer, if one is used. +******************************************************************************/ +#define TRC_CFG_STREAM_PORT_BUFFER_SIZE 10000 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAM_PORT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/include/trcStreamPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/include/trcStreamPort.h new file mode 100644 index 0000000000..3e4734774a --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/include/trcStreamPort.h @@ -0,0 +1,84 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The interface definitions for trace streaming ("stream ports"). + * This "stream port" sets up the recorder to stream the trace to file. + */ + +#ifndef TRC_STREAM_PORT_H +#define TRC_STREAM_PORT_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRC_USE_INTERNAL_BUFFER (TRC_CFG_STREAM_PORT_USE_INTERNAL_BUFFER) + +/* Default file name */ +#ifndef TRC_CFG_STREAM_PORT_TRACE_FILE +#define TRC_CFG_STREAM_PORT_TRACE_FILE "trace.psf" +#endif + +typedef struct TraceStreamPortFile +{ + FILE* pxFile; +#if (TRC_USE_INTERNAL_BUFFER) + uint8_t buffer[TRC_STREAM_PORT_BUFFER_SIZE]; +#endif +} TraceStreamPortFile_t; + +extern TraceStreamPortFile_t* pxStreamPortFile; + +#define TRC_STREAM_PORT_BUFFER_SIZE (sizeof(TraceStreamPortFile_t)) + +typedef struct TraceStreamPortBuffer +{ + uint8_t buffer[TRC_STREAM_PORT_BUFFER_SIZE]; +} TraceStreamPortBuffer_t; + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer); + +#define xTraceStreamPortAllocate(uiSize, ppvData) ((void)(uiSize), xTraceStaticBufferGet(ppvData)) + +#if (TRC_USE_INTERNAL_BUFFER == 1) +/* Push to internal buffer. It will call on xTraceStreamPortWriteData() periodically. */ +#define xTraceStreamPortCommit(pvData, uiSize, piBytesCommitted) xTraceInternalEventBufferPush(pvData, uiSize, piBytesCommitted) +#else +/* Write directly to file */ +#define xTraceStreamPortCommit(pvData, uiSize, piBytesCommitted) xTraceStreamPortWriteData(pvData, uiSize, piBytesCommitted) +#endif + +#define xTraceStreamPortWriteData(pvData, uiSize, piBytesWritten) (*(piBytesWritten) = fwrite(pvData, 1, uiSize, pxStreamPortFile->pxFile), TRC_SUCCESS) + +#define xTraceStreamPortReadData(pvData, uiSize, piBytesRead) ((void)(pvData), (void)(uiSize), (void)(piBytesRead), TRC_SUCCESS) + +#define xTraceStreamPortOnEnable(uiStartOption) ((void)(uiStartOption), TRC_SUCCESS) + +#define xTraceStreamPortOnDisable() (TRC_SUCCESS) + +traceResult xTraceStreamPortOnTraceBegin(void); + +traceResult xTraceStreamPortOnTraceEnd(void); + +#ifdef __cplusplus +} +#endif + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + +#endif /* TRC_STREAM_PORT_H */ 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 deleted file mode 100644 index 6977552c87..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/include/trcStreamingPort.h +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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/trcStreamPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamPort.c new file mode 100644 index 0000000000..1786026cd3 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamPort.c @@ -0,0 +1,82 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +TraceStreamPortFile_t* pxStreamPortFile; + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortFile_t); + + TRC_ASSERT(pxBuffer != 0); + + pxStreamPortFile = (TraceStreamPortFile_t*)pxBuffer; + pxStreamPortFile->pxFile = 0; + +#if (TRC_USE_INTERNAL_BUFFER == 1) + return xTraceInternalEventBufferInitialize(pxStreamPortFile->buffer, sizeof(pxStreamPortFile->buffer)); +#else + return TRC_SUCCESS; +#endif +} + +traceResult xTraceStreamPortOnTraceBegin(void) +{ + if (pxStreamPortFile == 0) + { + return TRC_FAIL; + } + + if (pxStreamPortFile->pxFile == 0) + { + errno_t err = fopen_s(&pxStreamPortFile->pxFile, TRC_CFG_STREAM_PORT_TRACE_FILE, "wb"); + if (err != 0) + { + printf("Could not open trace file, error code %d.\n", err); + + return TRC_FAIL; + } + else + { + printf("Trace file created.\n"); + } + } + + return TRC_SUCCESS; +} + +traceResult xTraceStreamPortOnTraceEnd(void) +{ + if (pxStreamPortFile == 0) + { + return TRC_FAIL; + } + + if (pxStreamPortFile->pxFile != 0) + { + fclose(pxStreamPortFile->pxFile); + pxStreamPortFile->pxFile = 0; + printf("Trace file closed.\n"); + } + + return TRC_SUCCESS; +} + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c deleted file mode 100644 index ccb95ff166..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 0dcd1591ef..5c35ed83e1 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,21 @@ -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 +Tracealyzer Stream Port for SEGGER J-Link +Percepio AB +www.percepio.com +----------------------------------------- + +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 +trcStreamPort.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/trcStreamPort.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 +trcStreamPort.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. diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/config/trcStreamPortConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/config/trcStreamPortConfig.h new file mode 100644 index 0000000000..29c7b9156c --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/config/trcStreamPortConfig.h @@ -0,0 +1,123 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The configuration for trace streaming ("stream ports"). + */ + +#ifndef TRC_STREAM_PORT_CONFIG_H +#define TRC_STREAM_PORT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* This define will determine whether to use the internal buffer or not. +If file writing creates additional trace events (i.e. it uses semaphores or mutexes), +then the internal buffer must be enabled to avoid infinite recursion. */ +#define TRC_CFG_STREAM_PORT_USE_INTERNAL_BUFFER 0 + +/** +* @def TRC_CFG_INTERNAL_BUFFER_SIZE +* +* @brief Configures the size of the internal buffer if used. +* is enabled. +*/ +#define TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_SIZE 5000 + +/** +* @def TRC_CFG_STREAM_PORT_RTT_UP_BUFFER_SIZE +* +* @brief 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_STREAM_PORT_RTT_UP_BUFFER_SIZE 5000 + +/** +* @def TRC_CFG_STREAM_PORT_RTT_DOWN_BUFFER_SIZE +* +* @brief 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_STREAM_PORT_RTT_DOWN_BUFFER_SIZE 32 + +/** +* @def TRC_CFG_STREAM_PORT_RTT_UP_BUFFER_INDEX +* +* @brief 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_STREAM_PORT_RTT_UP_BUFFER_INDEX 1 + +/** +* @def TRC_CFG_STREAM_PORT_RTT_DOWN_BUFFER_INDEX +* +* @brief 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_STREAM_PORT_RTT_DOWN_BUFFER_INDEX 1 + +/** +* @def TRC_CFG_STREAM_PORT_RTT_MODE +* +* @brief 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_STREAM_PORT_RTT_MODE SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL + +/** + * @def TRC_CFG_STREAM_PORT_RTT_NO_LOCK_WRITE + * + * @brief Sets if RTT should write without locking or not when writing + * RTT data. This should normally be disabled with an exception being + * Zephyr, where the SEGGER RTT locks aren't necessary and causes + * problems if enabled. + * + * Default: 0 + */ +#define TRC_CFG_STREAM_PORT_RTT_NO_LOCK_WRITE 0 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAM_PORT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/trcStreamPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/trcStreamPort.h new file mode 100644 index 0000000000..65075f9c40 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/trcStreamPort.h @@ -0,0 +1,143 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#ifndef TRC_STREAM_PORT_H +#define TRC_STREAM_PORT_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include +#include + +#define TRC_USE_INTERNAL_BUFFER (TRC_CFG_STREAM_PORT_USE_INTERNAL_BUFFER) + +/* Aligned */ +#define TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE ((((TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_SIZE) + sizeof(TraceUnsignedBaseType_t) - 1) / sizeof(TraceUnsignedBaseType_t)) * sizeof(TraceUnsignedBaseType_t)) + +/* Aligned */ +#define TRC_STREAM_PORT_RTT_UP_BUFFER_SIZE ((((TRC_CFG_STREAM_PORT_RTT_UP_BUFFER_SIZE) + sizeof(TraceUnsignedBaseType_t) - 1) / sizeof(TraceUnsignedBaseType_t)) * sizeof(TraceUnsignedBaseType_t)) + +/* Aligned */ +#define TRC_STREAM_PORT_RTT_DOWN_BUFFER_SIZE ((((TRC_CFG_STREAM_PORT_RTT_DOWN_BUFFER_SIZE) + sizeof(TraceUnsignedBaseType_t) - 1) / sizeof(TraceUnsignedBaseType_t)) * sizeof(TraceUnsignedBaseType_t)) + + +/** + * @brief A structure representing the trace stream port buffer. + */ +typedef struct TraceStreamPortBuffer +{ +#if (TRC_USE_INTERNAL_BUFFER == 1) + uint8_t bufferInternal[TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE]; +#endif + uint8_t bufferUp[TRC_STREAM_PORT_RTT_UP_BUFFER_SIZE]; + uint8_t bufferDown[TRC_STREAM_PORT_RTT_DOWN_BUFFER_SIZE]; +} TraceStreamPortBuffer_t; + +/** + * @internal Stream port initialize callback. + * + * This function is called by the recorder as part of its initialization phase. + * + * @param[in] pxBuffer Buffer + * + * @retval TRC_FAIL Initialization failed + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer); + +/** + * @brief Allocates data from the stream port. + * + * @param[in] uiSize Allocation size + * @param[out] ppvData Allocation data pointer + * + * @retval TRC_FAIL Allocate failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortAllocate(uiSize, ppvData) ((void)(uiSize), xTraceStaticBufferGet(ppvData)) + +/** + * @brief Commits data to the stream port, depending on the implementation/configuration of the + * stream port this data might be directly written to the stream port interface, buffered, or + * something else. + * + * @param[in] pvData Data to commit + * @param[in] uiSize Data to commit size + * @param[out] piBytesCommitted Bytes committed + * + * @retval TRC_FAIL Commit failed + * @retval TRC_SUCCESS Success + */ +#if (TRC_USE_INTERNAL_BUFFER == 1) +#define xTraceStreamPortCommit xTraceInternalEventBufferPush +#else +#define xTraceStreamPortCommit xTraceStreamPortWriteData +#endif + +/** + * @brief Writes data through the stream port interface. + * + * @param[in] pvData Data to write + * @param[in] uiSize Data to write size + * @param[out] piBytesWritten Bytes written + * + * @retval TRC_FAIL Write failed + * @retval TRC_SUCCESS Success + */ +#if (defined(TRC_CFG_STREAM_PORT_RTT_NO_LOCK_WRITE) && TRC_CFG_STREAM_PORT_RTT_NO_LOCK_WRITE == 1) +#define xTraceStreamPortWriteData(pvData, uiSize, piBytesWritten) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(piBytesWritten) = (int32_t)SEGGER_RTT_WriteNoLock((TRC_CFG_STREAM_PORT_RTT_UP_BUFFER_INDEX), (const char*)pvData, uiSize), TRC_SUCCESS) +#else +#define xTraceStreamPortWriteData(pvData, uiSize, piBytesWritten) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2(*(piBytesWritten) = (int32_t)SEGGER_RTT_Write((TRC_CFG_STREAM_PORT_RTT_UP_BUFFER_INDEX), (const char*)pvData, uiSize), TRC_SUCCESS) +#endif + +/** + * @brief Reads data through the stream port interface. + * + * @param[in] pvData Destination data buffer + * @param[in] uiSize Destination data buffer size + * @param[out] piBytesRead Bytes read + * + * @retval TRC_FAIL Read failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortReadData(pvData, uiSize, piBytesRead) ((SEGGER_RTT_HASDATA(TRC_CFG_STREAM_PORT_RTT_DOWN_BUFFER_INDEX)) ? (*(piBytesRead) = (int32_t)SEGGER_RTT_Read((TRC_CFG_STREAM_PORT_RTT_DOWN_BUFFER_INDEX), (char*)(pvData), uiSize), TRC_SUCCESS) : TRC_SUCCESS) + +traceResult xTraceStreamPortOnEnable(uint32_t uiStartOption); + +#define xTraceStreamPortOnDisable() (void)(TRC_SUCCESS) + +#define xTraceStreamPortOnTraceBegin() (void)(TRC_SUCCESS) + +#define xTraceStreamPortOnTraceEnd() (void)(TRC_SUCCESS) + +#ifdef __cplusplus +} +#endif + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + +#endif /* TRC_STREAM_PORT_H */ 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 deleted file mode 100644 index ca879ca644..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/include/trcStreamingPort.h +++ /dev/null @@ -1,196 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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/trcStreamPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/trcStreamPort.c new file mode 100644 index 0000000000..4bd7837a06 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/trcStreamPort.c @@ -0,0 +1,64 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +typedef struct TraceStreamPortRTT { +#if (TRC_USE_INTERNAL_BUFFER == 1) + uint8_t bufferInternal[TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE]; +#endif + uint8_t bufferUp[TRC_STREAM_PORT_RTT_UP_BUFFER_SIZE]; + uint8_t bufferDown[TRC_STREAM_PORT_RTT_DOWN_BUFFER_SIZE]; +} TraceStreamPortRTT_t; + +static TraceStreamPortRTT_t* pxStreamPortRTT; + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortRTT_t); + + if (pxBuffer == 0) + { + return TRC_FAIL; + } + + pxStreamPortRTT = (TraceStreamPortRTT_t*)pxBuffer; + +#if (TRC_USE_INTERNAL_BUFFER == 1) + return xTraceInternalEventBufferInitialize(pxStreamPortRTT->bufferInternal, sizeof(pxStreamPortRTT->bufferInternal)); +#else + return TRC_SUCCESS; +#endif +} + +traceResult xTraceStreamPortOnEnable(uint32_t uiStartOption) +{ + (void)uiStartOption; + + /* Configure the RTT buffers */ + SEGGER_RTT_ConfigUpBuffer(TRC_CFG_STREAM_PORT_RTT_UP_BUFFER_INDEX, "TzData", pxStreamPortRTT->bufferUp, sizeof(pxStreamPortRTT->bufferUp), TRC_CFG_STREAM_PORT_RTT_MODE); + SEGGER_RTT_ConfigDownBuffer(TRC_CFG_STREAM_PORT_RTT_DOWN_BUFFER_INDEX, "TzCtrl", pxStreamPortRTT->bufferDown, sizeof(pxStreamPortRTT->bufferDown), TRC_CFG_STREAM_PORT_RTT_MODE); + + return TRC_SUCCESS; +} + +#endif + +#endif 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 deleted file mode 100644 index 759987b677..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/Jlink_RTT/trcStreamingPort.c +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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/RingBuffer/Readme-Streamport.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/RingBuffer/Readme-Streamport.txt new file mode 100644 index 0000000000..8434b90e16 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/RingBuffer/Readme-Streamport.txt @@ -0,0 +1,19 @@ +Tracealyzer Stream Port for Ring Buffer +------------------------------------------------- + +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 +trcStreamPort.h, found in the "include" directory. + +This particular stream port is for streaming to a ring buffer. + +To use this stream port, make sure that include/trcStreamPort.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 +trcStreamPort.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/RingBuffer/config/trcStreamPortConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/RingBuffer/config/trcStreamPortConfig.h new file mode 100644 index 0000000000..0b970b724c --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/RingBuffer/config/trcStreamPortConfig.h @@ -0,0 +1,60 @@ +/* +* Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* + * The configuration for trace streaming ("stream ports"). +*/ + +#ifndef TRC_STREAM_PORT_CONFIG_H +#define TRC_STREAM_PORT_CONFIG_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Type flags */ +#define TRC_STREAM_PORT_RINGBUFFER_MODE_STOP_WHEN_FULL (0U) +#define TRC_STREAM_PORT_RINGBUFFER_MODE_OVERWRITE_WHEN_FULL (1U) + +/** + * @def TRC_CFG_STREAM_PORT_BUFFER_SIZE + * + * @brief Defines the size of the ring buffer use for storing trace events. + */ +#define TRC_CFG_STREAM_PORT_BUFFER_SIZE 10000 + +/** + * @def TRC_CFG_STREAM_PORT_BUFFER_MODE + * + * @brief Configures the behavior of the ring buffer when full. + * + * With TRC_CFG_STREAM_PORT_MODE set to TRC_STREAM_PORT_RINGBUFFER_MODE_OVERWRITE_WHEN_FULL, 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_STREAM_PORT_MODE is TRC_STREAM_PORT_RINGBUFFER_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_STREAM_PORT_RINGBUFFER_MODE TRC_STREAM_PORT_RINGBUFFER_MODE_OVERWRITE_WHEN_FULL + +#ifdef __cplusplus +} +#endif + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + +#endif /* TRC_STREAM_PORT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/RingBuffer/include/trcStreamPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/RingBuffer/include/trcStreamPort.h new file mode 100644 index 0000000000..afa8ff5243 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/RingBuffer/include/trcStreamPort.h @@ -0,0 +1,201 @@ +/* +* Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The interface definitions for trace streaming ("stream ports"). +* This "stream port" sets up the recorder to stream to a Ring Buffer. +*/ + +#ifndef TRC_STREAM_PORT_H +#define TRC_STREAM_PORT_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def TRC_EXTERNAL_BUFFERS + * + * @brief This Stream Port houses the EntryTable and Timestamp buffers + */ +#define TRC_EXTERNAL_BUFFERS 1 + +/** + * @def TRC_SEND_NAME_ONLY_ON_DELETE + * + * @brief This Stream Port requires additional information to be sent when objects are deleted + */ +#define TRC_SEND_NAME_ONLY_ON_DELETE 1 + +/** + * @def TRC_USE_INTERNAL_BUFFER + * + * @brief This Stream Port uses the Multi Core Buffer directly. + */ + +#define TRC_USE_INTERNAL_BUFFER 0 + +#define TRC_STREAM_PORT_BUFFER_SIZE ((((TRC_CFG_STREAM_PORT_BUFFER_SIZE) + sizeof(uint32_t) - 1) / sizeof(uint32_t)) * sizeof(uint32_t)) + +/** +* @brief +*/ +typedef struct TraceMultiCoreBuffer +{ + uint32_t uiSize; + uint8_t uiBuffer[TRC_STREAM_PORT_BUFFER_SIZE]; +} TraceMultiCoreBuffer_t; + +/** + * @brief + */ +typedef struct TraceRingBuffer +{ + volatile uint8_t START_MARKERS[12]; + TraceHeaderBuffer_t xHeaderBuffer; + TraceTimestampBuffer_t xTimestampInfo; + TraceEntryTableBuffer_t xEntryTableBuffer; + TraceMultiCoreBuffer_t xEventBuffer; + volatile uint8_t END_MARKERS[12]; +} TraceRingBuffer_t; + +/** + * @brief + */ +typedef struct TraceStreamPortData +{ + TraceMultiCoreEventBuffer_t xMultiCoreEventBuffer; + TraceRingBuffer_t xRingBuffer; +} TraceStreamPortData_t; + +extern TraceStreamPortData_t* pxStreamPortData; + +/** +* @def TRC_STREAM_PORT_BUFFER_SIZE +* @brief The buffer size, aligned to base type. +*/ +#define TRC_STREAM_PORT_DATA_BUFFER_SIZE (sizeof(TraceStreamPortData_t)) + +/** + * @brief A structure representing the trace stream port buffer. + */ +typedef struct TraceStreamPortBuffer +{ + uint8_t buffer[(TRC_STREAM_PORT_DATA_BUFFER_SIZE)]; +} TraceStreamPortBuffer_t; + +/** + * @internal Stream port initialize callback. + * + * This function is called by the recorder as part of its initialization phase. + * + * @param[in] pxBuffer Buffer + * + * @retval TRC_FAIL Initialization failed + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer); + +/** + * @brief Allocates data from the stream port. + * + * @param[in] uiSize Allocation size + * @param[out] ppvData Allocation data pointer + * + * @retval TRC_FAIL Allocate failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortAllocate(uiSize, ppvData) ((void)uiSize, xTraceStaticBufferGet(ppvData)) + +/** + * @brief Commits data to the stream port, depending on the implementation/configuration of the + * stream port this data might be directly written to the stream port interface, buffered, or + * something else. + * + * @param[in] pvData Data to commit + * @param[in] uiSize Data to commit size + * @param[out] piBytesCommitted Bytes commited + * + * @retval TRC_FAIL Commit failed + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortCommit(void* pvData, uint32_t uiSize, int32_t* piBytesCommitted); + +/** + * @brief Writes data through the stream port interface. + * + * @param[in] pvData Data to write + * @param[in] uiSize Data to write size + * @param[out] piBytesWritten Bytes written + * + * @retval TRC_FAIL Write failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortWriteData(pvData, uiSize, piBytesWritten) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4((void)pvData, (void)uiSize, (void)piBytesWritten, TRC_SUCCESS) + +/** + * @brief Reads data through the stream port interface. + * + * @param[in] pvData Destination data buffer + * @param[in] uiSize Destination data buffer size + * @param[out] piBytesRead Bytes read + * + * @retval TRC_FAIL Read failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortReadData(pvData, uiSize, piBytesRead) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_4((void)pvData, (void)uiSize, (void)piBytesRead, TRC_SUCCESS) + +/** + * @brief Callback for when recorder is enabled + * + * @param[in] uiStartOption Start option used when enabling trace recorder + * + * @retval TRC_FAIL Read failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortOnEnable(uiStartOption) TRC_COMMA_EXPR_TO_STATEMENT_EXPR_2((void)(uiStartOption), TRC_SUCCESS) + +/** + * @brief Callback for when recorder is disabled + * + * @retval TRC_FAIL Read failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortOnDisable() TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(TRC_SUCCESS) + +/** + * @brief Callback for when tracing begins + * + * @retval TRC_FAIL Read failed + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortOnTraceBegin(); + +/** + * @brief Callback for when tracing ends + * + * @retval TRC_FAIL Read failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortOnTraceEnd() TRC_COMMA_EXPR_TO_STATEMENT_EXPR_1(TRC_SUCCESS) + +#ifdef __cplusplus +} +#endif + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + +#endif /* TRC_STREAM_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/RingBuffer/trcStreamPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/RingBuffer/trcStreamPort.c new file mode 100644 index 0000000000..5c0484d7b7 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/RingBuffer/trcStreamPort.c @@ -0,0 +1,130 @@ +/* +* Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* Supporting functions for trace streaming, used by the "stream ports" +* for reading and writing data to the interface. +* This "stream port" sets up the recorder to stream to a Ring Buffer. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +/* Backwards compatibility with plugins */ +typedef TraceRingBuffer_t RecorderData; +RecorderData* RecorderDataPtr = 0; + +TraceStreamPortData_t* pxStreamPortData; + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer) +{ + TraceRingBuffer_t* pxRingBuffer; + + TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortData_t); + + if (pxBuffer == 0) + { + return TRC_FAIL; + } + + pxStreamPortData = (TraceStreamPortData_t*)pxBuffer; + RecorderDataPtr = pxRingBuffer = &pxStreamPortData->xRingBuffer; + + pxRingBuffer->xEventBuffer.uiSize = sizeof(pxRingBuffer->xEventBuffer.uiBuffer); + +#if (TRC_CFG_STREAM_PORT_RINGBUFFER_MODE == TRC_STREAM_PORT_RINGBUFFER_MODE_OVERWRITE_WHEN_FULL) + if (xTraceMultiCoreEventBufferInitialize(&pxStreamPortData->xMultiCoreEventBuffer, TRC_EVENT_BUFFER_OPTION_OVERWRITE, pxRingBuffer->xEventBuffer.uiBuffer, sizeof(pxRingBuffer->xEventBuffer.uiBuffer)) == TRC_FAIL) + { + return TRC_FAIL; + } +#else + if (xTraceMultiCoreEventBufferInitialize(&pxStreamPortData->xMultiCoreEventBuffer, TRC_EVENT_BUFFER_OPTION_SKIP, pxRingBuffer->xEventBuffer.uiBuffer, sizeof(pxRingBuffer->xEventBuffer.uiBuffer)) == TRC_FAIL) + { + return TRC_FAIL; + } +#endif + + if (xTraceHeaderInitialize(&pxRingBuffer->xHeaderBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceEntryTableInitialize(&pxRingBuffer->xEntryTableBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceTimestampInitialize(&pxRingBuffer->xTimestampInfo) == TRC_FAIL) + { + return TRC_FAIL; + } + + pxRingBuffer->END_MARKERS[0] = 0x0A; + pxRingBuffer->END_MARKERS[1] = 0x0B; + pxRingBuffer->END_MARKERS[2] = 0x0C; + pxRingBuffer->END_MARKERS[3] = 0x0D; + + pxRingBuffer->END_MARKERS[4] = 0x71; + pxRingBuffer->END_MARKERS[5] = 0x72; + pxRingBuffer->END_MARKERS[6] = 0x73; + pxRingBuffer->END_MARKERS[7] = 0x74; + + pxRingBuffer->END_MARKERS[8] = 0xF1; + pxRingBuffer->END_MARKERS[9] = 0xF2; + pxRingBuffer->END_MARKERS[10] = 0xF3; + pxRingBuffer->END_MARKERS[11] = 0xF4; + + pxRingBuffer->START_MARKERS[0] = 0x05; + pxRingBuffer->START_MARKERS[1] = 0x06; + pxRingBuffer->START_MARKERS[2] = 0x07; + pxRingBuffer->START_MARKERS[3] = 0x08; + + pxRingBuffer->START_MARKERS[4] = 0x75; + pxRingBuffer->START_MARKERS[5] = 0x76; + pxRingBuffer->START_MARKERS[6] = 0x77; + pxRingBuffer->START_MARKERS[7] = 0x78; + + pxRingBuffer->START_MARKERS[8] = 0xF5; + pxRingBuffer->START_MARKERS[9] = 0xF6; + pxRingBuffer->START_MARKERS[10] = 0xF7; + pxRingBuffer->START_MARKERS[11] = 0xF8; + + return TRC_SUCCESS; +} + +traceResult xTraceStreamPortCommit(void* pvData, uint32_t uiSize, int32_t* piBytesCommitted) +{ + if (pvData == 0) + { + return TRC_FAIL; + } + + xTraceMultiCoreEventBufferPush(&pxStreamPortData->xMultiCoreEventBuffer, pvData, uiSize, piBytesCommitted); + +#if (TRC_CFG_STREAM_PORT_RINGBUFFER_MODE == TRC_STREAM_PORT_RINGBUFFER_MODE_STOP_WHEN_FULL) + /* If no bytes was written it means that the buffer is full and we should stop + * tracing. + */ + if (uiSize > 0 && *piBytesCommitted == 0) { + xTraceDisable(); + return TRC_FAIL; + } +#endif + + return TRC_SUCCESS; +} + +traceResult xTraceStreamPortOnTraceBegin() +{ + return xTraceMultiCoreEventBufferClear(&pxStreamPortData->xMultiCoreEventBuffer); +} + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/Readme-Streamport.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/Readme-Streamport.txt index 7a59e3a2ee..35986a3ac4 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/Readme-Streamport.txt +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/Readme-Streamport.txt @@ -1,94 +1,93 @@ -Tracealyzer Stream Port for STM32 USB CDC (Virtual COM Port) ------------------------------------------------------------- - -This directory contains a "stream port" for the Tracealyzer recorder library, -allowing for streaming the trace data over a USB connection. The stream port is defined by a set of macros in -trcStreamingPort.h, found in the "include" directory, that relies on functions in trcStreamingPort.c. - -This particular stream port targets STM32 devices using USB CDC (virtual COM port). -It was been tested with STM32F767 and STM32L475. - ---- Prerequisites --- - -- An STM32 device with a USB connector for application use. - -- Tracealyzer 4 with a license for FreeRTOS, SafeRTOS or Micrium µC/OS-III. - -- STM32CubeIDE or the stand-alone STM32CubeMX configuration tool. - ---- Instructions --- - -1. Follow the general instructions (Section 1) at https://percepio.com/gettingstarted-freertos/ -and verify that Snapshot mode works. The basic integration of the recorder library is the same. - -2. Open the Device Configuration Tool (STM32CubeMX), e.g. by double-clicking on the .ioc file in your STM32CubeIDE project. - -2.1. Under "Middleware", enable "USB_DEVICE" and... -- In "USB_DEVICE Mode and Configuration", set the "Class for FS IP" to "Communication Device Class (Virtual Com Port)". -- Under Configuration -> Parameter Settings, set the TX and RX buffer sizes to a small value (e.g. 1). -The default TX and RX buffers are not used by the trace recorder library, so this avoids wasting RAM. - -2.2. Under "Connectivity", open "USB_OTG_FS" and... -- In "USB_OTG_FS Mode and Configuration", make sure "Mode" is set to "Device_Only" -- Under "Configuration", open "NVIC Settings" and make sure "USB OTG FS global interrupt" is enabled. - -3. Open trcConfig.h and set TRC_CFG_RECORDER_MODE to TRC_RECORDER_MODE_STREAMING. - -4. Copy trcStreamingPort.c and include/trcStreamingPort.h into your project. - -5. Make sure you have "vTraceEnable(TRC_INIT);" in main.c (not TRC_START or so). -This should be placed after the HW setup but before making any RTOS calls. - -6. Plug in a USB cable to the connector labeled "USB OTG" or similar (i.e. for application use). - -7. Build the project and start it. Check that your computer finds a new USB device (there should be a notification). - -8. Check the number of the new COM port, that should have appeared. This is NOT "STLink Virtual COM port". - -9. Start Tracealyzer and open Recording Settings and select Target Connection: SerialPort. -You can also access these settings via File -> Settings -> PSF Streaming Settings. - -10. Enter the number of the COM port in the "Device" field. The settings (data -bits, data rate etc.) are irrelevant for USB serial connections and not used. - -11. While the target is running, select Record Streaming Trace in Tracealyzer. -You should now see a live display of the trace, while it is being received. -Make sure there are no warnings about "Dropped Events" (in that case, see Troubleshooting, below). - -Note that you can still debug and use breakpoints while streaming the trace. - ---- Further reading --- - -- http://percepio.com/2017/02/03/usb-trace-streaming-st-nucleo-f767zi-board -- http://percepio.com/2016/10/05/rtos-tracing -- https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming/ - ---- Troubleshooting --- - -A. If you get an error about "multiple definition of SysTick_Handler", open -FreeRTOSConfig.h (found in Core/Inc) and add this line in the bottom, -after the definition of xPortSysTickHandler. - -#undef xPortSysTickHandler - -B. If you get "Missed Events" in the Live Stream window, it is typically because -your application produces more trace data than can be transferred, so the trace -buffer overflows. -You may try the following to start with: -- Increase TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT and/or TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE in trcStreamingConfig.h -- Decrease TRC_CFG_CTRL_TASK_DELAY in trcConfig.h -- Increase TRC_CFG_CTRL_TASK_PRIORITY in trcConfig.h - -Also see the "tuning" guide at https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming/ - -Also note that this USB stream port has a diagnostics option that might come handy. -Enable USB_PERF_DIAGNOSTICS in trcStreamingPort.h. This will save additional "user events" -each time a buffer page is transmitted, showing the number of bytes sent and the -remaining capacity in the trace buffer (if this goes down to zero, data is lost). - -#define USB_PERF_DIAGNOSTICS 1 - -If you need assistence, feel free to contact support@percepio.com. - -Percepio AB -https://percepio.com \ No newline at end of file +Tracealyzer Stream Port for STM32 USB CDC (Virtual COM Port) +Percepio AB +https://percepio.com +------------------------------------------------------------ + +This directory contains a "stream port" for the Tracealyzer recorder library, +allowing for streaming the trace data over a USB connection. The stream port is defined by a set of macros in +trcStreamPort.h, found in the "include" directory, that relies on functions in trcStreamingPort.c. + +This particular stream port targets STM32 devices using USB CDC (virtual COM port). +It was been tested with STM32F767 and STM32L475. + +--- Prerequisites --- + +- An STM32 device with a USB connector for application use. + +- Tracealyzer 4 with a license for FreeRTOS, SafeRTOS or Micrium µC/OS-III. + +- STM32CubeIDE or the stand-alone STM32CubeMX configuration tool. + +--- Instructions --- + +1. Follow the general instructions (Section 1) at https://percepio.com/gettingstarted-freertos/ +and verify that Snapshot mode works. The basic integration of the recorder library is the same. + +2. Open the Device Configuration Tool (STM32CubeMX), e.g. by double-clicking on the .ioc file in your STM32CubeIDE project. + +2.1. Under "Middleware", enable "USB_DEVICE" and... +- In "USB_DEVICE Mode and Configuration", set the "Class for FS IP" to "Communication Device Class (Virtual Com Port)". +- Under Configuration -> Parameter Settings, set the TX and RX buffer sizes to a small value (e.g. 1). +The default TX and RX buffers are not used by the trace recorder library, so this avoids wasting RAM. + +2.2. Under "Connectivity", open "USB_OTG_FS" and... +- In "USB_OTG_FS Mode and Configuration", make sure "Mode" is set to "Device_Only" +- Under "Configuration", open "NVIC Settings" and make sure "USB OTG FS global interrupt" is enabled. + +3. Open trcConfig.h and set TRC_CFG_RECORDER_MODE to TRC_RECORDER_MODE_STREAMING. + +4. Copy trcStreamingPort.c and include/trcStreamPort.h into your project. + +5. Make sure you have "vTraceEnable(TRC_INIT);" in main.c (not TRC_START or so). +This should be placed after the HW setup but before making any RTOS calls. + +6. Plug in a USB cable to the connector labeled "USB OTG" or similar (i.e. for application use). + +7. Build the project and start it. Check that your computer finds a new USB device (there should be a notification). + +8. Check the number of the new COM port, that should have appeared. This is NOT "STLink Virtual COM port". + +9. Start Tracealyzer and open Recording Settings and select Target Connection: SerialPort. +You can also access these settings via File -> Settings -> PSF Streaming Settings. + +10. Enter the number of the COM port in the "Device" field. The settings (data +bits, data rate etc.) are irrelevant for USB serial connections and not used. + +11. While the target is running, select Record Streaming Trace in Tracealyzer. +You should now see a live display of the trace, while it is being received. +Make sure there are no warnings about "Dropped Events" (in that case, see Troubleshooting, below). + +Note that you can still debug and use breakpoints while streaming the trace. + +--- Further reading --- + +- http://percepio.com/2017/02/03/usb-trace-streaming-st-nucleo-f767zi-board +- http://percepio.com/2016/10/05/rtos-tracing +- https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming/ + +--- Troubleshooting --- + +A. If you get an error about "multiple definition of SysTick_Handler", open +FreeRTOSConfig.h (found in Core/Inc) and add this line in the bottom, +after the definition of xPortSysTickHandler. + +#undef xPortSysTickHandler + +B. If you get "Missed Events" in the Live Stream window, it is typically because +your application produces more trace data than can be transferred, so the trace +buffer overflows. +You may try the following to start with: +- Increase TRC_CFG_PAGED_EVENT_BUFFER_PAGE_COUNT and/or TRC_CFG_PAGED_EVENT_BUFFER_PAGE_SIZE in trcStreamingConfig.h +- Decrease TRC_CFG_CTRL_TASK_DELAY in trcConfig.h +- Increase TRC_CFG_CTRL_TASK_PRIORITY in trcConfig.h + +Also see the "tuning" guide at https://percepio.com/2018/10/11/tuning-your-custom-trace-streaming/ + +Also note that this USB stream port has a diagnostics option that might come handy. +Enable USB_PERF_DIAGNOSTICS in trcStreamPort.h. This will save additional "user events" +each time a buffer page is transmitted, showing the number of bytes sent and the +remaining capacity in the trace buffer (if this goes down to zero, data is lost). + +#define USB_PERF_DIAGNOSTICS 1 + +If you need assistence, feel free to contact support@percepio.com. diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/config/trcStreamPortConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/config/trcStreamPortConfig.h new file mode 100644 index 0000000000..7130bf362f --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/config/trcStreamPortConfig.h @@ -0,0 +1,39 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The configuration for trace streaming ("stream ports"). + */ + +#ifndef TRC_STREAM_PORT_CONFIG_H +#define TRC_STREAM_PORT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* The time to wait if the USB interface is busy. */ +#define TRC_CFG_STREAM_PORT_DELAY_ON_BUSY 3 + +/******************************************************************************* +* Configuration Macro: TRC_CFG_STREAM_PORT_USB_BUFFER_SIZE +* +* Specifies the size of the usb buffer. +******************************************************************************/ +#define TRC_CFG_STREAM_PORT_USB_BUFFER_SIZE 64 + +/******************************************************************************* +* Configuration Macro: TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_SIZE +* +* Specifies the size of the internal buffer. +******************************************************************************/ +#define TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_SIZE 10000 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAM_PORT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/include/trcStreamPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/include/trcStreamPort.h new file mode 100644 index 0000000000..5b053fd01c --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/include/trcStreamPort.h @@ -0,0 +1,110 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#ifndef TRC_STREAM_PORT_H +#define TRC_STREAM_PORT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRC_USE_INTERNAL_BUFFER 1 + +#define TRC_STREAM_PORT_USB_BUFFER_SIZE ((((TRC_CFG_STREAM_PORT_USB_BUFFER_SIZE) + sizeof(TraceUnsignedBaseType_t) - 1) / sizeof(TraceUnsignedBaseType_t)) * sizeof(TraceUnsignedBaseType_t)) +#define TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE ((((TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_SIZE) + sizeof(TraceUnsignedBaseType_t) - 1) / sizeof(TraceUnsignedBaseType_t)) * sizeof(TraceUnsignedBaseType_t)) + +typedef struct TraceStreamPortBuffer +{ + uint8_t buffer[(TRC_STREAM_PORT_USB_BUFFER_SIZE) + (TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE) + sizeof(TraceUnsignedBaseType_t)]; +} TraceStreamPortBuffer_t; + +traceResult prvTraceCDCReceive(void* data, uint32_t uiSize, int32_t* piBytesReceived); + +traceResult prvTraceCDCTransmit(void* pvData, uint32_t uiSize, int32_t* piBytesSent); + +/** + * @internal Stream port initialize callback. + * + * This function is called by the recorder as part of its initialization phase. + * + * @param[in] pxBuffer Buffer + * + * @retval TRC_FAIL Initialization failed + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer); + +/** + * @brief Allocates data from the stream port. + * + * @param[in] uiSize Allocation size + * @param[out] ppvData Allocation data pointer + * + * @retval TRC_FAIL Allocate failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortAllocate(uiSize, ppvData) ((void)uiSize, xTraceStaticBufferGet(ppvData)) + +/** + * @brief Commits data to the stream port, depending on the implementation/configuration of the + * stream port this data might be directly written to the stream port interface, buffered, or + * something else. + * + * @param[in] pvData Data to commit + * @param[in] uiSize Data to commit size + * @param[out] piBytesCommitted Bytes committed + * + * @retval TRC_FAIL Commit failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortCommit xTraceInternalEventBufferPush + +/** + * @brief Writes data through the stream port interface. + * + * @param[in] pvData Data to write + * @param[in] uiSize Data to write size + * @param[out] piBytesWritten Bytes written + * + * @retval TRC_FAIL Write failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortWriteData prvTraceCDCTransmit + +/** + * @brief Reads data through the stream port interface. + * + * @param[in] pvData Destination data buffer + * @param[in] uiSize Destination data buffer size + * @param[out] piBytesRead Bytes read + * + * @retval TRC_FAIL Read failed + * @retval TRC_SUCCESS Success + */ +#define xTraceStreamPortReadData prvTraceCDCReceive + +#define xTraceStreamPortOnEnable(uiStartOption) ((void)(uiStartOption), TRC_SUCCESS) + +#define xTraceStreamPortOnDisable() (TRC_SUCCESS) + +#define xTraceStreamPortOnTraceBegin() (TRC_SUCCESS) + +#define xTraceStreamPortOnTraceEnd() (TRC_SUCCESS) + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAM_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/include/trcStreamingPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/include/trcStreamingPort.h deleted file mode 100644 index 52827f4315..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/include/trcStreamingPort.h +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 - -#include "usb_device.h" -#include "usbd_CDC_if.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* The time to wait if the USB interface is busy. */ -#define TRC_CFG_DELAY_ON_BUSY 3 - -/* For FreeRTOS. Modify for other RTOSes. */ -#define TRC_OS_DELAY(x) vTaskDelay(x) - -void trcCDCInit(void); - -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() \ - trcCDCInit();\ - TRC_STREAM_PORT_MALLOC(); - -#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/STM32_USB_CDC/trcStreamPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/trcStreamPort.c new file mode 100644 index 0000000000..b89144e02a --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/trcStreamPort.c @@ -0,0 +1,151 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Supporting functions for trace streaming ("stream ports"). + * This "stream port" sets up the recorder to use USB CDC as streaming channel. + * The example is for STM32 using STM32Cube. + */ + +#include + +#include +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +static void prvCDCInit(void); + +static int8_t CDC_Receive_FS_modified(uint8_t* pbuf, uint32_t *puiLength); + +extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; + +static int8_t(*CDC_Receive_FS)(uint8_t* Buf, uint32_t* Len); + +typedef struct TraceStreamPortUSBCommandBuffer { + TraceUnsignedBaseType_t idx; + uint8_t bufferUSB[TRC_STREAM_PORT_USB_BUFFER_SIZE]; + uint8_t bufferInternal[TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE]; +} TraceStreamPortUSBBuffers_t; + +TraceStreamPortUSBBuffers_t* pxUSBBuffers; + +static int8_t CDC_Receive_FS_modified(uint8_t* pBuffer, uint32_t *puiLength) +{ + for(uint32_t i = 0; i < *puiLength; i++) + { + pxUSBBuffers->bufferUSB[pxUSBBuffers->idx] = pBuffer[i]; + pxUSBBuffers->idx++; + } + + CDC_Receive_FS(pBuffer, puiLength); + + return (USBD_OK); +} + +static void prvCDCInit(void) +{ + /* Store the original "Receive" function, from the static initialization */ + CDC_Receive_FS = USBD_Interface_fops_FS.Receive; + + /* Update the function pointer with our modified variant */ + USBD_Interface_fops_FS.Receive = CDC_Receive_FS_modified; + + pxUSBBuffers->idx = 0; + + MX_USB_DEVICE_Init(); +} + +/* The READ function, used in trcStreamPort.h */ +traceResult prvTraceCDCReceive(void *data, uint32_t uiSize, int32_t* piBytesReceived) +{ + uint32_t i, uiDiff; + + if(pxUSBBuffers->idx > 0) + { + if ((TraceUnsignedBaseType_t)uiSize >= pxUSBBuffers->idx) // More than what is stored, number of bytes will be .idx + { + TRC_MEMCPY(data, pxUSBBuffers->bufferUSB, pxUSBBuffers->idx); + *piBytesReceived = (int32_t)pxUSBBuffers->idx; + pxUSBBuffers->idx = 0; // Make the buffer ready for a new command + } + else // If some data in the buffer is not read + { + uiDiff = pxUSBBuffers->idx - uiSize; + TRC_MEMCPY(data, pxUSBBuffers->bufferUSB, uiSize); + + for(i = 0; i < uiDiff; i++) + { + pxUSBBuffers->bufferUSB[i] = pxUSBBuffers->bufferUSB[i + uiSize]; + } + + *piBytesReceived = uiSize; + + pxUSBBuffers->idx = uiDiff; + } + } + else + { + *piBytesReceived = 0; + } + + return TRC_SUCCESS; +} + +/* The WRITE function, used in trcStreamPort.h */ +traceResult prvTraceCDCTransmit(void* pvData, uint32_t uiSize, int32_t * piBytesSent ) +{ + static int fail_counter = 0; + + int32_t result; + + *piBytesSent = 0; + + result = CDC_Transmit_FS(pvData, uiSize); + + if (result == USBD_OK) + { + fail_counter = 0; + *piBytesSent = uiSize; + return TRC_SUCCESS; + } + else + { + fail_counter++; + + /* We keep trying to send more pvData. If busy, we delay for a while. This function will be called again afterwards. */ + xTraceKernelPortDelay(TRC_CFG_STREAM_PORT_DELAY_ON_BUSY); + + if (fail_counter >= 100) + { + /* If many unsuccessful attempts in a row, something is very wrong. Returning -1 will stop the recorder. */ + return TRC_FAIL; + } + } + + return TRC_SUCCESS; +} + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortUSBBuffers_t); + + if (pxBuffer == 0) + { + return TRC_FAIL; + } + + pxUSBBuffers = (TraceStreamPortUSBBuffers_t*)pxBuffer; + + prvCDCInit(); + + return xTraceInternalEventBufferInitialize(pxUSBBuffers->bufferInternal, sizeof(pxUSBBuffers->bufferInternal)); +} + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/trcStreamingPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/trcStreamingPort.c deleted file mode 100644 index a2ad625e87..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/STM32_USB_CDC/trcStreamingPort.c +++ /dev/null @@ -1,164 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * Percepio AB, www.percepio.com - * - * trcStreamingPort.c - * - * Supporting functions for trace streaming ("stream ports"). - * This "stream port" sets up the recorder to use USB CDC as streaming channel. - * The example is for STM32 using STM32Cube. - * - * Terms of Use - * This file is part of the trace recorder library (RECORDER), which is the - * intellectual property of Percepio AB (PERCEPIO) and provided under a - * license as follows. - * The RECORDER may be used free of charge for the purpose of recording data - * intended for analysis in PERCEPIO products. It may not be used or modified - * for other purposes without explicit permission from PERCEPIO. - * You may distribute the RECORDER in its original source code form, assuming - * this text (terms of use, disclaimer, copyright notice) is unchanged. You are - * allowed to distribute the RECORDER with minor modifications intended for - * configuration or porting of the RECORDER, e.g., to allow using it on a - * specific processor, processor family or with a specific communication - * interface. Any such modifications should be documented directly below - * this comment block. - * - * Disclaimer - * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty - * as to its use or performance. PERCEPIO does not and cannot warrant the - * performance or results you may obtain by using the RECORDER or documentation. - * PERCEPIO make no warranties, express or implied, as to noninfringement of - * third party rights, merchantability, or fitness for any particular purpose. - * In no event will PERCEPIO, its technology partners, or distributors be liable - * to you for any consequential, incidental or special damages, including any - * lost profits or lost savings, even if a representative of PERCEPIO has been - * advised of the possibility of such damages, or for any claim by any third - * party. Some jurisdictions do not allow the exclusion or limitation of - * incidental, consequential or special damages, or the exclusion of implied - * warranties or limitations on how long an implied warranty may last, so the - * above limitations may not apply to you. - * - * Tabs are used for indent in this file (1 tab = 4 spaces) - * - * Copyright Percepio AB, 2018. - * www.percepio.com - ******************************************************************************/ - -#include "trcRecorder.h" - -#if (TRC_USE_TRACEALYZER_RECORDER == 1) -#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) - -#include "stdint.h" - -typedef struct{ - uint32_t idx; - uint8_t data[64]; -}recBuf; - -recBuf commandBuffer; - -static int8_t CDC_Receive_FS_modified (uint8_t* pbuf, uint32_t *Len); - -extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; - -static int8_t (* CDC_Receive_FS)(uint8_t *Buf, uint32_t *Len); - -static int8_t CDC_Receive_FS_modified (uint8_t* Buf, uint32_t *Len) -{ - for( uint32_t i=0;i<* Len;i++) - { - commandBuffer.data[commandBuffer.idx]=Buf[i]; - commandBuffer.idx++; - } - - CDC_Receive_FS(Buf, Len); - - return (USBD_OK); -} - - -void trcCDCInit(void) -{ - - /* Store the original "Receive" function, from the static initialization */ - CDC_Receive_FS = USBD_Interface_fops_FS.Receive; - - /* Update the function pointer with our modified variant */ - USBD_Interface_fops_FS.Receive = CDC_Receive_FS_modified; - - MX_USB_DEVICE_Init(); -} - -/* 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 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 +Tracealyzer Stream Port for TCP/IP (lwIP example) +Percepio AB +www.percepio.com +------------------------------------------------- + +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 +trcStreamPort.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 trcStreamPort.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. diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/config/trcStreamPortConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/config/trcStreamPortConfig.h new file mode 100644 index 0000000000..76ad0744e4 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/config/trcStreamPortConfig.h @@ -0,0 +1,41 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The configuration for trace streaming ("stream ports"). + */ + +#ifndef TRC_STREAM_PORT_CONFIG_H +#define TRC_STREAM_PORT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* This define will determine whether to use the internal buffer or not. +If file writing creates additional trace events (i.e. it uses semaphores or mutexes), +then the internal buffer must be enabled to avoid infinite recursion. */ +#define TRC_CFG_STREAM_PORT_USE_INTERNAL_BUFFER 0 + +/******************************************************************************* +* Configuration Macro: TRC_CFG_STREAM_PORT_TCPIP_PORT +* +* Specifies the TCP/IP port. +******************************************************************************/ +#define TRC_CFG_STREAM_PORT_TCPIP_PORT 8888 + +/******************************************************************************* +* Configuration Macro: TRC_CFG_STREAM_PORT_BUFFER_SIZE +* +* Specifies the size of the internal buffer, if one is used. +******************************************************************************/ +#define TRC_CFG_STREAM_PORT_BUFFER_SIZE 10000 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAM_PORT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/include/trcStreamPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/include/trcStreamPort.h new file mode 100644 index 0000000000..7dc0ceb3cc --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/include/trcStreamPort.h @@ -0,0 +1,75 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#ifndef TRC_STREAM_PORT_H +#define TRC_STREAM_PORT_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRC_USE_INTERNAL_BUFFER (TRC_CFG_STREAM_PORT_USE_INTERNAL_BUFFER) + +/** + * @def TRC_STREAM_PORT_BUFFER_SIZE + * + * @brief The buffer size, aligned to base type. + */ +#define TRC_STREAM_PORT_BUFFER_SIZE ((((TRC_CFG_STREAM_PORT_BUFFER_SIZE) + sizeof(TraceUnsignedBaseType_t) - 1) / sizeof(TraceUnsignedBaseType_t)) * sizeof(TraceUnsignedBaseType_t)) + +typedef struct TraceStreamPortBuffer +{ +#if (TRC_USE_INTERNAL_BUFFER) + uint8_t buffer[(TRC_STREAM_PORT_BUFFER_SIZE)]; +#else + TraceUnsignedBaseType_t buffer[1]; +#endif +} TraceStreamPortBuffer_t; + +int32_t prvTraceTcpWrite(void* pvData, uint32_t uiSize, int32_t* piBytesWritten); + +int32_t prvTraceTcpRead(void* pvData, uint32_t uiSize, int32_t* piBytesRead); + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer); + +#define xTraceStreamPortAllocate(uiSize, ppvData) ((void)(uiSize), xTraceStaticBufferGet(ppvData)) + +#if (TRC_USE_INTERNAL_BUFFER == 1) +/* Push to internal buffer. It will call on xTraceStreamPortWriteData() periodically. */ +#define xTraceStreamPortCommit xTraceInternalEventBufferPush +#else +/* Write directly */ +#define xTraceStreamPortCommit xTraceStreamPortWriteData +#endif + +#define xTraceStreamPortWriteData(pvData, uiSize, piBytesWritten) (prvTraceTcpWrite(pvData, uiSize, piBytesWritten) == 0 ? TRC_SUCCESS : TRC_FAIL) + +#define xTraceStreamPortReadData(pvData, uiSize, piBytesRead) (prvTraceTcpRead(pvData, uiSize, piBytesRead) == 0 ? TRC_SUCCESS : TRC_FAIL) + +#define xTraceStreamPortOnEnable(uiStartOption) ((void)(uiStartOption), TRC_SUCCESS) + +#define xTraceStreamPortOnDisable() (TRC_SUCCESS) + +#define xTraceStreamPortOnTraceBegin() (TRC_SUCCESS) + +traceResult xTraceStreamPortOnTraceEnd(void); + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAM_PORT_H */ + 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 deleted file mode 100644 index c538e2b9ba..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/include/trcStreamingPort.h +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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/trcStreamPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/trcStreamPort.c new file mode 100644 index 0000000000..9ff82d1f22 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/trcStreamPort.c @@ -0,0 +1,205 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +/* TCP/IP includes - for lwIP in this case */ +#include +#include +#include + +int sock = -1, new_sd = -1; +int flags = 0; +int remoteSize; +struct sockaddr_in address, remote; + +typedef struct TraceStreamPortTCPIP +{ +#if (TRC_USE_INTERNAL_BUFFER) + uint8_t buffer[(TRC_STREAM_PORT_BUFFER_SIZE)]; +#else + TraceUnsignedBaseType_t buffer[1]; +#endif +} TraceStreamPortTCPIP_t; + +static TraceStreamPortTCPIP_t* pxStreamPortFile; + +static int32_t prvSocketSend(void* pvData, uint32_t uiSize, int32_t* piBytesWritten); +static int32_t prvSocketReceive(void* pvData, uint32_t uiSize, int32_t* bytesRead); +static int32_t prvSocketInitializeListener(); +static int32_t prvSocketAccept(); +static void prvCloseAllSockets(); + +static int32_t prvSocketSend( void* pvData, uint32_t uiSize, int32_t* piBytesWritten ) +{ + if (new_sd < 0) + return -1; + + if (piBytesWritten == 0) + return -1; + + *piBytesWritten = send( new_sd, pvData, uiSize, 0 ); + if (*piBytesWritten < 0) + { + /* EWOULDBLOCK may be expected when buffers are full */ + if ((errno != 0) && (errno != EWOULDBLOCK)) + { + closesocket(new_sd); + new_sd = -1; + return -1; + } + else + *piBytesWritten = 0; + } + + return 0; +} + +static int32_t prvSocketReceive( void* pvData, uint32_t uiSize, int32_t* bytesRead ) +{ + if (new_sd < 0) + return -1; + + *bytesRead = recv( new_sd, pvData, uiSize, 0 ); + /* EWOULDBLOCK may be expected when there is no pvData to receive */ + if (errno != 0 && errno != EWOULDBLOCK) + { + closesocket(new_sd); + new_sd = -1; + return -1; + } + + return 0; +} + +static int32_t prvSocketInitializeListener() +{ + 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_CFG_STREAM_PORT_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; +} + +static int32_t prvSocketAccept() +{ + 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; +} + +static void prvCloseAllSockets() +{ + if (new_sd > 0) + { + closesocket(new_sd); + } + + if (sock > 0) + { + closesocket(sock); + } +} +/************** MODIFY THE ABOVE PART TO USE YOUR TPC/IP STACK ****************/ + +int32_t prvTraceTcpWrite(void* pvData, uint32_t uiSize, int32_t *piBytesWritten) +{ + prvSocketInitializeListener(); + + prvSocketAccept(); + + return prvSocketSend(pvData, uiSize, piBytesWritten); +} + +int32_t prvTraceTcpRead(void* pvData, uint32_t uiSize, int32_t *piBytesRead) +{ + prvSocketInitializeListener(); + + prvSocketAccept(); + + return prvSocketReceive(pvData, uiSize, piBytesRead); +} + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortTCPIP_t); + + if (pxBuffer == 0) + { + return TRC_FAIL; + } + + pxStreamPortFile = (TraceStreamPortTCPIP_t*)pxBuffer; + +#if (TRC_USE_INTERNAL_BUFFER == 1) + return xTraceInternalEventBufferInitialize(pxStreamPortFile->buffer, sizeof(pxStreamPortFile->buffer)); +#else + return TRC_SUCCESS; +#endif +} + +traceResult xTraceStreamPortOnTraceEnd(void) +{ + prvCloseAllSockets(); + + return TRC_SUCCESS; +} + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/trcStreamingPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/trcStreamingPort.c deleted file mode 100644 index ebb0c99a49..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP/trcStreamingPort.c +++ /dev/null @@ -1,180 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 index b61ecff8f1..6738fd47ca 100644 --- 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 @@ -1,38 +1,37 @@ -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 +Tracealyzer Stream Port for TCP/IP (Win32 example) +Percepio AB +www.percepio.com +------------------------------------------------- + +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 trcStreamPort.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 trcStreamPort.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. diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/config/trcStreamPortConfig.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/config/trcStreamPortConfig.h new file mode 100644 index 0000000000..76ad0744e4 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/config/trcStreamPortConfig.h @@ -0,0 +1,41 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The configuration for trace streaming ("stream ports"). + */ + +#ifndef TRC_STREAM_PORT_CONFIG_H +#define TRC_STREAM_PORT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* This define will determine whether to use the internal buffer or not. +If file writing creates additional trace events (i.e. it uses semaphores or mutexes), +then the internal buffer must be enabled to avoid infinite recursion. */ +#define TRC_CFG_STREAM_PORT_USE_INTERNAL_BUFFER 0 + +/******************************************************************************* +* Configuration Macro: TRC_CFG_STREAM_PORT_TCPIP_PORT +* +* Specifies the TCP/IP port. +******************************************************************************/ +#define TRC_CFG_STREAM_PORT_TCPIP_PORT 8888 + +/******************************************************************************* +* Configuration Macro: TRC_CFG_STREAM_PORT_BUFFER_SIZE +* +* Specifies the size of the internal buffer, if one is used. +******************************************************************************/ +#define TRC_CFG_STREAM_PORT_BUFFER_SIZE 10000 + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_STREAM_PORT_CONFIG_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/include/trcStreamPort.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/include/trcStreamPort.h new file mode 100644 index 0000000000..fae09bdfa5 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/include/trcStreamPort.h @@ -0,0 +1,81 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#ifndef TRC_STREAM_PORT_H +#define TRC_STREAM_PORT_H + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRC_USE_INTERNAL_BUFFER (TRC_CFG_STREAM_PORT_USE_INTERNAL_BUFFER) + +/** + * @def TRC_STREAM_PORT_BUFFER_SIZE + * + * @brief The buffer size, aligned to base type. + */ +#define TRC_STREAM_PORT_BUFFER_SIZE ((((TRC_CFG_STREAM_PORT_BUFFER_SIZE) + sizeof(TraceUnsignedBaseType_t) - 1) / sizeof(TraceUnsignedBaseType_t)) * sizeof(TraceUnsignedBaseType_t)) + +typedef struct TraceStreamPortBuffer +{ +#if (TRC_USE_INTERNAL_BUFFER) + uint8_t buffer[(TRC_STREAM_PORT_BUFFER_SIZE)]; +#else + TraceUnsignedBaseType_t buffer[1]; +#endif +} TraceStreamPortBuffer_t; + +int32_t prvTraceWriteToSocket(void* data, uint32_t size, int32_t* ptrBytesWritten); +int32_t prvTraceReadFromSocket(void* data, uint32_t bufsize, int32_t* ptrBytesRead); + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer); + +#define xTraceStreamPortAllocate(uiSize, ppvData) ((void)(uiSize), xTraceStaticBufferGet(ppvData)) + +#if (TRC_USE_INTERNAL_BUFFER == 1) +/* Push to internal buffer. It will call on xTraceStreamPortWriteData() periodically. */ +#define xTraceStreamPortCommit xTraceInternalEventBufferPush +#else +/* Write directly */ +#define xTraceStreamPortCommit xTraceStreamPortWriteData +#endif + +#define xTraceStreamPortWriteData(pvData, uiSize, piBytesWritten) (prvTraceWriteToSocket(pvData, uiSize, piBytesWritten) == 0 ? TRC_SUCCESS : TRC_FAIL) + +#define xTraceStreamPortReadData(pvData, uiSize, piBytesRead) (prvTraceReadFromSocket(pvData, uiSize, piBytesRead) == 0 ? TRC_SUCCESS : TRC_FAIL) + +#define xTraceStreamPortOnEnable(uiStartOption) ((void)(uiStartOption), TRC_SUCCESS) + +#define xTraceStreamPortOnDisable() (TRC_SUCCESS) + +#define xTraceStreamPortOnTraceBegin() (TRC_SUCCESS) + +traceResult xTraceStreamPortOnTraceEnd(void); + +#ifdef __cplusplus +} +#endif + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + +#endif /* TRC_STREAM_PORT_H */ 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 deleted file mode 100644 index 838aea923e..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/include/trcStreamingPort.h +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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/trcStreamPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/trcStreamPort.c new file mode 100644 index 0000000000..cffdbe4f51 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/trcStreamPort.c @@ -0,0 +1,238 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#include +#include + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#pragma comment(lib,"ws2_32.lib") //Winsock Library + +typedef struct TraceStreamPortTCPIP +{ +#if (TRC_USE_INTERNAL_BUFFER) + uint8_t buffer[(TRC_STREAM_PORT_BUFFER_SIZE)]; +#else + TraceUnsignedBaseType_t buffer[1]; +#endif +} TraceStreamPortTCPIP_t; + +static TraceStreamPortTCPIP_t* pxStreamPortFile; +static SOCKET server_socket = (UINT_PTR)0, trace_socket = (UINT_PTR)0; +struct sockaddr_in server, client; + +static int prvInitServerSocketIfNeeded(void); +static int prvInitWinsockIfNeeded(void); +static int prvInitTraceSocketIfNeeded(void); +static void prvCloseAllSockets(void); + +static int prvInitWinsockIfNeeded(void) +{ + WSADATA wsa; + + if (server_socket) + return 0; + + if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) + { + return -1; + } + + return 0; +} + +static int prvInitServerSocketIfNeeded(void) +{ + if (prvInitWinsockIfNeeded() < 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(TRC_CFG_STREAM_PORT_TCPIP_PORT); + + if (bind(server_socket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) + { + closesocket(server_socket); + WSACleanup(); + server_socket = (UINT_PTR)0; + return -1; + } + + if (listen(server_socket, 3) < 0) + { + closesocket(server_socket); + WSACleanup(); + server_socket = (UINT_PTR)0; + return -1; + } + + return 0; +} + +static int prvInitTraceSocketIfNeeded(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)0; + + closesocket(server_socket); + WSACleanup(); + server_socket = (UINT_PTR)0; + + return -1; + } + + return 0; +} + +int32_t prvTraceWriteToSocket(void* data, uint32_t size, int32_t *ptrBytesWritten) +{ + int ret; + + if (prvInitServerSocketIfNeeded() < 0) + { + return -1; + } + + if (prvInitTraceSocketIfNeeded() < 0) + { + return -1; + } + + if (!trace_socket) + { + if (ptrBytesWritten != 0) + { + *ptrBytesWritten = 0; + } + return -1; + } + ret = send(trace_socket, data, size, 0); + if (ret <= 0) + { + if (ptrBytesWritten != 0) + { + *ptrBytesWritten = 0; + } + + closesocket(trace_socket); + trace_socket = (UINT_PTR)0; + return ret; + } + + if (ptrBytesWritten != 0) + { + *ptrBytesWritten = ret; + } + + return 0; +} + +int32_t prvTraceReadFromSocket(void* data, uint32_t bufsize, int32_t *ptrBytesRead) +{ + unsigned long bytesAvailable = 0; + + if (prvInitServerSocketIfNeeded() < 0) + return -1; + + if (prvInitTraceSocketIfNeeded() < 0) + return -1; + + if (ioctlsocket(trace_socket, FIONREAD, &bytesAvailable) != NO_ERROR) + { + closesocket(trace_socket); + trace_socket = (UINT_PTR)0; + return -1; + } + + if (bytesAvailable > 0) + { + *ptrBytesRead = recv(trace_socket, data, bufsize, 0); + if (*ptrBytesRead == SOCKET_ERROR) + { + closesocket(trace_socket); + trace_socket = (UINT_PTR)0; + return -1; + } + } + + return 0; +} + +static void prvCloseAllSockets(void) +{ + if (trace_socket != 0) + { + closesocket(trace_socket); + trace_socket = 0; + } + + if (server_socket != 0) + { + closesocket(server_socket); + server_socket = 0; + } +} + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortTCPIP_t); + + if (pxBuffer == 0) + { + return TRC_FAIL; + } + + pxStreamPortFile = (TraceStreamPortTCPIP_t*)pxBuffer; + +#if (TRC_USE_INTERNAL_BUFFER == 1) + return xTraceInternalEventBufferInitialize(pxStreamPortFile->buffer, sizeof(pxStreamPortFile->buffer)); +#else + return TRC_SUCCESS; +#endif +} + +traceResult xTraceStreamPortOnTraceEnd(void) +{ + prvCloseAllSockets(); + + return TRC_SUCCESS; +} + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ 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 deleted file mode 100644 index aa39c0503f..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/TCPIP_Win32/trcStreamingPort.c +++ /dev/null @@ -1,210 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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 deleted file mode 100644 index a231518058..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/Readme-Streamport.txt +++ /dev/null @@ -1,27 +0,0 @@ -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 deleted file mode 100644 index 082eebf510..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/include/trcStreamingPort.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * 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 deleted file mode 100644 index 351d833259..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/USB_CDC/trcStreamingPort.c +++ /dev/null @@ -1,291 +0,0 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.3.11 - * Percepio AB, www.percepio.com - * - * trcStreamingPort.c - * - * Supporting functions for trace streaming ("stream ports"). - * This "stream port" sets up the recorder to use USB CDC as streaming channel. - * The example is for STM32 using STM32Cube. - * - * Terms of Use - * This file is part of the trace recorder library (RECORDER), which is the - * intellectual property of Percepio AB (PERCEPIO) and provided under a - * license as follows. - * The RECORDER may be used free of charge for the purpose of recording data - * intended for analysis in PERCEPIO products. It may not be used or modified - * for other purposes without explicit permission from PERCEPIO. - * You may distribute the RECORDER in its original source code form, assuming - * this text (terms of use, disclaimer, copyright notice) is unchanged. You are - * allowed to distribute the RECORDER with minor modifications intended for - * configuration or porting of the RECORDER, e.g., to allow using it on a - * specific processor, processor family or with a specific communication - * interface. Any such modifications should be documented directly below - * this comment block. - * - * Disclaimer - * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty - * as to its use or performance. PERCEPIO does not and cannot warrant the - * performance or results you may obtain by using the RECORDER or documentation. - * PERCEPIO make no warranties, express or implied, as to noninfringement of - * third party rights, merchantability, or fitness for any particular purpose. - * In no event will PERCEPIO, its technology partners, or distributors be liable - * to you for any consequential, incidental or special damages, including any - * lost profits or lost savings, even if a representative of PERCEPIO has been - * advised of the possibility of such damages, or for any claim by any third - * party. Some jurisdictions do not allow the exclusion or limitation of - * incidental, consequential or special damages, or the exclusion of implied - * warranties or limitations on how long an implied warranty may last, so the - * above limitations may not apply to you. - * - * Tabs are used for indent in this file (1 tab = 4 spaces) - * - * Copyright Percepio AB, 2018. - * www.percepio.com - ******************************************************************************/ - -#include "trcRecorder.h" - -#if (TRC_USE_TRACEALYZER_RECORDER == 1) -#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) - -#include "stdint.h" - -/* Include files as needed, in this case it is files from STM32Cube FW_F7 V1.4.1 */ -#include "usb_device.h" -#include "usbd_cdc.h" -#include "usbd_CDC_if.h" -#include "usb_device.h" - -#define BUFSIZE 64 - -typedef struct{ - uint32_t idx; - uint8_t data[BUFSIZE]; -}recBuf; - -/* Define size for the receive and transmit buffer over CDC */ -#define APP_RX_DATA_SIZE 8 -#define APP_TX_DATA_SIZE 64 - -/* Received Data over USB are stored in this buffer */ -uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; - -/* Send Data over USB CDC are stored in this buffer */ -uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; - -extern USBD_HandleTypeDef hUsbDeviceFS; - -extern PCD_HandleTypeDef hpcd_USB_OTG_FS; - -recBuf commandBuffer; - -static int8_t CDC_Init_FS (void); -static int8_t CDC_DeInit_FS (void); -static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length); -static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len); - -USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = -{ - CDC_Init_FS, - CDC_DeInit_FS, - CDC_Control_FS, - CDC_Receive_FS -}; - -/* Private functions ---------------------------------------------------------*/ -/** - * @brief CDC_Init_FS - * Initializes the CDC media low layer over the FS USB IP - * @param None - * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Init_FS(void) -{ - /* Set Application Buffers */ - USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0); - USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS); - return (USBD_OK); -} - -/** - * @brief CDC_DeInit_FS - * DeInitializes the CDC media low layer - * @param None - * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_DeInit_FS(void) -{ - return (USBD_OK); -} - -/** - * @brief CDC_Control_FS - * Manage the CDC class requests - * @param cmd: Command code - * @param pbuf: Buffer containing command data (request parameters) - * @param length: Number of data to be sent (in bytes) - * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length) -{ - switch (cmd) - { - case CDC_SEND_ENCAPSULATED_COMMAND: - break; - - case CDC_GET_ENCAPSULATED_RESPONSE: - break; - - case CDC_SET_COMM_FEATURE: - break; - - case CDC_GET_COMM_FEATURE: - break; - - case CDC_CLEAR_COMM_FEATURE: - break; - - /*******************************************************************************/ - /* Line Coding Structure */ - /*-----------------------------------------------------------------------------*/ - /* Offset | Field | Size | Value | Description */ - /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ - /* 4 | bCharFormat | 1 | Number | Stop bits */ - /* 0 - 1 Stop bit */ - /* 1 - 1.5 Stop bits */ - /* 2 - 2 Stop bits */ - /* 5 | bParityType | 1 | Number | Parity */ - /* 0 - None */ - /* 1 - Odd */ - /* 2 - Even */ - /* 3 - Mark */ - /* 4 - Space */ - /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ - /*******************************************************************************/ - case CDC_SET_LINE_CODING: - break; - - case CDC_GET_LINE_CODING: - break; - - case CDC_SET_CONTROL_LINE_STATE: - break; - - case CDC_SEND_BREAK: - break; - - default: - break; - } - return (USBD_OK); -} - -/** - * @brief CDC_Receive_FS - * Data received over USB OUT endpoint are sent over CDC interface - * through this function. - * - * @note - * This function will block any OUT packet reception on USB endpoint - * until exiting this function. If you exit this function before transfer - * is complete on CDC interface (i.e. using DMA controller) it will result - * in receiving more data while previous ones are still not sent. - * - * @param Buf: Buffer of data to be received - * @param Len: Number of data received (in bytes) - * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len) -{ - for( uint32_t i=0;i<* Len;i++) - { - commandBuffer.data[commandBuffer.idx]=Buf[i]; - commandBuffer.idx++; - } - USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); - USBD_CDC_ReceivePacket(&hUsbDeviceFS); - - return (USBD_OK); -} - -/** - * @brief CDC_Transmit_FS - * Data send over USB IN endpoint are sent over CDC interface - * through this function. - * @note - * - * - * @param Buf: Buffer of data to be send - * @param Len: Number of data to be send (in bytes) - * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY - */ -uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) -{ - uint8_t result = USBD_OK; - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; - if (hcdc->TxState != 0){ - return USBD_BUSY; - } - USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len); - result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); - return result; -} - -/* The READ function, used in trcStreamingPort.h */ -int32_t trcCDCReceive(void *data, uint32_t size, int32_t* NumBytes) -{ - uint32_t i,diff; - - if(commandBuffer.idx>0) - { - if (size >= commandBuffer.idx) // more than what is stored, number of bytes will be .idx - { - memcpy(data,commandBuffer.data, commandBuffer.idx); - *NumBytes=commandBuffer.idx; - commandBuffer.idx=0; // Make the buffer ready for a new command - } - else //If some data in the buffer is not read - { - diff = commandBuffer.idx-size; - memcpy(data,commandBuffer.data, size); - for(i=0;i +#include + +#define TRC_USE_INTERNAL_BUFFER (TRC_CFG_STREAM_PORT_USE_INTERNAL_BUFFER) + +/* Aligned */ +#define TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE ((((TRC_CFG_STREAM_PORT_INTERNAL_BUFFER_SIZE) + sizeof(TraceUnsignedBaseType_t) - 1) / sizeof(TraceUnsignedBaseType_t)) * sizeof(TraceUnsignedBaseType_t)) + +/** + * @brief A structure representing the trace stream port buffer. + */ +typedef struct TraceStreamPortBuffer +{ +#if (TRC_USE_INTERNAL_BUFFER == 1) + uint8_t uiBufferInternal[TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE]; +#endif + uint8_t uiBuffer[4]; +} TraceStreamPortBuffer_t; + +/** + * @internal Stream port initialize callback. + * + * This function is called by the recorder as part of its initialization phase. + * + * @param[in] pxBuffer Buffer + * @retval TRC_FAIL Initialization failed + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer); + +/** + * @brief Stream port begin callback. + * + * This function is called by the recorder as part of its begin phase. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortOnBegin(void); + +/** + * @brief Stream port end callback. + * + * This function is called by the recorder as part of its end phase. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortOnEnd(void); + +/** + * @brief Allocates data from the stream port. + * + * @param[in] uiSize Allocation size + * @param[out] ppvData Allocation data pointer + * + * @retval TRC_FAIL Allocate failed + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortAllocate(uint32_t uiSize, void** ppvData); + +/** + * @brief Commits data to the stream port, depending on the implementation/configuration of the + * stream port this data might be directly written to the stream port interface, buffered, or + * something else. + * + * @param[in] pvData Data to commit + * @param[in] uiSize Data to commit size + * @param[out] piBytesCommitted Bytes commited + * + * @retval TRC_FAIL Commit failed + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortCommit(void* pvData, uint32_t uiSize, int32_t* piBytesCommitted); + +/** + * @brief Writes data through the stream port interface. + * + * @param[in] pvData Data to write + * @param[in] uiSize Data to write size + * @param[out] piBytesWritten Bytes written + * + * @retval TRC_FAIL Write failed + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortWriteData(void* pvData, uint32_t uiSize, int32_t* piBytesWritten); + +/** + * @brief Reads data through the stream port interface. + * + * @param[in] pvData Destination data buffer + * @param[in] uiSize Destination data buffer size + * @param[out] piBytesRead Bytes read + * + * @retval TRC_FAIL Read failed + * @retval TRC_SUCCESS Success + */ +traceResult xTraceStreamPortReadData(void* pvData, uint32_t uiSize, int32_t* piBytesRead); + +#ifdef __cplusplus +} +#endif + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ + +#endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/ + +#endif /* TRC_STREAMING_PORT_H */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/XMOS_xScope/trcStreamPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/XMOS_xScope/trcStreamPort.c new file mode 100644 index 0000000000..46ecbf5be7 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/XMOS_xScope/trcStreamPort.c @@ -0,0 +1,101 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Supporting functions for trace streaming, used by the "stream ports" + * for reading and writing data to the interface. + */ + +#include +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +typedef struct TraceStreamPortXS { +#if (TRC_USE_INTERNAL_BUFFER == 1) + uint8_t uiBufferInternal[TRC_STREAM_PORT_INTERNAL_BUFFER_SIZE]; +#endif + uint8_t uiBuffer[4]; +} TraceStreamPortXS_t; + +static TraceStreamPortXS_t* pxStreamPortXS; + +traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortXS_t); + + if (pxBuffer == 0) + { + return TRC_FAIL; + } + + pxStreamPortXS = (TraceStreamPortXS_t*)pxBuffer; + +#if (TRC_USE_INTERNAL_BUFFER == 1) + return xTraceInternalEventBufferInitialize(pxStreamPortXS->uiBufferInternal, sizeof(pxStreamPortXS->uiBufferInternal)); +#else + return TRC_SUCCESS; +#endif +} + +traceResult xTraceStreamPortOnBegin(void) +{ + return TRC_SUCCESS; +} + +traceResult xTraceStreamPortOnEnd(void) +{ + return TRC_SUCCESS; +} + +traceResult xTraceStreamPortAllocate(uint32_t uiSize, void** ppvData) +{ + (void)uiSize; + + return xTraceStaticBufferGet(ppvData); +} + +traceResult xTraceStreamPortCommit(void* pvData, uint32_t uiSize, int32_t* piBytesCommitted) +{ + if (pvData == 0) + { + return TRC_FAIL; + } + +#if (TRC_USE_INTERNAL_BUFFER == 1) + /* Push to internal buffer. It will call on xTraceStreamPortWriteData() periodically. */ + return xTraceInternalEventBufferPush(pvData, uiSize, piBytesCommitted); +#else + /* Write directly to file */ + return xTraceStreamPortWriteData(pvData, uiSize, piBytesCommitted); +#endif +} + +traceResult xTraceStreamPortWriteData(void* pvData, uint32_t uiSize, int32_t* piBytesWritten) +{ + /* xscope_bytes is supposed to be thread safe, so we do not bother with any + * critical sections here. */ + xscope_bytes(0, uiSize, (unsigned char*)pvData); + + if (piBytesWritten != 0) { + /* Since xScope always write all bytes (not all might be received) we flag this as + * a full write */ + *piBytesWritten = (int32_t)uiSize; + } + + return TRC_SUCCESS; +} + +traceResult xTraceStreamPortReadData(void* pvData, uint32_t uiSize, int32_t* piBytesRead) +{ + return TRC_SUCCESS; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/tracealyzer_readme.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/tracealyzer_readme.txt deleted file mode 100644 index 92e28dbf77..0000000000 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/tracealyzer_readme.txt +++ /dev/null @@ -1,418 +0,0 @@ -------------------------------------------------------------------------------- - 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.11 -> v4.4.0 -- Updates to the USB CDC streamport - -------------------------------------------------------------------------------- - -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/trcAssert.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcAssert.c new file mode 100644 index 0000000000..8d40867d6d --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcAssert.c @@ -0,0 +1,125 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for errors. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +#if (defined(TRC_CFG_TEST_MODE) && (TRC_CFG_TEST_MODE) == 1) + +extern inline TraceBaseType_t prvTraceAssertCheckCondition(TraceBaseType_t condition); + +#endif + +#define TRC_ASSERT_STATE_INDEX_LINE_NUMBER 0 + +typedef struct TraceAssertInfo +{ + TraceEntryHandle_t xEntry; +} TraceAssertInfo_t; + +static TraceAssertInfo_t* pxAssertInfo; + +traceResult xTraceAssertInitialize(TraceAssertBuffer_t *pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceAssertBuffer_t, TraceAssertInfo_t); + + TRC_ASSERT(pxBuffer != 0); + + pxAssertInfo = (TraceAssertInfo_t*)pxBuffer; + pxAssertInfo->xEntry = 0; + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_ASSERT); + + return TRC_SUCCESS; +} + +void prvTraceAssertCreate(const char* szFilePath, TraceUnsignedBaseType_t uxLineNumber) +{ + TraceBaseType_t i, xLength; + TraceUnsignedBaseType_t uxEntryLineNumber = 0xFFFFFFFF; + static TraceUnsignedBaseType_t uxRecursionGuard = 0; + + if (uxRecursionGuard == 0) + { + /* Recursion can only get here once */ + uxRecursionGuard = 1; + + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ASSERT)) + { + return; + } + + if (pxAssertInfo->xEntry == 0) + { + if (xTraceEntryCreate(&pxAssertInfo->xEntry) == TRC_FAIL) + { + return; + } + } + + xTraceEntryGetState(pxAssertInfo->xEntry, TRC_ASSERT_STATE_INDEX_LINE_NUMBER, &uxEntryLineNumber); + + /* We only save the first ASSERT information */ + if (uxEntryLineNumber == 0) + { + /* Find length */ + for (i = 0; (szFilePath[i] != 0) && (i < 128); i++) {} + + xLength = i; + + /* Find last slash or backslash */ + for (i = xLength - 1; (i >= 0) && ((szFilePath[i] != '\\') && (szFilePath[i] != '/')); i--) {} + + /* We treat the entry as an object and set it's name and state */ + xTraceObjectSetName((TraceObjectHandle_t)pxAssertInfo->xEntry, &szFilePath[i + 1]); + xTraceObjectSetState((TraceObjectHandle_t)pxAssertInfo->xEntry, uxLineNumber); + + xTraceError(TRC_ERROR_ASSERT); + } + } + + xTraceDiagnosticsIncrease(TRC_DIAGNOSTICS_ASSERTS_TRIGGERED); +} + +traceResult xTraceAssertGet(TraceStringHandle_t *pxFileNameStringHandle, TraceUnsignedBaseType_t *puxLineNumber) +{ + TRC_ASSERT(pxFileNameStringHandle != 0); + + TRC_ASSERT(puxLineNumber != 0); + + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ASSERT)) + { + return TRC_FAIL; + } + + *puxLineNumber = 0; + xTraceEntryGetState(pxAssertInfo->xEntry, TRC_ASSERT_STATE_INDEX_LINE_NUMBER, puxLineNumber); + + if (*puxLineNumber == 0) + { + return TRC_FAIL; + } + + /* The string handle can be set to the entry handle */ + *pxFileNameStringHandle = (TraceStringHandle_t)pxAssertInfo->xEntry; + + return TRC_SUCCESS; +} + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcCounter.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcCounter.c new file mode 100644 index 0000000000..4c9f455d30 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcCounter.c @@ -0,0 +1,154 @@ +/* +* Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation of intervals. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#define TRC_COUNTER_VALUE_INDEX 0 +#define TRC_COUNTER_LOWER_LIMIT_INDEX 1 +#define TRC_COUNTER_UPPER_LIMIT_INDEX 2 + +static TraceCounterCallback_t xCallbackFunction; + +traceResult xTraceCounterSetCallback(TraceCounterCallback_t xCallback) +{ + TRC_ASSERT(xCallback != 0); + + xCallbackFunction = xCallback; + + /* We only set this component as initialized when the callback has been set */ + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_COUNTER); + + return TRC_SUCCESS; +} + +traceResult xTraceCounterCreate(const char *szName, TraceBaseType_t xInitialValue, TraceBaseType_t xLowerLimit, TraceBaseType_t xUpperLimit, TraceCounterHandle_t *pxCounterHandle) +{ + TraceObjectHandle_t xObjectHandle; + TraceUnsignedBaseType_t uxStates[3]; + + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_COUNTER)); + + /* This should never fail */ + TRC_ASSERT(pxCounterHandle != 0); + + TRC_ASSERT(xInitialValue >= xLowerLimit && xInitialValue <= xUpperLimit); + + uxStates[TRC_COUNTER_VALUE_INDEX] = xInitialValue; + uxStates[TRC_COUNTER_LOWER_LIMIT_INDEX] = xLowerLimit; + uxStates[TRC_COUNTER_UPPER_LIMIT_INDEX] = xUpperLimit; + + /* We need to check this */ + if (xTraceObjectRegisterInternal(PSF_EVENT_COUNTER_CREATE, 0, szName, 3, uxStates, TRC_ENTRY_OPTION_COUNTER, &xObjectHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + *pxCounterHandle = (TraceIntervalHandle_t)xObjectHandle; + + return TRC_SUCCESS; +} + +traceResult xTraceCounterIncrease(TraceCounterHandle_t xCounterHandle) +{ + return xTraceCounterAdd(xCounterHandle, 1); +} +traceResult xTraceCounterDecrease(TraceCounterHandle_t xCounterHandle) +{ + return xTraceCounterAdd(xCounterHandle, -1); +} + +traceResult xTraceCounterAdd(TraceCounterHandle_t xCounterHandle, TraceBaseType_t xValue) +{ + TraceBaseType_t xCurrent; + + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_COUNTER)); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceCounterGet(xCounterHandle, &xCurrent) == TRC_SUCCESS); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceCounterSet(xCounterHandle, xCurrent + xValue) == TRC_SUCCESS); + + return TRC_SUCCESS; +} + +traceResult xTraceCounterSet(TraceCounterHandle_t xCounterHandle, TraceBaseType_t xValue) +{ + TraceEventHandle_t xEventHandle = 0; + TraceBaseType_t xLowerLimit; + TraceBaseType_t xUpperLimit; + + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_COUNTER)); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState((TraceEntryHandle_t)xCounterHandle, TRC_COUNTER_VALUE_INDEX, (TraceUnsignedBaseType_t)xValue) == TRC_SUCCESS); + + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_COUNTER_CHANGE, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, (void*)xCounterHandle); + xTraceEventAdd32(xEventHandle, (TraceUnsignedBaseType_t)xValue); + xTraceEventEnd(xEventHandle); + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceCounterGetLowerLimit(xCounterHandle, &xLowerLimit) == TRC_SUCCESS); + + if (xValue < xLowerLimit) + { + xCallbackFunction(xCounterHandle); + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceCounterGetUpperLimit(xCounterHandle, &xUpperLimit) == TRC_SUCCESS); + + if (xValue > xUpperLimit) + { + xCallbackFunction(xCounterHandle); + } + + return TRC_SUCCESS; +} + +traceResult xTraceCounterGet(TraceCounterHandle_t xCounterHandle, TraceBaseType_t* pxValue) +{ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_COUNTER)); + + return xTraceEntryGetState((TraceEntryHandle_t)xCounterHandle, TRC_COUNTER_VALUE_INDEX, (TraceUnsignedBaseType_t*)pxValue); +} + +traceResult xTraceCounterGetUpperLimit(TraceCounterHandle_t xCounterHandle, TraceBaseType_t* pxValue) +{ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_COUNTER)); + + return xTraceEntryGetState((TraceEntryHandle_t)xCounterHandle, TRC_COUNTER_UPPER_LIMIT_INDEX, (TraceUnsignedBaseType_t*)pxValue); +} + +traceResult xTraceCounterGetLowerLimit(TraceCounterHandle_t xCounterHandle, TraceBaseType_t* pxValue) +{ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_COUNTER)); + + return xTraceEntryGetState((TraceEntryHandle_t)xCounterHandle, TRC_COUNTER_LOWER_LIMIT_INDEX, (TraceUnsignedBaseType_t*)pxValue); +} + +traceResult xTraceCounterGetName(TraceCounterHandle_t xCounterHandle, const char** pszName) +{ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_COUNTER)); + + return xTraceEntryGetSymbol((TraceEntryHandle_t)xCounterHandle, pszName); +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcDiagnostics.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcDiagnostics.c new file mode 100644 index 0000000000..08683712a2 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcDiagnostics.c @@ -0,0 +1,166 @@ +/* +* Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation of the diagnostics. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +typedef struct TraceDiagnostics +{ + TraceBaseType_t metrics[TRC_DIAGNOSTICS_COUNT]; +} TraceDiagnostics_t; + +static TraceDiagnostics_t *pxDiagnostics; + +traceResult xTraceDiagnosticsInitialize(TraceDiagnosticsBuffer_t *pxBuffer) +{ + uint32_t i; + + TRC_ASSERT_EQUAL_SIZE(TraceDiagnosticsBuffer_t, TraceDiagnostics_t); + + /* This should never fail */ + TRC_ASSERT(pxBuffer != 0); + + pxDiagnostics = (TraceDiagnostics_t*)pxBuffer; + + for (i = 0; i < TRC_DIAGNOSTICS_COUNT; i++) + { + pxDiagnostics->metrics[i] = 0; + } + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_DIAGNOSTICS); + + return TRC_SUCCESS; +} + +traceResult xTraceDiagnosticsGet(TraceDiagnosticsType_t xType, TraceBaseType_t* pxValue) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_DIAGNOSTICS)); + + /* This should never fail */ + TRC_ASSERT((TraceUnsignedBaseType_t)xType < TRC_DIAGNOSTICS_COUNT); + + /* This should never fail */ + TRC_ASSERT(pxValue != 0); + + *pxValue = pxDiagnostics->metrics[(TraceUnsignedBaseType_t)xType]; + + return TRC_SUCCESS; +} + +traceResult xTraceDiagnosticsSet(TraceDiagnosticsType_t xType, TraceBaseType_t xValue) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_DIAGNOSTICS)); + + /* This should never fail */ + TRC_ASSERT((TraceUnsignedBaseType_t)xType < TRC_DIAGNOSTICS_COUNT); + + pxDiagnostics->metrics[(TraceUnsignedBaseType_t)xType] = xValue; + + return TRC_SUCCESS; +} + +traceResult xTraceDiagnosticsAdd(TraceDiagnosticsType_t xType, TraceBaseType_t xValue) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_DIAGNOSTICS)); + + /* This should never fail */ + TRC_ASSERT((TraceUnsignedBaseType_t)xType < TRC_DIAGNOSTICS_COUNT); + + pxDiagnostics->metrics[(TraceUnsignedBaseType_t)xType] += xValue; + + return TRC_SUCCESS; +} + +traceResult xTraceDiagnosticsIncrease(TraceDiagnosticsType_t xType) +{ + return xTraceDiagnosticsAdd(xType, 1); +} + +traceResult xTraceDiagnosticsDecrease(TraceDiagnosticsType_t xType) +{ + return xTraceDiagnosticsAdd(xType, -1); +} + +traceResult xTraceDiagnosticsSetIfHigher(TraceDiagnosticsType_t xType, TraceBaseType_t xValue) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_DIAGNOSTICS)); + + /* This should never fail */ + TRC_ASSERT((TraceUnsignedBaseType_t)xType < TRC_DIAGNOSTICS_COUNT); + + if (xValue > pxDiagnostics->metrics[xType]) + { + pxDiagnostics->metrics[(TraceUnsignedBaseType_t)xType] = xValue; + } + + return TRC_SUCCESS; +} + +traceResult xTraceDiagnosticsSetIfLower(TraceDiagnosticsType_t xType, TraceBaseType_t xValue) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_DIAGNOSTICS)); + + /* This should never fail */ + TRC_ASSERT((TraceUnsignedBaseType_t)xType < TRC_DIAGNOSTICS_COUNT); + + if (xValue < pxDiagnostics->metrics[(TraceUnsignedBaseType_t)xType]) + { + pxDiagnostics->metrics[(TraceUnsignedBaseType_t)xType] = xValue; + } + + return TRC_SUCCESS; +} + +traceResult xTraceDiagnosticsCheckStatus(void) +{ + /* It is probably good if we always check this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_DIAGNOSTICS)) + { + return TRC_FAIL; + } + + if (pxDiagnostics->metrics[TRC_DIAGNOSTICS_ENTRY_SLOTS_NO_ROOM] > 0) + { + xTraceWarning(TRC_WARNING_ENTRY_TABLE_SLOTS); + pxDiagnostics->metrics[TRC_DIAGNOSTICS_ENTRY_SLOTS_NO_ROOM] = 0; + } + + if (pxDiagnostics->metrics[TRC_DIAGNOSTICS_ENTRY_SYMBOL_LONGEST_LENGTH] > (TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH)) + { + xTraceWarning(TRC_WARNING_ENTRY_SYMBOL_MAX_LENGTH); + pxDiagnostics->metrics[TRC_DIAGNOSTICS_ENTRY_SYMBOL_LONGEST_LENGTH] = 0; + } + + if (pxDiagnostics->metrics[TRC_DIAGNOSTICS_BLOB_MAX_BYTES_TRUNCATED] > 0) + { + xTraceWarning(TRC_WARNING_EVENT_SIZE_TRUNCATED); + pxDiagnostics->metrics[TRC_DIAGNOSTICS_BLOB_MAX_BYTES_TRUNCATED] = 0; + } + + if (pxDiagnostics->metrics[TRC_DIAGNOSTICS_STACK_MONITOR_NO_SLOTS] > 0) + { + xTraceWarning(TRC_WARNING_STACKMON_NO_SLOTS); + pxDiagnostics->metrics[TRC_DIAGNOSTICS_STACK_MONITOR_NO_SLOTS] = 0; + } + + return TRC_SUCCESS; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcEntryTable.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcEntryTable.c new file mode 100644 index 0000000000..8bbec98b40 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcEntryTable.c @@ -0,0 +1,429 @@ +/* +* Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation of the entry table. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#define VALIDATE_ENTRY_HANDLE(xEntryHandle) ((((TraceUnsignedBaseType_t)(xEntryHandle) >= (TraceUnsignedBaseType_t)pxEntryTable) && ((TraceUnsignedBaseType_t)(xEntryHandle) < ((TraceUnsignedBaseType_t)pxEntryTable + sizeof(TraceEntryTable_t))))) + +#define GIVE_ENTRY_INDEX(xIndex) xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount] = (xIndex); xIndexTable.uiFreeIndexCount++ + +#define GET_FREE_INDEX_COUNT() xIndexTable.uiFreeIndexCount + +#define CALCULATE_ENTRY_INDEX(xEntryHandle) (TraceEntryIndex_t)(((TraceUnsignedBaseType_t)((TraceUnsignedBaseType_t)(xEntryHandle) - (TraceUnsignedBaseType_t)pxEntryTable) / sizeof(TraceEntry_t))) + +#if (TRC_ENTRY_TABLE_SLOTS > 256) +typedef uint16_t TraceEntryIndex_t; +#else +typedef uint8_t TraceEntryIndex_t; +#endif /* (TRC_CFG_ENTRY_TABLE_SLOTS > 256) */ + +typedef struct EntryIndexTable +{ + TraceEntryIndex_t axFreeIndexes[TRC_ENTRY_TABLE_SLOTS]; + uint32_t uiFreeIndexCount; +} TraceEntryIndexTable_t; + +typedef struct TraceEntryTable +{ + uint32_t uiSlots; + uint32_t uiEntrySymbolLength; + uint32_t uiEntryStateCount; + TraceEntry_t axEntries[TRC_ENTRY_TABLE_SLOTS]; +} TraceEntryTable_t; + +/* Private function definitions */ +traceResult prvEntryIndexInitialize(TraceEntryIndexTable_t *pxIndexTable); +traceResult prvEntryIndexTake(TraceEntryIndex_t *pxIndex); + +/* Variables */ +static TraceEntryTable_t *pxEntryTable; +static TraceEntryIndexTable_t xIndexTable; + +traceResult xTraceEntryTableInitialize(TraceEntryTableBuffer_t *pxBuffer) +{ + uint32_t i, j; + + TRC_ASSERT_EQUAL_SIZE(TraceEntryTableBuffer_t, TraceEntryTable_t); + + /* This should never fail */ + TRC_ASSERT(pxBuffer != 0); + + /* This should never fail */ + TRC_ASSERT((TRC_ENTRY_TABLE_SLOTS) != 0); + + pxEntryTable = (TraceEntryTable_t*)pxBuffer; + + pxEntryTable->uiSlots = TRC_ENTRY_TABLE_SLOTS; + pxEntryTable->uiEntrySymbolLength = TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE; + pxEntryTable->uiEntryStateCount = TRC_ENTRY_TABLE_STATE_COUNT; + + for (i = 0; i < TRC_ENTRY_TABLE_SLOTS; i++) + { + pxEntryTable->axEntries[i].pvAddress = 0; + for (j = 0; j < TRC_ENTRY_TABLE_STATE_COUNT; j++) + { + pxEntryTable->axEntries[i].xStates[j] = 0; + } + pxEntryTable->axEntries[i].szSymbol[0] = 0; + } + + prvEntryIndexInitialize(&xIndexTable); + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY); + + return TRC_SUCCESS; +} + +traceResult xTraceEntryCreate(TraceEntryHandle_t *pxEntryHandle) +{ + uint32_t i; + TraceEntryIndex_t xIndex; + TraceEntry_t *pxEntry; + + TRACE_ALLOC_CRITICAL_SECTION(); + + /* We always check this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)) + { + return TRC_FAIL; + } + + /* This should never fail */ + TRC_ASSERT(pxEntryHandle != 0); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (prvEntryIndexTake(&xIndex) != TRC_SUCCESS) + { + xTraceDiagnosticsIncrease(TRC_DIAGNOSTICS_ENTRY_SLOTS_NO_ROOM); + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + + pxEntry = &pxEntryTable->axEntries[xIndex]; + + pxEntry->pvAddress = (void*)pxEntry; /* We set a temporary address */ + + for (i = 0; i < TRC_ENTRY_TABLE_STATE_COUNT; i++) + { + pxEntry->xStates[i] = 0; + } + + pxEntry->uiOptions = 0; + pxEntry->szSymbol[0] = 0; + + *pxEntryHandle = (TraceEntryHandle_t)pxEntry; + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_SUCCESS; +} + +traceResult xTraceEntryDelete(TraceEntryHandle_t xEntryHandle) +{ + TraceEntryIndex_t xIndex; + + TRACE_ALLOC_CRITICAL_SECTION(); + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* This should never fail */ + TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); + + /* Calculate the index based on the entry address */ + /* Does not need to be locked. */ + /* This should never fail */ + xIndex = CALCULATE_ENTRY_INDEX(xEntryHandle); + + TRC_ASSERT(xIndex < TRC_ENTRY_TABLE_SLOTS); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (((TraceEntry_t*)xEntryHandle)->pvAddress == 0) + { + /* Someone else has deleted this already? */ + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + + /* A valid address, so we assume it is OK. */ + /* For good measure, we clear the address field */ + ((TraceEntry_t*)xEntryHandle)->pvAddress = 0; + + /* Give back the index */ + GIVE_ENTRY_INDEX(xIndex); + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_SUCCESS; +} + +traceResult xTraceEntryFind(void* pvAddress, TraceEntryHandle_t* pxEntryHandle) +{ + uint32_t i; + TraceEntry_t* pxEntry; + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* This should never fail */ + TRC_ASSERT(pxEntryHandle != 0); + + /* This should never fail */ + TRC_ASSERT(pvAddress != 0); + + for (i = 0; i < TRC_ENTRY_TABLE_SLOTS; i++) + { + pxEntry = (TraceEntry_t*)(((uint32_t)pxEntryTable->axEntries) + (i * sizeof(TraceEntry_t))); + if (pxEntry->pvAddress == pvAddress) + { + *pxEntryHandle = (TraceEntryHandle_t)pxEntry; + + return TRC_SUCCESS; + } + } + + return TRC_FAIL; +} + +traceResult xTraceEntrySetSymbol(TraceEntryHandle_t xEntryHandle, const char* szSymbol) +{ + uint32_t i; + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + if (szSymbol == 0) + { + szSymbol = ""; + } + + /* Does not need to be locked. */ + /* This should never fail */ + TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); + + for (i = 0; i < (TRC_ENTRY_TABLE_SYMBOL_LENGTH); i++) + { + ((TraceEntry_t*)xEntryHandle)->szSymbol[i] = szSymbol[i]; /* We do this first to ensure we also get the 0 termination, if there is one */ + + if (szSymbol[i] == 0) + { + break; + } + } + + /* Check the length of "name", if longer than TRC_ENTRY_TABLE_SYMBOL_LENGTH */ + while ((szSymbol[i] != 0) && i < 128) + { + i++; + } + + /* Remember the longest symbol name */ + xTraceDiagnosticsSetIfHigher(TRC_DIAGNOSTICS_ENTRY_SYMBOL_LONGEST_LENGTH, i); + + return TRC_SUCCESS; +} + +traceResult xTraceEntryGetCount(uint32_t* puiCount) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* This should never fail */ + TRC_ASSERT(puiCount != 0); + + *puiCount = TRC_ENTRY_TABLE_SLOTS - GET_FREE_INDEX_COUNT(); + + return TRC_SUCCESS; +} + +traceResult xTraceEntryGetAtIndex(uint32_t index, TraceEntryHandle_t* pxEntryHandle) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* This should never fail */ + TRC_ASSERT(index < TRC_ENTRY_TABLE_SLOTS); + + /* This should never fail */ + TRC_ASSERT(pxEntryHandle != 0); + + *pxEntryHandle = (TraceEntryHandle_t)((uint32_t)(pxEntryTable->axEntries) + (index * sizeof(TraceEntry_t))); + + return TRC_SUCCESS; +} + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +traceResult xTraceEntryCreateWithAddress(void* pvAddress, TraceEntryHandle_t* pxEntryHandle) +{ + /* This should never fail */ + TRC_ASSERT(pvAddress != 0); + + return TRC_ENTRY_CREATE_WITH_ADDRESS(pvAddress, pxEntryHandle); +} + +traceResult xTraceEntrySetState(TraceEntryHandle_t xEntryHandle, uint32_t uiStateIndex, TraceUnsignedBaseType_t uxState) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* This should never fail */ + TRC_ASSERT(uiStateIndex < (TRC_ENTRY_TABLE_STATE_COUNT)); + + /* This should never fail */ + TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); + + return TRC_ENTRY_SET_STATE(xEntryHandle, uiStateIndex, uxState); +} + +traceResult xTraceEntrySetOptions(TraceEntryHandle_t xEntryHandle, uint32_t uiMask) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* Does not need to be locked. */ + /* This should never fail */ + TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); + + return TRC_ENTRY_SET_OPTIONS(xEntryHandle, uiMask); +} + +traceResult xTraceEntryClearOptions(TraceEntryHandle_t xEntryHandle, uint32_t uiMask) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* Does not need to be locked. */ + /* This should never fail */ + TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); + + return TRC_ENTRY_CLEAR_OPTIONS(xEntryHandle, uiMask); +} + +traceResult xTraceEntryGetAddress(TraceEntryHandle_t xEntryHandle, void **ppvAddress) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* This should never fail */ + TRC_ASSERT(ppvAddress != 0); + + /* Does not need to be locked. */ + /* This should never fail */ + TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); + + return TRC_ENTRY_GET_ADDRESS(xEntryHandle, ppvAddress); +} + +traceResult xTraceEntryGetSymbol(TraceEntryHandle_t xEntryHandle, const char** pszSymbol) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* This should never fail */ + TRC_ASSERT(pszSymbol != 0); + + /* Does not need to be locked. */ + /* This should never fail */ + TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); + + return TRC_ENTRY_GET_SYMBOL(xEntryHandle, pszSymbol); +} + +traceResult xTraceEntryGetState(TraceEntryHandle_t xEntryHandle, uint32_t uiStateIndex, TraceUnsignedBaseType_t *puxState) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* This should never fail */ + TRC_ASSERT(puxState != 0); + + /* This should never fail */ + TRC_ASSERT(uiStateIndex < TRC_ENTRY_TABLE_STATE_COUNT); + + /* Does not need to be locked. */ + /* This should never fail */ + TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); + + return TRC_ENTRY_GET_STATE(xEntryHandle, uiStateIndex, puxState); +} + +traceResult xTraceEntryGetOptions(TraceEntryHandle_t xEntryHandle, uint32_t *puiOptions) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY)); + + /* This should never fail */ + TRC_ASSERT(puiOptions != 0); + + /* Does not need to be locked. */ + /* This should never fail */ + TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); + + return TRC_ENTRY_GET_OPTIONS(xEntryHandle, puiOptions); +} + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +/* PRIVATE FUNCTIONS */ + +traceResult prvEntryIndexInitialize(TraceEntryIndexTable_t* pxIndexTable) +{ + uint32_t i; + + for (i = 0; i < TRC_ENTRY_TABLE_SLOTS; i++) + { + pxIndexTable->axFreeIndexes[i] = (TraceEntryIndex_t)i; + } + + xIndexTable.uiFreeIndexCount = TRC_ENTRY_TABLE_SLOTS; + + return TRC_SUCCESS; +} + +traceResult prvEntryIndexTake(TraceEntryIndex_t *pxIndex) +{ + /* Critical Section must be active! */ + TraceEntryIndex_t xIndex; + + if (xIndexTable.uiFreeIndexCount == 0) + { + return TRC_FAIL; + } + + /* Always take the first item */ + xIndex = xIndexTable.axFreeIndexes[0]; + xIndexTable.uiFreeIndexCount--; + + /* Move the last item to the first slot, to avoid holes */ + xIndexTable.axFreeIndexes[0] = xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount]; + +#if (TRC_ENTRY_TABLE_SLOTS > 256) + xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount] = UINT16_MAX; +#else + xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount] = UINT8_MAX; +#endif + + *pxIndex = xIndex; + return TRC_SUCCESS; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcError.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcError.c new file mode 100644 index 0000000000..2a6b2588c4 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcError.c @@ -0,0 +1,339 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for errors. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +/* We skip the slot for TRC_ERROR_NONE so error code 1 is the first bit */ +#define GET_ERROR_WARNING_FLAG(errorCode) (pxErrorInfo->uiErrorAndWarningFlags & (1 << ((errorCode) - 1))) +#define SET_ERROR_WARNING_FLAG(errorCode) (pxErrorInfo->uiErrorAndWarningFlags |= (1 << ((errorCode) - 1))) + +traceResult prvTraceErrorPrint(uint32_t uiErrorCode); +traceResult prvTraceErrorGetDescription(uint32_t uiErrorCode, const char** pszDesc); + +typedef struct TraceErrorInfo +{ + uint32_t uiErrorAndWarningFlags; + uint32_t uiErrorCode; + TraceStringHandle_t xWarningChannel; +} TraceErrorInfo_t; + +static TraceErrorInfo_t* pxErrorInfo; + +traceResult xTraceErrorInitialize(TraceErrorBuffer_t* pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceErrorBuffer_t, TraceErrorInfo_t); + + /* This should never fail */ + TRC_ASSERT(pxBuffer != 0); + + pxErrorInfo = (TraceErrorInfo_t*)pxBuffer; + + pxErrorInfo->uiErrorAndWarningFlags = 0; + pxErrorInfo->uiErrorCode = 0; + pxErrorInfo->xWarningChannel = 0; + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_ERROR); + + return TRC_SUCCESS; +} + +/* Called on warnings, when the recording can continue. */ +traceResult xTraceWarning(uint32_t uiErrorCode) +{ + /* Probably good to verify this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR)) + { + /* If not initialized */ + return TRC_FAIL; + } + + if (GET_ERROR_WARNING_FLAG(uiErrorCode) == 0) + { + /* Will never reach this point more than once per warning type, since we verify if uiErrorAndWarningFlags[uiErrorCode] has already been set */ + SET_ERROR_WARNING_FLAG(uiErrorCode); + + prvTraceErrorPrint(uiErrorCode); + } + + return TRC_SUCCESS; +} + +/* Called on critical errors in the recorder. Stops the recorder! */ +traceResult xTraceError(uint32_t uiErrorCode) +{ + /* Probably good to verify this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR)) + { + return TRC_FAIL; + } + + if (pxErrorInfo->uiErrorCode == TRC_ERROR_NONE) + { + /* Will never reach this point more than once, since we verify if uiErrorCode has already been set */ + SET_ERROR_WARNING_FLAG(uiErrorCode); + pxErrorInfo->uiErrorCode = uiErrorCode; + + if (prvTraceErrorPrint(uiErrorCode) == TRC_FAIL) + { + xTraceDisable(); + + return TRC_FAIL; + } + + xTracePrint(pxErrorInfo->xWarningChannel, "Recorder stopped in xTraceError(...)!"); + xTraceDisable(); + } + + return TRC_SUCCESS; +} + +/******************************************************************************* + * xTraceErrorGetLast + * + * Returns the last error or warning, as a string, or NULL if none. + *****************************************************************************/ +traceResult xTraceErrorGetLast(const char **pszError) +{ + /* Probably good to verify this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR)) + { + return TRC_FAIL; + } + + /* This should never fail */ + TRC_ASSERT(pszError != 0); + + return prvTraceErrorGetDescription(pxErrorInfo->uiErrorCode, pszError); +} + +/******************************************************************************* + * xTraceErrorClear + * + * Clears any errors. + *****************************************************************************/ +traceResult xTraceErrorClear(void) +{ + /* Probably good to verify this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ERROR)) + { + /* If not initialized */ + return TRC_FAIL; + } + + pxErrorInfo->uiErrorCode = TRC_ERROR_NONE; + + return TRC_SUCCESS; +} + +/* Returns the error or warning, as a string, or NULL if none. */ +traceResult prvTraceErrorPrint(uint32_t uiErrorCode) +{ + const char* szDesc; + /* Note: the error messages are short, in order to fit in a User Event. + Instead, the users can read more in the below comments.*/ + + if (pxErrorInfo->xWarningChannel == 0) + { + /* 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". + */ + if (xTraceStringRegister("#WFR", &pxErrorInfo->xWarningChannel) == TRC_FAIL) + { + return TRC_FAIL; + } + } + + prvTraceErrorGetDescription(uiErrorCode, &szDesc); + + switch (uiErrorCode) + { + case TRC_WARNING_ENTRY_TABLE_SLOTS: + case TRC_WARNING_ENTRY_SYMBOL_MAX_LENGTH: + case TRC_WARNING_EVENT_SIZE_TRUNCATED: + case TRC_WARNING_STREAM_PORT_READ: + case TRC_WARNING_STREAM_PORT_WRITE: + case TRC_WARNING_STREAM_PORT_INITIAL_BLOCKING: + case TRC_WARNING_STACKMON_NO_SLOTS: + case TRC_ERROR_STREAM_PORT_WRITE: + case TRC_ERROR_EVENT_CODE_TOO_LARGE: + case TRC_ERROR_ISR_NESTING_OVERFLOW: + case TRC_ERROR_DWT_NOT_SUPPORTED: + case TRC_ERROR_DWT_CYCCNT_NOT_SUPPORTED: + case TRC_ERROR_TZCTRLTASK_NOT_CREATED: + xTracePrint(pxErrorInfo->xWarningChannel, szDesc); + break; + + case TRC_ERROR_ASSERT: + /* A TRC_ASSERT has triggered */ + { + TraceUnsignedBaseType_t uxLineNumber; + TraceStringHandle_t xFileName; + + if (xTraceAssertGet(&xFileName, &uxLineNumber) == TRC_FAIL) + { + return TRC_FAIL; + } + + xTracePrintF(pxErrorInfo->xWarningChannel, szDesc, xFileName, (uint32_t)uxLineNumber); + + return TRC_SUCCESS; + } + + default: + /* No error, or an unknown error occurred */ + xTracePrintF(pxErrorInfo->xWarningChannel, "Unknown error code: 0x%08X", uiErrorCode); + + return TRC_FAIL; + } + + return TRC_SUCCESS; +} + +/* Returns the error or warning, as a string, or NULL if none. */ +traceResult prvTraceErrorGetDescription(uint32_t uiErrorCode, const char** pszDesc) +{ + /* 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 (uiErrorCode) + { + case TRC_ERROR_NONE: + return TRC_FAIL; + + case TRC_WARNING_ENTRY_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_ENTRY_TABLE_SLOTS by at least that value. */ + + *pszDesc = "Exceeded TRC_CFG_ENTRY_TABLE_SLOTS"; + break; + + case TRC_WARNING_ENTRY_SYMBOL_MAX_LENGTH: + /* A symbol name exceeded TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH in length. + Make sure the symbol names are at most TRC_CFG_SYMBOL_MAX_LENGTH, + or inspect uiLongestSymbolName in trcEntryTable and increase + TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH to at least this value. */ + + *pszDesc = "Exceeded TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH"; + break; + + case TRC_WARNING_EVENT_SIZE_TRUNCATED: + /* Some arguments was longer than the maximum payload size + and has been truncated by "uiMaxBytesTruncated" bytes. + + This usually happens for the following functions: + - xTracePrint + - xTracePrintF + - xTraceStringRegister + + A trace event may store a maximum of 56 bytes payload, including + data arguments and string characters. */ + + *pszDesc = "Event size exceeded"; + break; + + case TRC_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. */ + + *pszDesc = "TRC_STREAM_PORT_READ_DATA returned error"; + break; + + case TRC_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. */ + + *pszDesc = "TRC_STREAM_PORT_WRITE_DATA returned error"; + break; + + case TRC_WARNING_STREAM_PORT_INITIAL_BLOCKING: + /* Blocking occurred during xTraceEnable. This happens if the trace buffer is + smaller than the initial transmission (trace header, object table, and symbol table). */ + + *pszDesc = "Blocking in xTraceEnable"; + break; + + case TRC_WARNING_STACKMON_NO_SLOTS: + /* Some tasks did not fit in the stack monitor. Increase the slot count. */ + + *pszDesc = "No slots left in Stack Monitor"; + break; + + case TRC_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. */ + + *pszDesc = "TRC_STREAM_PORT_WRITE_DATA returned error"; + break; + + case TRC_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.*/ + + *pszDesc = "Invalid event code"; + break; + + case TRC_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. */ + + *pszDesc = "Exceeded ISR nesting"; + break; + + case TRC_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".*/ + + *pszDesc = "DWT not supported"; + break; + + case TRC_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".*/ + + *pszDesc = "DWT_CYCCNT not supported"; + break; + + case TRC_ERROR_TZCTRLTASK_NOT_CREATED: + /* xTraceEnable failed creating the trace control task (TzCtrl) - incorrect parameters (priority?) + or insufficient heap size? */ + *pszDesc = "Could not create TzCtrl"; + break; + + case TRC_ERROR_ASSERT: + /* A TRC_ASSERT has triggered */ + *pszDesc = "ASSERT: %s (%d)"; + break; + + default: + /* An unknown error occurred */ + *pszDesc = "Unknown error code: 0x%08X"; + break; + } + + return TRC_SUCCESS; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcEvent.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcEvent.c new file mode 100644 index 0000000000..87d80feb63 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcEvent.c @@ -0,0 +1,407 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for events. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#define VERIFY_EVENT_SIZE(i) \ + if ((i) > (TRC_MAX_BLOB_SIZE)) \ + { \ + xTraceDiagnosticsSetIfHigher(TRC_DIAGNOSTICS_BLOB_MAX_BYTES_TRUNCATED, (TraceUnsignedBaseType_t)((i) - (TRC_MAX_BLOB_SIZE))); \ + (i) = TRC_MAX_BLOB_SIZE; \ + } + +TraceEventDataTable_t *pxTraceEventDataTable; + +int32_t DUMMY_iTraceBytesCommitted; + +TRACE_ALLOC_CRITICAL_SECTION(); + +traceResult xTraceEventInitialize(TraceEventDataBuffer_t* pxBuffer) +{ + TraceCoreEventData_t* pxCoreEventData; + uint32_t i, j; + + TRC_ASSERT_EQUAL_SIZE(TraceEventDataBuffer_t, TraceEventDataTable_t); + + /* This should never fail */ + TRC_ASSERT(pxBuffer != 0); + + pxTraceEventDataTable = (TraceEventDataTable_t*)pxBuffer; + + for (i = 0; i < TRC_CFG_CORE_COUNT; i++) + { + pxCoreEventData = &pxTraceEventDataTable->coreEventData[i]; + + pxCoreEventData->eventCounter = 0; + + for (j = 0; j < (TRC_CFG_MAX_ISR_NESTING) + 1; j++) + { + RESET_EVENT_DATA(&pxCoreEventData->eventData[j]); + } + } + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_EVENT); + + return TRC_SUCCESS; +} + +traceResult xTraceEventBeginRawOffline(uint32_t uiSize, TraceEventHandle_t* pxEventHandle) +{ + TraceEventData_t* pxEventData; + int32_t ISR_nesting; + + /* We need to check this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)) + { + return TRC_FAIL; + } + + /* This should never fail */ + TRC_ASSERT(pxEventHandle != 0); + + TRACE_ENTER_CRITICAL_SECTION(); + + xTraceISRGetCurrentNesting(&ISR_nesting); + + /* We add 1 since xTraceISRGetCurrentNesting(...) returns -1 if no ISR is active */ + pxEventData = &pxTraceEventDataTable->coreEventData[TRC_CFG_GET_CURRENT_CORE()].eventData[ISR_nesting + 1]; + + /* This should never fail */ + TRC_ASSERT_CUSTOM_ON_FAIL(pxEventData->pvBlob == 0, TRACE_EXIT_CRITICAL_SECTION(); return TRC_FAIL; ); + + VERIFY_EVENT_SIZE(uiSize); + + pxEventData->size = ((uiSize + (sizeof(uint32_t) - 1)) / sizeof(uint32_t)) * sizeof(uint32_t); /* 4-byte align */ + + pxEventData->offset = 0; + + /* This can fail and we should handle it */ + if (xTraceStreamPortAllocate(pxEventData->size, &pxEventData->pvBlob) == TRC_FAIL) + { + TRACE_EXIT_CRITICAL_SECTION(); + return TRC_FAIL; + } + + *pxEventHandle = (TraceEventHandle_t)pxEventData; + + return TRC_SUCCESS; +} + +traceResult xTraceEventBeginRawOfflineBlocking(uint32_t uiSize, TraceEventHandle_t* pxEventHandle) +{ + TraceEventData_t* pxEventData; + int32_t ISR_nesting; + uint32_t uiAttempts = 0; + + /* We need to check this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)) + { + return TRC_FAIL; + } + + /* This should never fail */ + TRC_ASSERT(pxEventHandle != 0); + + TRACE_ENTER_CRITICAL_SECTION(); + + xTraceGetCurrentISRNesting(&ISR_nesting); + + /* We add 1 since xTraceISRGetCurrentNesting(...) returns -1 if no ISR is active */ + pxEventData = &pxTraceEventDataTable->coreEventData[TRC_CFG_GET_CURRENT_CORE()].eventData[ISR_nesting + 1]; + + /* This should never fail */ + TRC_ASSERT_CUSTOM_ON_FAIL(pxEventData->pvBlob == 0, TRACE_EXIT_CRITICAL_SECTION(); return TRC_FAIL; ); + + VERIFY_EVENT_SIZE(uiSize); + + pxEventData->size = ((uiSize + (sizeof(uint32_t) - 1)) / sizeof(uint32_t)) * sizeof(uint32_t); /* 4-byte align */ + + pxEventData->offset = 0; + + /* This can fail and we should handle it */ + while (xTraceStreamPortAllocate(pxEventData->size, &pxEventData->pvBlob) != TRC_SUCCESS) + { + uiAttempts++; + } + + *pxEventHandle = (TraceEventHandle_t)pxEventData; + + return TRC_SUCCESS; +} + +traceResult xTraceEventEndOffline(TraceEventHandle_t xEventHandle) +{ + int32_t iBytesCommitted; + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(((TraceEventData_t*)xEventHandle)->pvBlob != 0); + + xTraceStreamPortCommit(((TraceEventData_t*)xEventHandle)->pvBlob, ((TraceEventData_t*)xEventHandle)->size, &iBytesCommitted); + + RESET_EVENT_DATA((TraceEventData_t*)xEventHandle); + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_SUCCESS; +} + +traceResult xTraceEventEndOfflineBlocking(TraceEventHandle_t xEventHandle) +{ + TraceEventData_t* pxEventData = (TraceEventData_t*)xEventHandle; + int32_t iBytesCommitted; + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(pxEventData != 0); + + while (pxEventData->size > 0) + { + iBytesCommitted = 0; + xTraceStreamPortCommit(pxEventData->pvBlob, pxEventData->size, &iBytesCommitted); + + pxEventData->size -= iBytesCommitted; + pxEventData->pvBlob = ((uint8_t*)pxEventData->pvBlob) + iBytesCommitted; + } + + RESET_EVENT_DATA(pxEventData); + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_SUCCESS; +} + +traceResult xTraceEventAddData(TraceEventHandle_t xEventHandle, void* pvData, uint32_t uiSize) +{ + uint32_t i; + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(pvData != 0); + + /* This should never fail */ + TRC_ASSERT(((TraceEventData_t*)xEventHandle)->offset + uiSize <= ((TraceEventData_t*)xEventHandle)->size); + + for (i = 0; i < uiSize; i++) + { + TRC_EVENT_ADD_8(xEventHandle, ((uint8_t*)pvData)[i]); + } + + return TRC_SUCCESS; +} + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +traceResult xTraceEventGetSize(void *pvAddress, uint32_t* puiSize) +{ + /* This should never fail */ + TRC_ASSERT(pvAddress != 0); + + /* This should never fail */ + TRC_ASSERT(puiSize != 0); + + /* This should never fail */ + TRC_ASSERT((sizeof(TraceBaseEvent_t) + (TRC_EVENT_GET_PARAM_COUNT(((TraceBaseEvent_t*)pvAddress)->EventID)) * sizeof(uint32_t)) <= TRC_MAX_BLOB_SIZE); + + return TRC_EVENT_GET_SIZE(pvAddress, puiSize); +} + +traceResult xTraceEventGetRawData(TraceEventHandle_t xEventHandle, uint32_t uiOffset, uint32_t uiSize, void** ppvData) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(ppvData != 0); + + /* This should never fail */ + TRC_ASSERT(uiOffset + uiSize <= ((TraceEventData_t*)xEventHandle)->size); + + return TRC_EVENT_GET_RAW_DATA(xEventHandle, uiOffset, uiSize, ppvData); +} + +traceResult xTraceEventGetPayload(TraceEventHandle_t xEventHandle, uint32_t uiOffset, uint32_t uiSize, void** ppvData) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(ppvData != 0); + + /* This should never fail */ + TRC_ASSERT(uiOffset + uiSize <= ((TraceEventData_t*)xEventHandle)->size); + + return TRC_EVENT_GET_PAYLOAD(xEventHandle, uiOffset, uiSize, ppvData); +} + +traceResult xTraceEventPayloadRemaining(TraceEventHandle_t xEventHandle, uint32_t* puiValue) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(puiValue != 0); + + /* This should never fail */ + TRC_ASSERT(((TraceEventData_t*)xEventHandle)->pvBlob != 0); + + return TRC_EVENT_PAYLOAD_REMAINING(xEventHandle, puiValue); +} + +traceResult xTraceEventPayloadUsed(TraceEventHandle_t xEventHandle, uint32_t* puiValue) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(puiValue != 0); + + /* This should never fail */ + TRC_ASSERT(((TraceEventData_t*)xEventHandle)->pvBlob != 0); + + return TRC_EVENT_PAYLOAD_USED(xEventHandle, puiValue); +} + +traceResult xTraceEventPayloadSize(TraceEventHandle_t xEventHandle, uint32_t* puiValue) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(puiValue != 0); + + /* This should never fail */ + TRC_ASSERT(((TraceEventData_t*)xEventHandle)->pvBlob != 0); + + return TRC_EVENT_PAYLOAD_SIZE(xEventHandle, puiValue); +} + +traceResult xTraceEventAddPointer(TraceEventHandle_t xEventHandle, void* pvAddress) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(((TraceEventData_t*)xEventHandle)->offset + sizeof(void*) <= ((TraceEventData_t*)xEventHandle)->size); + + /* Make sure we are writing at void* aligned offset */ + /* This should never fail */ + TRC_ASSERT((((TraceEventData_t*)xEventHandle)->offset & (sizeof(void*) - 1)) == 0); + + return TRC_EVENT_ADD_POINTER(xEventHandle, pvAddress); +} + +traceResult xTraceEventAddUnsignedBaseType(TraceEventHandle_t xEventHandle, TraceUnsignedBaseType_t uxValue) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(((TraceEventData_t*)xEventHandle)->offset + sizeof(TraceUnsignedBaseType_t) <= ((TraceEventData_t*)xEventHandle)->size); + + /* Make sure we are writing at TraceUnsignedBaseType_t aligned offset */ + /* This should never fail */ + TRC_ASSERT((((TraceEventData_t*)xEventHandle)->offset & (sizeof(TraceUnsignedBaseType_t) - 1)) == 0); + + return TRC_EVENT_ADD_UNSIGNED_BASE_TYPE(xEventHandle, uxValue); +} + +traceResult xTraceEventAdd32(TraceEventHandle_t xEventHandle, uint32_t value) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(((TraceEventData_t*)xEventHandle)->offset + sizeof(uint32_t) <= ((TraceEventData_t*)xEventHandle)->size); + + /* Make sure we are writing at 32-bit aligned offset */ + /* This should never fail */ + TRC_ASSERT((((TraceEventData_t*)xEventHandle)->offset & 3) == 0); + + return TRC_EVENT_ADD_32(xEventHandle, value); +} + +traceResult xTraceEventAdd16(TraceEventHandle_t xEventHandle, uint16_t value) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(((TraceEventData_t*)xEventHandle)->offset + sizeof(uint16_t) <= ((TraceEventData_t*)xEventHandle)->size); + + /* Make sure we are writing at 16-bit aligned offset */ + /* This should never fail */ + TRC_ASSERT((((TraceEventData_t*)xEventHandle)->offset & 1) == 0); + + return TRC_EVENT_ADD_16(xEventHandle, value); +} + +traceResult xTraceEventAdd8(TraceEventHandle_t xEventHandle, uint8_t value) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_EVENT)); + + /* This should never fail */ + TRC_ASSERT(xEventHandle != 0); + + /* This should never fail */ + TRC_ASSERT(((TraceEventData_t*)xEventHandle)->offset + sizeof(uint8_t) <= ((TraceEventData_t*)xEventHandle)->size); + + return TRC_EVENT_ADD_8(xEventHandle, value); +} + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcEventBuffer.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcEventBuffer.c new file mode 100644 index 0000000000..d236b983a6 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcEventBuffer.c @@ -0,0 +1,256 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for the event buffer. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +traceResult xTraceEventBufferInitialize(TraceEventBuffer_t* pxTraceEventBuffer, uint32_t uiOptions, + uint8_t* puiBuffer, uint32_t uiSize) +{ + /* This should never fail */ + TRC_ASSERT(pxTraceEventBuffer != 0); + + /* This should never fail */ + TRC_ASSERT(puiBuffer != 0); + + pxTraceEventBuffer->uiOptions = uiOptions; + pxTraceEventBuffer->uiHead = 0; + pxTraceEventBuffer->uiTail = 0; + pxTraceEventBuffer->uiSize = uiSize; + pxTraceEventBuffer->uiFree = uiSize; + pxTraceEventBuffer->puiBuffer = puiBuffer; + pxTraceEventBuffer->uiTimerWraparounds = 0; + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_EVENT_BUFFER); + + return TRC_SUCCESS; +} + +/** + * @brief Pops the oldest event from the Event Buffer. + * + * @param[in] pxTraceEventBuffer Pointer to initialized trace event buffer. + * + * @retval TRC_FAIL Failure + * @retval TRC_SUCCESS Success + */ +static traceResult prvTraceEventBufferPop(TraceEventBuffer_t *pxTraceEventBuffer) +{ + uint32_t uiFreeSize = 0; + + /* Get size of event we are freeing */ + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEventGetSize(((void*)&(pxTraceEventBuffer->puiBuffer[pxTraceEventBuffer->uiTail])), &uiFreeSize) == TRC_SUCCESS); + + pxTraceEventBuffer->uiFree += uiFreeSize; + + /* Update tail to point to the new last event */ + pxTraceEventBuffer->uiTail = (pxTraceEventBuffer->uiTail + uiFreeSize) % pxTraceEventBuffer->uiSize; + + return TRC_SUCCESS; +} + +traceResult xTraceEventBufferPush(TraceEventBuffer_t *pxTraceEventBuffer, void *pxData, uint32_t uiDataSize, int32_t *piBytesWritten) +{ + uint32_t uiBufferSize; + + /* This should never fail */ + TRC_ASSERT(pxTraceEventBuffer != 0); + + /* This should never fail */ + TRC_ASSERT(pxData != 0); + + uiBufferSize = pxTraceEventBuffer->uiSize; + + /* Check if the data size is larger than the buffer */ + /* This should never fail */ + TRC_ASSERT(uiDataSize <= uiBufferSize); + + /* Check byte alignment */ + /* This should never fail */ + TRC_ASSERT((uiDataSize % 4) == 0); + + /* Ensure bytes written start at 0 */ + /* This should never fail */ + TRC_ASSERT(piBytesWritten != 0); + + *piBytesWritten = 0; + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceTimestampGetWraparounds(&pxTraceEventBuffer->uiTimerWraparounds) == TRC_SUCCESS); + + /* In ring buffer mode we cannot provide lock free access since the producer modified + * the head and tail variables in the same call. This option is only safe when used + * with an internal buffer (streaming snapshot) which no consumer accesses. + */ + switch (pxTraceEventBuffer->uiOptions) + { + case TRC_EVENT_BUFFER_OPTION_OVERWRITE: + { + uint32_t uiHead = pxTraceEventBuffer->uiHead; + + /* If there isn't enough space in the buffer pop events until there is */ + while (pxTraceEventBuffer->uiFree < uiDataSize) + { + prvTraceEventBufferPop(pxTraceEventBuffer); + } + + /* Copy data */ + if ((uiBufferSize - uiHead) > uiDataSize) + { + TRC_MEMCPY(&pxTraceEventBuffer->puiBuffer[uiHead], pxData, uiDataSize); + } + else + { + TRC_MEMCPY(&pxTraceEventBuffer->puiBuffer[uiHead], pxData, uiBufferSize - uiHead); + TRC_MEMCPY(pxTraceEventBuffer->puiBuffer, + (void*)(&((uint8_t*)pxData)[(uiBufferSize - uiHead)]), + uiDataSize - (uiBufferSize - uiHead)); + } + + pxTraceEventBuffer->uiFree -= uiDataSize; + + pxTraceEventBuffer->uiHead = (uiHead + uiDataSize) % uiBufferSize; + + *piBytesWritten = uiDataSize; + + break; + } + + case TRC_EVENT_BUFFER_OPTION_SKIP: + { + /* Since a consumer could potentially update tail (free) during the procedure + * we have to save it here to avoid problems with the push algorithm. + */ + uint32_t uiHead = pxTraceEventBuffer->uiHead; + uint32_t uiTail = pxTraceEventBuffer->uiTail; + + if (uiHead >= uiTail) + { + uint32_t uiFreeSpace = (uiBufferSize - uiHead - sizeof(uint32_t)) + uiTail; + + if (uiFreeSpace < uiDataSize) + { + *piBytesWritten = 0; + + return TRC_SUCCESS; + } + + /* Copy data */ + if ((uiBufferSize - uiHead) > uiDataSize) + { + TRC_MEMCPY(&pxTraceEventBuffer->puiBuffer[pxTraceEventBuffer->uiHead], pxData, uiDataSize); + } + else + { + TRC_MEMCPY(&pxTraceEventBuffer->puiBuffer[uiHead], pxData, uiBufferSize - uiHead); + TRC_MEMCPY(pxTraceEventBuffer->puiBuffer, + (void*)(&((uint8_t*)pxData)[(uiBufferSize - uiHead)]), + uiDataSize - (uiBufferSize - uiHead)); + } + + pxTraceEventBuffer->uiHead = (uiHead + uiDataSize) % uiBufferSize; + } + else + { + uint32_t uiFreeSpace = uiTail - uiHead - sizeof(uint32_t); + + if (uiFreeSpace < uiDataSize) + { + *piBytesWritten = 0; + + return TRC_SUCCESS; + } + + /* Copy data */ + TRC_MEMCPY(&pxTraceEventBuffer->puiBuffer[pxTraceEventBuffer->uiHead], pxData, uiDataSize); + + pxTraceEventBuffer->uiHead = (uiHead + uiDataSize); + } + + *piBytesWritten = uiDataSize; + + break; + } + + default: + { + return TRC_FAIL; + } + } + + return TRC_SUCCESS; +} + +traceResult xTraceEventBufferTransfer(TraceEventBuffer_t* pxTraceEventBuffer, int32_t* piBytesWritten) +{ + int32_t iBytesWritten = 0; + int32_t iSumBytesWritten = 0; + uint32_t uiHead; + uint32_t uiTail; + + /* This should never fail */ + TRC_ASSERT(pxTraceEventBuffer != 0); + + /* This should never fail */ + TRC_ASSERT(piBytesWritten != 0); + + uiHead = pxTraceEventBuffer->uiHead; + uiTail = pxTraceEventBuffer->uiTail; + + /* Check if core event buffer is empty */ + if (uiHead == uiTail) + { + return TRC_SUCCESS; + } + + /* Check if we can do a direct write or if we have to handle wrapping */ + if (uiHead > uiTail) + { + xTraceStreamPortWriteData(&pxTraceEventBuffer->puiBuffer[uiTail], (uiHead - uiTail), &iBytesWritten); + + pxTraceEventBuffer->uiTail = uiHead; + } + else + { + xTraceStreamPortWriteData(&pxTraceEventBuffer->puiBuffer[uiTail], (pxTraceEventBuffer->uiSize - uiTail), &iBytesWritten); + + iSumBytesWritten += iBytesWritten; + + xTraceStreamPortWriteData(pxTraceEventBuffer->puiBuffer, uiHead, &iBytesWritten); + + pxTraceEventBuffer->uiTail = uiHead; + } + + iSumBytesWritten += iBytesWritten; + + *piBytesWritten = iSumBytesWritten; + + return TRC_SUCCESS; +} + +traceResult xTraceEventBufferClear(TraceEventBuffer_t* pxTraceEventBuffer) +{ + /* This should never fail */ + TRC_ASSERT(pxTraceEventBuffer != 0); + + pxTraceEventBuffer->uiHead = 0; + pxTraceEventBuffer->uiTail = 0; + pxTraceEventBuffer->uiFree = pxTraceEventBuffer->uiSize; + + return TRC_SUCCESS; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcExtension.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcExtension.c new file mode 100644 index 0000000000..948082160f --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcExtension.c @@ -0,0 +1,99 @@ +/* +* Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation of extensions. +*/ +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#define TRC_EXTENSION_BASE_EVENT_ID (TRC_EVENT_LAST_ID + 1) +uint32_t uiTraceNextFreeExtensionEventId = TRC_EXTENSION_BASE_EVENT_ID; + +#define TRC_EXTENSION_COMBINE_VERSION(_major, _minor, _patch) \ + ( \ + ((0x000000FF & (_major)) << 24) | \ + ((0x000000FF & (_minor)) << 16) | \ + ((0x0000FFFF & (_patch)) << 0) \ + ) + +#define TRC_EXTENSION_STATE_INDEX_VERSION 0 +#define TRC_EXTENSION_STATE_INDEX_BASE_EVENT_ID 1 +#define TRC_EXTENSION_STATE_INDEX_EVENT_COUNT 2 + +/* TODO: INITIALIZE */ + +traceResult xTraceExtensionCreate(const char* szName, uint8_t uiMajor, uint8_t uiMinor, uint16_t uiPatch, uint32_t uiEventCount, TraceExtensionHandle_t* pxExtensionHandle) +{ + TraceObjectHandle_t xObjectHandle; + TraceUnsignedBaseType_t uxStates[3]; + + /* This should never fail */ + TRC_ASSERT(uiEventCount != 0); + + /* This should never fail */ + TRC_ASSERT(pxExtensionHandle != 0); + + uxStates[TRC_EXTENSION_STATE_INDEX_VERSION] = TRC_EXTENSION_COMBINE_VERSION(uiMajor, uiMinor, uiPatch); + uxStates[TRC_EXTENSION_STATE_INDEX_BASE_EVENT_ID] = uiTraceNextFreeExtensionEventId; + uxStates[TRC_EXTENSION_STATE_INDEX_EVENT_COUNT] = uiEventCount; + + /* We need to check this */ + if (xTraceObjectRegisterInternal(PSF_EVENT_EXTENSION_CREATE, 0, szName, 3, uxStates, TRC_ENTRY_OPTION_EXTENSION, &xObjectHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + uiTraceNextFreeExtensionEventId += uiEventCount; + + *pxExtensionHandle = (TraceExtensionHandle_t)xObjectHandle; + + return TRC_SUCCESS; +} + +traceResult xTraceExtensionGetBaseEventId(TraceExtensionHandle_t xExtensionHandle, uint32_t *puiBaseEventId) +{ + TraceUnsignedBaseType_t uxBaseEventId; + + /* This should never fail */ + TRC_ASSERT(puiBaseEventId != 0); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState((TraceEntryHandle_t)xExtensionHandle, TRC_EXTENSION_STATE_INDEX_BASE_EVENT_ID, &uxBaseEventId) == TRC_SUCCESS); + + *puiBaseEventId = (uint32_t)uxBaseEventId; + + return TRC_SUCCESS; +} + +traceResult xTraceExtensionGetEventId(TraceExtensionHandle_t xExtensionHandle, uint32_t uiLocalEventId, uint32_t *puiGlobalEventId) +{ + TraceUnsignedBaseType_t uxBaseEventId; + + /* This should never fail */ + TRC_ASSERT(puiGlobalEventId != 0); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState((TraceEntryHandle_t)xExtensionHandle, TRC_EXTENSION_STATE_INDEX_BASE_EVENT_ID, &uxBaseEventId) == TRC_SUCCESS); + + *puiGlobalEventId = (uint32_t)uxBaseEventId + uiLocalEventId; + + return TRC_SUCCESS; +} + +traceResult xTraceExtensionGetConfigName(TraceExtensionHandle_t xExtensionHandle, const char **pszName) +{ + return xTraceEntryGetSymbol((TraceEntryHandle_t)xExtensionHandle, pszName); +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c new file mode 100644 index 0000000000..bfed5f0925 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHardwarePort.c @@ -0,0 +1,141 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The hardware abstraction layer for the trace recorder. + */ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +/* If using DWT timestamping (default on ARM Cortex-M3, M4 and M7), make sure the DWT unit is initialized. */ +#if ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) && (defined (__CORTEX_M) && (__CORTEX_M >= 0x03))) +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) +#ifndef TRC_CFG_ARM_CM_USE_SYSTICK + +void xTraceHardwarePortInitCortexM() +{ + /* 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.*/ + + xTraceError(TRC_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.*/ + + xTraceError(TRC_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 /* TRC_CFG_ARM_CM_USE_SYSTICK */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ +#endif /* ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) && (defined (__CORTEX_M) && (__CORTEX_M >= 0x03))) */ + +#if ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_ZyncUltraScaleR5) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_CYCLONE_V_HPS)) + +#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 (pxTraceRecorderData->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 (pxTraceRecorderData->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 /* ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_ZyncUltraScaleR5)) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHeap.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHeap.c new file mode 100644 index 0000000000..6ec948004a --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcHeap.c @@ -0,0 +1,161 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for heaps. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#if (TRC_USE_HEAPS == 1) + +#define TRC_HEAP_STATE_INDEX_CURRENT 0 +#define TRC_HEAP_STATE_INDEX_HIGHWATERMARK 1 +#define TRC_HEAP_STATE_INDEX_MAX 2 + +traceResult xTraceHeapCreate(const char *szName, TraceUnsignedBaseType_t uxCurrent, TraceUnsignedBaseType_t uxHighWaterMark, TraceUnsignedBaseType_t uxMax, TraceHeapHandle_t *pxHeapHandle) +{ + TraceObjectHandle_t xObjectHandle; + TraceUnsignedBaseType_t uxStates[3]; + + /* This should never fail */ + TRC_ASSERT(pxHeapHandle != 0); + + uxStates[TRC_HEAP_STATE_INDEX_CURRENT] = uxCurrent; + uxStates[TRC_HEAP_STATE_INDEX_HIGHWATERMARK] = uxHighWaterMark; + uxStates[TRC_HEAP_STATE_INDEX_MAX] = uxMax; + + /* We need to check this */ + if (xTraceObjectRegisterInternal(PSF_EVENT_HEAP_CREATE, 0, szName, 3, uxStates, TRC_ENTRY_OPTION_HEAP, &xObjectHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + *pxHeapHandle = (TraceHeapHandle_t)xObjectHandle; + + return TRC_SUCCESS; +} + +traceResult xTraceHeapAlloc(TraceHeapHandle_t xHeapHandle, void *pvAddress, TraceUnsignedBaseType_t uxSize) +{ + TraceUnsignedBaseType_t uxCurrent, uxHighWaterMark; + TraceEventHandle_t xEventHandle = 0; + + if (xHeapHandle == 0) + { + /* This can happen */ + return TRC_FAIL; + } + + /* If the address is null we assume this was a failed alloc attempt */ + if (pvAddress != 0) + { + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState(xHeapHandle, TRC_HEAP_STATE_INDEX_CURRENT, &uxCurrent) == TRC_SUCCESS); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState(xHeapHandle, TRC_HEAP_STATE_INDEX_HIGHWATERMARK, &uxHighWaterMark) == TRC_SUCCESS); + + uxCurrent += uxSize; + + if (uxCurrent > uxHighWaterMark) + { + uxHighWaterMark = uxCurrent; + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xHeapHandle, TRC_HEAP_STATE_INDEX_HIGHWATERMARK, uxHighWaterMark) == TRC_SUCCESS); + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xHeapHandle, TRC_HEAP_STATE_INDEX_CURRENT, uxCurrent) == TRC_SUCCESS); + } + + /* We need to check this */ + if (xTraceEventBegin(pvAddress != 0 ? PSF_EVENT_MALLOC : PSF_EVENT_MALLOC_FAILED, sizeof(void*) + sizeof(TraceUnsignedBaseType_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, pvAddress); + xTraceEventAddUnsignedBaseType(xEventHandle, uxSize); + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +traceResult xTraceHeapFree(TraceHeapHandle_t xHeapHandle, void *pvAddress, TraceUnsignedBaseType_t uxSize) +{ + TraceUnsignedBaseType_t uxCurrent; + TraceEventHandle_t xEventHandle = 0; + + if (xHeapHandle == 0) + { + /* This can happen */ + return TRC_FAIL; + } + + /* If the address is null we assume this was a failed alloc attempt */ + if (pvAddress != 0) + { + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState(xHeapHandle, TRC_HEAP_STATE_INDEX_CURRENT, &uxCurrent) == TRC_SUCCESS); + + uxCurrent -= uxSize; + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xHeapHandle, TRC_HEAP_STATE_INDEX_CURRENT, uxCurrent) == TRC_SUCCESS); + } + + /* We need to check this */ + if (xTraceEventBegin(pvAddress != 0 ? PSF_EVENT_FREE : PSF_EVENT_FREE_FAILED, sizeof(void*) + sizeof(TraceUnsignedBaseType_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, pvAddress); + xTraceEventAddUnsignedBaseType(xEventHandle, uxSize); + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +traceResult xTraceHeapGetCurrent(TraceHeapHandle_t xHeapHandle, TraceUnsignedBaseType_t *puxCurrent) +{ + /* This should never fail */ + TRC_ASSERT(xHeapHandle != 0); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState(xHeapHandle, TRC_HEAP_STATE_INDEX_CURRENT, puxCurrent) == TRC_SUCCESS); + + return TRC_SUCCESS; +} + +traceResult xTraceHeapGetHighWaterMark(TraceHeapHandle_t xHeapHandle, TraceUnsignedBaseType_t *puxHighWaterMark) +{ + /* This should never fail */ + TRC_ASSERT(xHeapHandle != 0); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState(xHeapHandle, TRC_HEAP_STATE_INDEX_HIGHWATERMARK, puxHighWaterMark) == TRC_SUCCESS); + + return TRC_SUCCESS; +} + +traceResult xTraceHeapGetMax(TraceHeapHandle_t xHeapHandle, TraceUnsignedBaseType_t *puxMax) +{ + /* This should never fail */ + TRC_ASSERT(xHeapHandle != 0); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState(xHeapHandle, TRC_HEAP_STATE_INDEX_MAX, puxMax) == TRC_SUCCESS); + + return TRC_SUCCESS; +} + +#endif /* (TRC_USE_HEAPS == 1) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcISR.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcISR.c new file mode 100644 index 0000000000..abcf3e4849 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcISR.c @@ -0,0 +1,274 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for ISR tagging. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +TraceISRInfo_t* pxTraceISRInfo; + +traceResult xTraceISRInitialize(TraceISRInfoBuffer_t *pxBuffer) +{ + uint32_t uiCoreIndex; + uint32_t uiStackIndex; + + TRC_ASSERT_EQUAL_SIZE(TraceISRInfoBuffer_t, TraceISRInfo_t); + + /* This should never fail */ + TRC_ASSERT(pxBuffer != 0); + + pxTraceISRInfo = (TraceISRInfo_t*)pxBuffer; + + for (uiCoreIndex = 0; uiCoreIndex < (TRC_CFG_CORE_COUNT); uiCoreIndex++) + { + TraceISRCoreInfo_t* pxCoreInfo = &pxTraceISRInfo->coreInfos[uiCoreIndex]; + + /* Initialize ISR stack */ + for (uiStackIndex = 0; uiStackIndex < (TRC_CFG_MAX_ISR_NESTING); uiStackIndex++) + { + pxCoreInfo->handleStack[uiStackIndex] = 0; + } + + pxCoreInfo->stackIndex = -1; + pxCoreInfo->isPendingContextSwitch = 0; + } + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_ISR); + + return TRC_SUCCESS; +} + +traceResult xTraceISRRegister(const char* szName, uint32_t uiPriority, TraceISRHandle_t *pxISRHandle) +{ + TraceEntryHandle_t xEntryHandle; + TraceEventHandle_t xEventHandle = 0; + uint32_t i = 0, uiLength = 0, uiValue = 0; + + /* We need to check this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR)) + { + return TRC_FAIL; + } + + /* This should never fail */ + TRC_ASSERT(pxISRHandle != 0); + + if (szName == 0) + { + szName = ""; + } + + /* Always save in symbol table, in case the recording has not yet started */ + /* We need to check this */ + if (xTraceEntryCreate(&xEntryHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetSymbol(xEntryHandle, szName) == TRC_SUCCESS); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xEntryHandle, 0, (TraceUnsignedBaseType_t)uiPriority) == TRC_SUCCESS); + + *pxISRHandle = (TraceISRHandle_t)xEntryHandle; + + for (i = 0; (szName[i] != 0) && (i < 128); i++) {} + + uiLength = i; + + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_DEFINE_ISR, uiLength + sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, (void*)xEntryHandle); + xTraceEventAdd32(xEventHandle, uiPriority); + xTraceEventAddData(xEventHandle, (void*)szName, uiLength); + + /* Check if we can truncate */ + xTraceEventPayloadRemaining(xEventHandle, &uiValue); + if (uiValue > 0) + { + xTraceEventAdd8(xEventHandle, 0); + } + + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +traceResult xTraceISRBegin(TraceISRHandle_t xISRHandle) +{ + TraceEventHandle_t xEventHandle = 0; + TRACE_ALLOC_CRITICAL_SECTION(); + + (void)xEventHandle; + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR)); + + TRACE_ENTER_CRITICAL_SECTION(); + + /* We are at the start of a possible ISR chain. + * No context switches should have been triggered now. + */ + TraceISRCoreInfo_t* pxCoreInfo = &pxTraceISRInfo->coreInfos[TRC_CFG_GET_CURRENT_CORE()]; + + if (pxCoreInfo->stackIndex == -1) + { + pxCoreInfo->isPendingContextSwitch = 0; + } + + if (pxCoreInfo->stackIndex < (TRC_CFG_MAX_ISR_NESTING) - 1) + { + pxCoreInfo->stackIndex++; + pxCoreInfo->handleStack[pxCoreInfo->stackIndex] = xISRHandle; + +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_ISR_BEGIN, sizeof(void*), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, (void*)xISRHandle); + xTraceEventEnd(xEventHandle); + } +#endif + } + else + { + TRACE_EXIT_CRITICAL_SECTION(); + + xTraceError(TRC_ERROR_ISR_NESTING_OVERFLOW); + + return TRC_FAIL; + } + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_SUCCESS; +} + +traceResult xTraceISREnd(TraceBaseType_t xIsTaskSwitchRequired) +{ + TraceEventHandle_t xEventHandle = 0; + TRACE_ALLOC_CRITICAL_SECTION(); + + (void)xEventHandle; + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR)); + + TRACE_ENTER_CRITICAL_SECTION(); + + TraceISRCoreInfo_t* pxCoreInfo = &pxTraceISRInfo->coreInfos[TRC_CFG_GET_CURRENT_CORE()]; + + /* Is there a pending task-switch? (perhaps from an earlier ISR) */ + pxCoreInfo->isPendingContextSwitch |= xIsTaskSwitchRequired; + + if (pxCoreInfo->stackIndex > 0) + { + pxCoreInfo->stackIndex--; + +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) + /* Store return to interrupted ISR (if nested ISRs)*/ + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_ISR_RESUME, sizeof(void*), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, (void*)pxCoreInfo->handleStack[pxCoreInfo->stackIndex]); + xTraceEventEnd(xEventHandle); + } +#endif + } + else + { + pxCoreInfo->stackIndex--; + + /* Store return to interrupted task, if no context switch will occur in between. */ + if ((pxCoreInfo->isPendingContextSwitch == 0) || (xTraceKernelPortIsSchedulerSuspended())) + { +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_TASK_ACTIVATE, sizeof(void*), &xEventHandle) == TRC_SUCCESS) + { + void *pvCurrentTask = 0; + + xTraceTaskGetCurrent(&pvCurrentTask); + xTraceEventAddPointer(xEventHandle, pvCurrentTask); + xTraceEventEnd(xEventHandle); + } +#endif + } + } + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_SUCCESS; +} + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +traceResult xTraceISRGetCurrentNesting(int32_t* puiValue) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR)); + + /* This should never fail */ + TRC_ASSERT(puiValue != 0); + + TraceISRCoreInfo_t* pxCoreInfo = &pxTraceISRInfo->coreInfos[TRC_CFG_GET_CURRENT_CORE()]; + *puiValue = pxCoreInfo->stackIndex; + + return TRC_SUCCESS; +} + +int32_t xTraceISRGetCurrentNestingReturned(void) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR)); + + return pxTraceISRInfo->coreInfos[TRC_CFG_GET_CURRENT_CORE()].stackIndex; +} + +traceResult xTraceISRGetCurrent(TraceISRHandle_t* pxISRHandle) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ISR)); + + /* This should never fail */ + TRC_ASSERT(pxISRHandle != 0); + + TraceISRCoreInfo_t* pxCoreInfo = &pxTraceISRInfo->coreInfos[TRC_CFG_GET_CURRENT_CORE()]; + + if (pxCoreInfo->stackIndex < 0) + { + return TRC_FAIL; + } + + *pxISRHandle = pxCoreInfo->handleStack[pxCoreInfo->stackIndex]; + + return TRC_SUCCESS; +} + +#endif + +/* DEPRECATED */ +TraceISRHandle_t xTraceSetISRProperties(const char* szName, uint32_t uiPriority) +{ + TraceISRHandle_t xISRHandle = 0; + + xTraceISRRegister(szName, uiPriority, &xISRHandle); + + return xISRHandle; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcInternalEventBuffer.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcInternalEventBuffer.c new file mode 100644 index 0000000000..100350a848 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcInternalEventBuffer.c @@ -0,0 +1,75 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The implementation of the internal buffer. + */ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#if (TRC_USE_INTERNAL_BUFFER == 1) + +#include +#include +#include + +static TraceMultiCoreEventBuffer_t *pxInternalEventBuffer; + +traceResult xTraceInternalEventBufferInitialize(uint8_t* puiBuffer, uint32_t uiSize) +{ + /* uiSize must be larger than sizeof(TraceMultiCoreEventBuffer_t) or there will be no room for any data */ + /* This should never fail */ + TRC_ASSERT(uiSize > sizeof(TraceMultiCoreEventBuffer_t)); + + /* pxInternalBuffer will be placed at the beginning of the puiBuffer */ + pxInternalEventBuffer = (TraceMultiCoreEventBuffer_t*)puiBuffer; + + /* Send in a an address pointing after the TraceMultiCoreEventBuffer_t */ + /* We need to check this */ + if (xTraceMultiCoreEventBufferInitialize(pxInternalEventBuffer, TRC_EVENT_BUFFER_OPTION_SKIP, + &puiBuffer[sizeof(TraceMultiCoreEventBuffer_t)], uiSize - sizeof(TraceMultiCoreEventBuffer_t)) == TRC_FAIL) + { + return TRC_FAIL; + } + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_INTERNAL_EVENT_BUFFER); + + return TRC_SUCCESS; +} + +traceResult xTraceInternalEventBufferPush(void *pvData, uint32_t uiSize, int32_t *piBytesWritten) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_INTERNAL_EVENT_BUFFER)); + + return xTraceMultiCoreEventBufferPush(pxInternalEventBuffer, pvData, uiSize, piBytesWritten); +} + +traceResult xTraceInternalEventBufferTransfer(int32_t *piBytesWritten) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_INTERNAL_EVENT_BUFFER)); + + return xTraceMultiCoreEventBufferTransfer(pxInternalEventBuffer, piBytesWritten); +} + +traceResult xTraceInternalEventBufferClear() +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_INTERNAL_EVENT_BUFFER)); + + return xTraceMultiCoreEventBufferClear(pxInternalEventBuffer); +} + +#endif /* (TRC_USE_INTERNAL_BUFFER == 1) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcInterval.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcInterval.c new file mode 100644 index 0000000000..49a1da045e --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcInterval.c @@ -0,0 +1,83 @@ +/* +* Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation of intervals. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#define TRC_INTERVAL_STATE_INDEX 0 + +traceResult xTraceIntervalCreate(const char *szName, TraceIntervalHandle_t *pxIntervalHandle) +{ + TraceObjectHandle_t xObjectHandle; + + /* This should never fail */ + TRC_ASSERT(pxIntervalHandle != 0); + + /* We need to check this */ + if (xTraceObjectRegister(PSF_EVENT_INTERVAL_CREATE, 0, szName, 0, &xObjectHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetOptions((TraceEntryHandle_t)xObjectHandle, TRC_ENTRY_OPTION_INTERVAL) == TRC_SUCCESS); + + *pxIntervalHandle = (TraceIntervalHandle_t)xObjectHandle; + + return TRC_SUCCESS; +} + +traceResult xTraceIntervalStart(TraceIntervalHandle_t xIntervalHandle) +{ + TraceEventHandle_t xEventHandle = 0; + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState((TraceEntryHandle_t)xIntervalHandle, TRC_INTERVAL_STATE_INDEX, 1) == TRC_SUCCESS); + + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_INTERVAL_STATECHANGE, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, (void*)xIntervalHandle); + xTraceEventAdd32(xEventHandle, 1); + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +traceResult xTraceIntervalStop(TraceIntervalHandle_t xIntervalHandle) +{ + TraceEventHandle_t xEventHandle = 0; + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState((TraceEntryHandle_t)xIntervalHandle, TRC_INTERVAL_STATE_INDEX, 0) == TRC_SUCCESS); + + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_INTERVAL_STATECHANGE, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, (void*)xIntervalHandle); + xTraceEventAdd32(xEventHandle, 0); + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +traceResult xTraceIntervalGetState(TraceIntervalHandle_t xIntervalHandle, TraceUnsignedBaseType_t *puxState) +{ + return xTraceEntryGetState((TraceEntryHandle_t)xIntervalHandle, TRC_INTERVAL_STATE_INDEX, puxState); +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c index f34a848583..3108e017b1 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcKernelPort.c @@ -1,1083 +1,655 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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)*/ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The FreeRTOS specific parts of the trace recorder + */ + +#include +#include + +#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 + +#include +#include + +#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)) + +#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 + +/* The TzCtrl task - receives commands from Tracealyzer (start/stop) */ +static portTASK_FUNCTION(TzCtrl, pvParameters); + +#endif + +#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 + +#endif + +#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 + +#endif + +#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 + +#endif + +#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 + +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) + +traceResult xTraceKernelPortGetUnusedStack(void* pvTask, TraceUnsignedBaseType_t* puxUnusedStack) +{ + *puxUnusedStack = uxTaskGetStackHighWaterMark(pvTask); + + return TRC_SUCCESS; +} + +#endif + +traceResult xTraceKernelPortDelay(uint32_t uiTicks) +{ + vTaskDelay(uiTicks); + + return TRC_SUCCESS; +} + +unsigned char xTraceKernelPortIsSchedulerSuspended(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; +} + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +typedef struct TraceKernelPortData +{ + TraceHeapHandle_t xSystemHeapHandle; + TraceKernelPortTaskHandle_t xTzCtrlHandle; +} TraceKernelPortData_t; + +static TraceKernelPortData_t* pxKernelPortData; + +#define TRC_PORT_MALLOC(size) pvPortMalloc(size) + +traceResult xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t* pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceKernelPortDataBuffer_t, TraceKernelPortData_t); + + if (pxBuffer == 0) + { + return TRC_FAIL; + } + + pxKernelPortData = (TraceKernelPortData_t*)pxBuffer; + + pxKernelPortData->xSystemHeapHandle = 0; + pxKernelPortData->xTzCtrlHandle = 0; + + return TRC_SUCCESS; +} + +traceResult xTraceKernelPortEnable(void) +{ + HeapStats_t xHeapStats; + void* pvAlloc; + + if (pxKernelPortData->xSystemHeapHandle == 0) + { + /* Some magic to make sure the heap has been initialized! */ + pvAlloc = pvPortMalloc(1); + if (pvAlloc != 0) + { + vPortFree(pvAlloc); + } + + vPortGetHeapStats(&xHeapStats); + xTraceHeapCreate("System Heap", configTOTAL_HEAP_SIZE - xHeapStats.xAvailableHeapSpaceInBytes, configTOTAL_HEAP_SIZE - xHeapStats.xMinimumEverFreeBytesRemaining, configTOTAL_HEAP_SIZE, &pxKernelPortData->xSystemHeapHandle); + } + + if (pxKernelPortData->xTzCtrlHandle == 0) + { + /* Creates the TzCtrl task - receives trace commands (start, stop, ...) */ +#if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1) + pxKernelPortData->xTzCtrlHandle = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl); +#else + xTaskCreate(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, &pxKernelPortData->xTzCtrlHandle); +#endif + + if (pxKernelPortData->xTzCtrlHandle == 0) + { + xTraceError(TRC_ERROR_TZCTRLTASK_NOT_CREATED); + + return TRC_FAIL; + } + } + + return TRC_SUCCESS; +} + +static portTASK_FUNCTION(TzCtrl, pvParameters) +{ + (void)pvParameters; + + while (1) + { + xTraceTzCtrl(); + + vTaskDelay(TRC_CFG_CTRL_TASK_DELAY); + } +} + +#if (TRC_CFG_SCHEDULING_ONLY == 0) + +void vTraceSetQueueName(void* pvQueue, const char* szName) +{ + xTraceObjectSetNameWithoutHandle(pvQueue, szName); +} + +void vTraceSetSemaphoreName(void* pvSemaphore, const char* szName) +{ + xTraceObjectSetNameWithoutHandle(pvSemaphore, szName); +} + +void vTraceSetMutexName(void* pvMutex, const char* szName) +{ + xTraceObjectSetNameWithoutHandle(pvMutex, szName); +} + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) + +void vTraceSetEventGroupName(void* pvEventGroup, const char* szName) +{ + xTraceObjectSetNameWithoutHandle(pvEventGroup, szName); +} + +#endif + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +void vTraceSetStreamBufferName(void* pvStreamBuffer, const char* szName) +{ + xTraceObjectSetNameWithoutHandle(pvStreamBuffer, szName); +} + +void vTraceSetMessageBufferName(void* pvMessageBuffer, const char* szName) +{ + xTraceObjectSetNameWithoutHandle(pvMessageBuffer, szName); +} + +#endif + +#endif + +TraceHeapHandle_t xTraceKernelPortGetSystemHeapHandle(void) +{ + return pxKernelPortData->xSystemHeapHandle; +} + +#endif + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + +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 + +uint8_t prvTraceGetQueueType(void* pvQueue) +{ + // This is either declared in header file in FreeRTOS 8 and later, or as extern above + return ucQueueGetQueueType(pvQueue); +} + +/* Tasks */ +uint16_t prvTraceGetTaskNumberLow16(void* pvTask) +{ + return TRACE_GET_LOW16(uxTaskGetTaskNumber(pvTask)); +} + +uint16_t prvTraceGetTaskNumberHigh16(void* pvTask) +{ + return TRACE_GET_HIGH16(uxTaskGetTaskNumber(pvTask)); +} + +void prvTraceSetTaskNumberLow16(void* pvTask, uint16_t uiValue) +{ + vTaskSetTaskNumber(pvTask, TRACE_SET_LOW16(uxTaskGetTaskNumber(pvTask), uiValue)); +} + +void prvTraceSetTaskNumberHigh16(void* pvTask, uint16_t uiValue) +{ + vTaskSetTaskNumber(pvTask, TRACE_SET_HIGH16(uxTaskGetTaskNumber(pvTask), uiValue)); +} + +uint16_t prvTraceGetQueueNumberLow16(void* pvQueue) +{ + return TRACE_GET_LOW16(prvTraceGetQueueNumber(pvQueue)); +} + +uint16_t prvTraceGetQueueNumberHigh16(void* pvQueue) +{ + return TRACE_GET_HIGH16(prvTraceGetQueueNumber(pvQueue)); +} + +void prvTraceSetQueueNumberLow16(void* pvQueue, uint16_t uiValue) +{ + vQueueSetQueueNumber(pvQueue, TRACE_SET_LOW16(prvTraceGetQueueNumber(pvQueue), uiValue)); +} + +void prvTraceSetQueueNumberHigh16(void* pvQueue, uint16_t uiValue) +{ + vQueueSetQueueNumber(pvQueue, TRACE_SET_HIGH16(prvTraceGetQueueNumber(pvQueue), uiValue)); +} + +#if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +uint16_t prvTraceGetTimerNumberLow16(void* pvTimer) +{ + return TRACE_GET_LOW16(uxTimerGetTimerNumber(pvTimer)); +} + +uint16_t prvTraceGetTimerNumberHigh16(void* pvTimer) +{ + return TRACE_GET_HIGH16(uxTimerGetTimerNumber(pvTimer)); +} + +void prvTraceSetTimerNumberLow16(void* pvTimer, uint16_t uiValue) +{ + vTimerSetTimerNumber(pvTimer, TRACE_SET_LOW16(uxTimerGetTimerNumber(pvTimer), uiValue)); +} + +void prvTraceSetTimerNumberHigh16(void* pvTimer, uint16_t uiValue) +{ + vTimerSetTimerNumber(pvTimer, TRACE_SET_HIGH16(uxTimerGetTimerNumber(pvTimer), uiValue)); +} + +#endif + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +uint16_t prvTraceGetEventGroupNumberLow16(void* pvEventGroup) +{ + return TRACE_GET_LOW16(uxEventGroupGetNumber(pvEventGroup)); +} + +uint16_t prvTraceGetEventGroupNumberHigh16(void* pvEventGroup) +{ + return TRACE_GET_HIGH16(uxEventGroupGetNumber(pvEventGroup)); +} + +void prvTraceSetEventGroupNumberLow16(void* pvEventGroup, uint16_t uiValue) +{ + vEventGroupSetNumber(pvEventGroup, TRACE_SET_LOW16(uxEventGroupGetNumber(pvEventGroup), uiValue)); +} + +void prvTraceSetEventGroupNumberHigh16(void* pvEventGroup, uint16_t uiValue) +{ + vEventGroupSetNumber(pvEventGroup, TRACE_SET_HIGH16(uxEventGroupGetNumber(pvEventGroup), uiValue)); +} + +#endif + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +uint16_t prvTraceGetStreamBufferNumberLow16(void* pvStreamBuffer) +{ + return TRACE_GET_LOW16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer)); +} + +uint16_t prvTraceGetStreamBufferNumberHigh16(void* pvStreamBuffer) +{ + return TRACE_GET_HIGH16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer)); +} + +void prvTraceSetStreamBufferNumberLow16(void* pvStreamBuffer, uint16_t uiValue) +{ + vStreamBufferSetStreamBufferNumber(pvStreamBuffer, TRACE_SET_LOW16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer), uiValue)); +} + +void prvTraceSetStreamBufferNumberHigh16(void* pvStreamBuffer, uint16_t uiValue) +{ + vStreamBufferSetStreamBufferNumber(pvStreamBuffer, TRACE_SET_HIGH16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer), uiValue)); +} + +#endif + +static TraceKernelPortTaskHandle_t xTzCtrlHandle = 0; /* TzCtrl task TCB */ + +/* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */ +int uiInEventGroupSetBitsFromISR = 0; + +/** + * @internal Class reference table + */ +traceObjectClass TraceQueueClassTable[5] = { + TRACE_CLASS_QUEUE, + TRACE_CLASS_MUTEX, + TRACE_CLASS_SEMAPHORE, + TRACE_CLASS_SEMAPHORE, + TRACE_CLASS_MUTEX +}; + +#if (TRC_CFG_SCHEDULING_ONLY == 0) + +void vTraceSetQueueName(void* pvQueue, const char* szName) +{ + prvTraceSetObjectName(TRACE_CLASS_QUEUE, TRACE_GET_OBJECT_NUMBER(QUEUE, pvQueue), szName); +} + +void vTraceSetSemaphoreName(void* pvSemaphore, const char* szName) +{ + prvTraceSetObjectName(TRACE_CLASS_SEMAPHORE, TRACE_GET_OBJECT_NUMBER(QUEUE, pvSemaphore), szName); +} + +void vTraceSetMutexName(void* pvMutex, const char* szName) +{ + prvTraceSetObjectName(TRACE_CLASS_MUTEX, TRACE_GET_OBJECT_NUMBER(QUEUE, pvMutex), szName); +} + +#if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X) + +void vTraceSetEventGroupName(void* pvEventGroup, const char* szName) +{ + prvTraceSetObjectName(TRACE_CLASS_EVENTGROUP, TRACE_GET_OBJECT_NUMBER(EVENTGROUP, pvEventGroup), szName); +} + +#endif + +#if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0) + +void vTraceSetStreamBufferName(void* pvStreamBuffer, const char* szName) +{ + prvTraceSetObjectName(TRACE_CLASS_STREAMBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, pvStreamBuffer), szName); +} + +void vTraceSetMessageBufferName(void* pvStreamBuffer, const char* szName) +{ + prvTraceSetObjectName(TRACE_CLASS_MESSAGEBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, pvStreamBuffer), szName); +} + +#endif + +#endif + +void* prvTraceGetCurrentTaskHandle() +{ + return xTaskGetCurrentTaskHandle(); +} + +traceResult xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t* pxBuffer) +{ + (void)pxBuffer; + + return TRC_SUCCESS; +} + +traceResult xTraceKernelPortEnable(void) +{ +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) + + if (xTzCtrlHandle == 0) + { +#if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1) + + xTzCtrlHandle = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl); + +#else + + xTaskCreate(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, &xTzCtrlHandle); + +#endif + } + +#else + + (void)xTzCtrlHandle; + +#endif + + return TRC_SUCCESS; +} + +#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 (xTraceIsRecorderEnabled()) + { + prvReportStackUsage(); + } + + vTaskDelay(TRC_CFG_CTRL_TASK_DELAY); + } +} + +#endif + +traceResult xTraceKernelPortInitObjectPropertyTable() +{ + 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; + + return TRC_SUCCESS; +} + +traceResult xTraceKernelPortInitObjectHandleStack() +{ + uint32_t i = 0; + + 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; + + for (i = 0; i < TRACE_NCLASSES; i++) + { + objectHandleStacks.handleCountWaterMarksOfClass[i] = 0; + } + + for (i = 0; i < TRACE_KERNEL_OBJECT_COUNT; i++) + { + objectHandleStacks.objectHandles[i] = 0; + } + + return TRC_SUCCESS; +} + +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!"; + } +} + +#endif + +#endif diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcMultiCoreEventBuffer.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcMultiCoreEventBuffer.c new file mode 100644 index 0000000000..6cd5263ef6 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcMultiCoreEventBuffer.c @@ -0,0 +1,112 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The interface for the multi-core event buffer. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +traceResult xTraceMultiCoreEventBufferInitialize(TraceMultiCoreEventBuffer_t* pxTraceMultiCoreEventBuffer, uint32_t uiOptions, + uint8_t* puiBuffer, uint32_t uiSize) +{ + uint32_t i; + + /* This should never fail */ + TRC_ASSERT(pxTraceMultiCoreEventBuffer != 0); + + /* This should never fail */ + TRC_ASSERT(puiBuffer != 0); + + uint32_t uiBufferSizePerCore = uiSize / TRC_CFG_CORE_COUNT; + + /* This should never fail */ + TRC_ASSERT(uiBufferSizePerCore != 0); + + for (i = 0; i < TRC_CFG_CORE_COUNT; i++) + { + /* Set the event buffer pointers to point into the allocated space we have been given, this ensures + * a flat memory layout necessary for usage in streaming snaphot. */ + pxTraceMultiCoreEventBuffer->xEventBuffer[i] = (TraceEventBuffer_t*)(&puiBuffer[i * uiBufferSizePerCore]); + + /* Initialize the event buffer structure with its memory buffer placed following its own structure data. */ + /* We need to check this */ + if (xTraceEventBufferInitialize(pxTraceMultiCoreEventBuffer->xEventBuffer[i], uiOptions, + &puiBuffer[(i * uiBufferSizePerCore) + sizeof(TraceEventBuffer_t)], + uiBufferSizePerCore - sizeof(TraceEventBuffer_t)) == TRC_FAIL) + { + return TRC_FAIL; + } + } + + return TRC_SUCCESS; +} + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +traceResult xTraceMultiCoreEventBufferPush(TraceMultiCoreEventBuffer_t* pxTraceMultiCoreEventBuffer, + void* pvData, uint32_t uiSize, int32_t* piBytesWritten) +{ + /* This should never fail */ + TRC_ASSERT(pxTraceMultiCoreEventBuffer != 0); + + TRC_ASSERT((TRC_CFG_GET_CURRENT_CORE()) < (TRC_CFG_CORE_COUNT)); + + return xTraceEventBufferPush(pxTraceMultiCoreEventBuffer->xEventBuffer[TRC_CFG_GET_CURRENT_CORE()], pvData, uiSize, piBytesWritten); +} + +#endif + +traceResult xTraceMultiCoreEventBufferTransfer(TraceMultiCoreEventBuffer_t* pxTraceMultiCoreEventBuffer, int32_t* piBytesWritten) +{ + int32_t iBytesWritten = 0; + uint32_t coreId; + + /* This should never fail */ + TRC_ASSERT(pxTraceMultiCoreEventBuffer != 0); + + /* This should never fail */ + TRC_ASSERT(piBytesWritten != 0); + + *piBytesWritten = 0; + + for (coreId = 0; coreId < TRC_CFG_CORE_COUNT; coreId++) + { + /* We need to check this */ + if (xTraceEventBufferTransfer(pxTraceMultiCoreEventBuffer->xEventBuffer[coreId], &iBytesWritten) == TRC_FAIL) + { + return TRC_FAIL; + } + + *piBytesWritten += iBytesWritten; + } + + return TRC_SUCCESS; +} + +traceResult xTraceMultiCoreEventBufferClear(TraceMultiCoreEventBuffer_t* pxTraceMultiCoreEventBuffer) +{ + uint32_t coreId; + + /* This should never fail */ + TRC_ASSERT(pxTraceMultiCoreEventBuffer != 0); + + for (coreId = 0; coreId < TRC_CFG_CORE_COUNT; coreId++) + { + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEventBufferClear(pxTraceMultiCoreEventBuffer->xEventBuffer[coreId]) == TRC_SUCCESS); + } + + return TRC_SUCCESS; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcObject.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcObject.c new file mode 100644 index 0000000000..a5f16b6bce --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcObject.c @@ -0,0 +1,349 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for strings. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#include + +#ifndef TRC_SEND_NAME_ONLY_ON_DELETE +#define TRC_SEND_NAME_ONLY_ON_DELETE 0 +#endif + +traceResult prvTraceObjectSendState(uint32_t uiEventCode, void* pvObject, TraceUnsignedBaseType_t uxState); +traceResult prvTraceObjectSendNameEvent(void* pvObject, const char* szName); + +traceResult xTraceObjectRegisterInternal(uint32_t uiEventCode, void* pvObject, const char* szName, TraceUnsignedBaseType_t uxStateCount, TraceUnsignedBaseType_t uxStates[], TraceUnsignedBaseType_t uxOptions, TraceObjectHandle_t* pxObjectHandle) +{ + TraceEntryHandle_t xEntryHandle; + TraceEventHandle_t xEventHandle = 0; + TraceUnsignedBaseType_t i; + + TRACE_ALLOC_CRITICAL_SECTION(); + + /* This should never fail */ + TRC_ASSERT(pxObjectHandle != 0); + + /* This should never fail */ + TRC_ASSERT(uxStateCount <= (TRC_ENTRY_TABLE_STATE_COUNT)); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (pvObject != 0) + { + /* An address was supplied */ + if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL) + { + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + } + else + { + /* No address was supplied */ + if (xTraceEntryCreate(&xEntryHandle) == TRC_FAIL) + { + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + } + + for (i = 0; i < uxStateCount; i++) + { + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xEntryHandle, i, uxStates[i]) == TRC_SUCCESS); + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetOptions(xEntryHandle, uxOptions) == TRC_SUCCESS); + + *pxObjectHandle = (TraceObjectHandle_t)xEntryHandle; + + TRACE_EXIT_CRITICAL_SECTION(); + + if (szName != 0 && szName[0] != 0) + { + /* Not a null or empty string */ + /* This will set the symbol and create an event for it */ + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceObjectSetName((TraceObjectHandle_t)xEntryHandle, szName) == TRC_SUCCESS); + } + + /* Send the create event, if possible */ + /*We need to check this */ + if (xTraceEventBegin(uiEventCode, sizeof(void*) + uxStateCount * sizeof(TraceUnsignedBaseType_t) + sizeof(TraceUnsignedBaseType_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, pvObject); + for (i = 0; i < uxStateCount; i++) + { + xTraceEventAddUnsignedBaseType(xEventHandle, uxStates[i]); + } + xTraceEventAddUnsignedBaseType(xEventHandle, uxOptions); + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +traceResult xTraceObjectRegister(uint32_t uiEventCode, void *pvObject, const char* szName, TraceUnsignedBaseType_t uxState, TraceObjectHandle_t *pxObjectHandle) +{ + TraceEntryHandle_t xEntryHandle; + + TRACE_ALLOC_CRITICAL_SECTION(); + + /* This should never fail */ + TRC_ASSERT(pxObjectHandle != 0); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (pvObject != 0) + { + /* An address was supplied */ + if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL) + { + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + } + else + { + /* No address was supplied */ + if (xTraceEntryCreate(&xEntryHandle) == TRC_FAIL) + { + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xEntryHandle, 0, uxState) == TRC_SUCCESS); + + *pxObjectHandle = (TraceObjectHandle_t)xEntryHandle; + + TRACE_EXIT_CRITICAL_SECTION(); + + if (szName != 0 && szName[0] != 0) + { + /* Not a null or empty string */ + /* This will set the symbol and create an event for it */ + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceObjectSetName((TraceObjectHandle_t)xEntryHandle, szName) == TRC_SUCCESS); + } + + /* Send the create event, if possible */ + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(prvTraceObjectSendState(uiEventCode, pvObject, uxState) == TRC_SUCCESS); + + return TRC_SUCCESS; +} + +traceResult xTraceObjectUnregister(TraceObjectHandle_t xObjectHandle, uint32_t uiEventCode, TraceUnsignedBaseType_t uxState) +{ + void* pvObject; + const char *szName; + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xObjectHandle, &pvObject) == TRC_SUCCESS); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetSymbol((TraceEntryHandle_t)xObjectHandle, &szName) == TRC_SUCCESS); + +#if (TRC_SEND_NAME_ONLY_ON_DELETE == 1) + /* Send name event because this is a delete */ + /* This should never fail */ + TRC_ASSERT(prvTraceObjectSendNameEvent(pvObject, szName) == TRC_SUCCESS); +#endif /* (TRC_SEND_NAME_ONLY_ON_DELETE == 1) */ + + /* Send the delete event, if possible */ + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(prvTraceObjectSendState(uiEventCode, pvObject, uxState) == TRC_SUCCESS); + + return xTraceEntryDelete(xObjectHandle); +} + +traceResult xTraceObjectSetName(TraceObjectHandle_t xObjectHandle, const char* szName) +{ + void* pvObject; + + if (szName == 0) + { + szName = ""; + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xObjectHandle, &pvObject) == TRC_SUCCESS); + +#if (TRC_SEND_NAME_ONLY_ON_DELETE == 0) + /* Send name event now since we don't do it on delete events */ + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(prvTraceObjectSendNameEvent(pvObject, szName) == TRC_SUCCESS); +#endif /* (TRC_SEND_NAME_ONLY_ON_DELETE == 0) */ + + return xTraceEntrySetSymbol((TraceEntryHandle_t)xObjectHandle, szName); +} + +traceResult xTraceObjectRegisterWithoutHandle(uint32_t uiEventCode, void* pvObject, const char* szName, TraceUnsignedBaseType_t uxState) +{ + TraceObjectHandle_t xObjectHandle; + + return xTraceObjectRegister(uiEventCode, pvObject, szName, uxState, &xObjectHandle); +} + +traceResult xTraceObjectUnregisterWithoutHandle(uint32_t uiEventCode, void* pvObject, TraceUnsignedBaseType_t uxState) +{ + TraceEntryHandle_t xEntryHandle; + traceResult xResult; + + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL) + { + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + + xResult = xTraceObjectUnregister((TraceObjectHandle_t)xEntryHandle, uiEventCode, uxState); + + TRACE_EXIT_CRITICAL_SECTION(); + + return xResult; +} + +traceResult xTraceObjectSetNameWithoutHandle(void* pvObject, const char* szName) +{ + TraceEntryHandle_t xEntryHandle; + traceResult xResult; + + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL) + { + /* No previous entry found. Create one. */ + if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL) + { + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + } + + xResult = xTraceObjectSetName((TraceObjectHandle_t)xEntryHandle, szName); + + TRACE_EXIT_CRITICAL_SECTION(); + + return xResult; +} + +traceResult xTraceObjectSetSpecificStateWithoutHandle(void* pvObject, uint32_t uiIndex, TraceUnsignedBaseType_t uxState) +{ + TraceEntryHandle_t xEntryHandle; + traceResult xResult; + + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL) + { + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + + xResult = xTraceObjectSetSpecificState((TraceObjectHandle_t)xEntryHandle, uiIndex, uxState); + + TRACE_EXIT_CRITICAL_SECTION(); + + return xResult; +} + +traceResult xTraceObjectSetOptionsWithoutHandle(void* pvObject, uint32_t uiMask) +{ + TraceEntryHandle_t xEntryHandle; + traceResult xResult; + + TRACE_ALLOC_CRITICAL_SECTION(); + + TRACE_ENTER_CRITICAL_SECTION(); + + if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL) + { + /* No previous entry found. Create one. */ + if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL) + { + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + } + + xResult = xTraceObjectSetOptions((TraceObjectHandle_t)xEntryHandle, uiMask); + + TRACE_EXIT_CRITICAL_SECTION(); + + return xResult; +} + +traceResult prvTraceObjectSendState(uint32_t uiEventCode, void* pvObject, TraceUnsignedBaseType_t uxState) +{ + TraceEventHandle_t xEventHandle = 0; + + if (xTraceEventBegin(uiEventCode, sizeof(void*) + sizeof(TraceUnsignedBaseType_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, pvObject); + xTraceEventAddUnsignedBaseType(xEventHandle, uxState); + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +traceResult prvTraceObjectSendNameEvent(void* pvObject, const char* szName) +{ + uint32_t i = 0, uiLength = 0, uiValue = 0; + TraceEventHandle_t xEventHandle = 0; + + for (i = 0; (szName[i] != 0) && (i < (TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE)); i++) {} + + uiLength = i; + + if (xTraceEventBegin(PSF_EVENT_OBJ_NAME, sizeof(void*) + uiLength, &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, pvObject); + xTraceEventAddData(xEventHandle, (void*)szName, uiLength); + + /* Check if we can truncate */ + xTraceEventPayloadRemaining(xEventHandle, &uiValue); + if (uiValue > 0) + { + xTraceEventAdd8(xEventHandle, 0); + } + + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcPrint.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcPrint.c new file mode 100644 index 0000000000..c693719df3 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcPrint.c @@ -0,0 +1,314 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for print. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#if (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) + +#include + +static traceResult prvTraceVPrintF(TraceStringHandle_t xChannel, const char* szFormat, uint32_t uiLength, uint32_t uiArgs, va_list *pxVL); + +typedef struct TracePrintInfo +{ + TraceStringHandle_t defaultChannel; + TraceStringHandle_t consoleChannel; +} TracePrintInfo_t; + +static TracePrintInfo_t *pxPrintInfo; + +traceResult xTracePrintInitialize(TracePrintBuffer_t *pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TracePrintBuffer_t, TracePrintInfo_t); + + /* This should never fail */ + TRC_ASSERT(pxBuffer != 0); + + pxPrintInfo = (TracePrintInfo_t*)pxBuffer; + pxPrintInfo->defaultChannel = 0; + pxPrintInfo->consoleChannel = 0; + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_PRINT); + + return TRC_SUCCESS; +} + +/****************************************************************************** + * xTracePrint + * + * 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 xTraceStringRegister(). + * + * Example: + * + * TraceStringHandle_t xChannel = xTraceStringRegister("MyChannel"); + * ... + * xTracePrint(xChannel, "Hello World!"); + * + ******************************************************************************/ +traceResult xTracePrint(TraceStringHandle_t xChannel, const char* szString) +{ + uint32_t uiLength = 0; + uint32_t i = 0; + + /* We need to check this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT)) + { + return TRC_FAIL; + } + + if (szString == 0) + { + szString = ""; + } + + while ((szString[i] != 0) && (i < 128)) + { + i++; + } + + uiLength = i + 1; /* Null termination */ + + return prvTraceVPrintF(xChannel, szString, uiLength, 0, (va_list*)0); +} + +/******************************************************************************* +* xTraceConsoleChannelPrintF +* +* 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 xTraceConsoleChannelPrintF +* ... +* LogString("My value is: %d", myValue); +******************************************************************************/ +traceResult xTraceConsoleChannelPrintF(const char* szFormat, ...) +{ + traceResult xResult; + va_list xVL; + + /* We need to check this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT)) + { + return TRC_FAIL; + } + + if (pxPrintInfo->consoleChannel == 0) + { + if (xTraceStringRegister("Debug Console", &pxPrintInfo->consoleChannel) == TRC_FAIL) + { + return TRC_FAIL; + } + } + + va_start(xVL, szFormat); + xResult = xTraceVPrintF(pxPrintInfo->consoleChannel, szFormat, xVL); + va_end(xVL); + + return xResult; +} + +/****************************************************************************** + * xTracePrintF + * + * 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 xTraceStringRegister(). + * + * Example: + * + * TraceStringHandle_t adc_uechannel = xTraceStringRegister("ADC User Events"); + * ... + * xTracePrintF(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). + * + ******************************************************************************/ +traceResult xTracePrintF(TraceStringHandle_t xChannel, const char* szFormat, ...) +{ + traceResult xResult; + va_list xVL; + + /* We need to check this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT)) + { + return TRC_FAIL; + } + + va_start(xVL, szFormat); + xResult = xTraceVPrintF(xChannel, szFormat, xVL); + va_end(xVL); + + return xResult; +} + +/****************************************************************************** + * xTraceVPrintF + * + * xTracePrintF variant that accepts a va_list. + * See xTraceVPrintF documentation for further details. + * + ******************************************************************************/ +traceResult xTraceVPrintF(TraceStringHandle_t xChannel, const char* szFormat, va_list xVL) +{ + uint32_t i = 0; + uint32_t uiArgs = 0; + uint32_t uiLength; + + /* We need to check this */ + if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_PRINT)) + { + return TRC_FAIL; + } + + if (szFormat == 0) + { + szFormat = ""; + } + + /* Count the number of arguments in the format string (e.g., %d) */ + for (i = 0; (szFormat[i] != 0) && (i < 128); i++) + { + if (szFormat[i] == '%') + { + if (szFormat[i + 1] == 0) + { + /* Found end of string, let for loop detect it */ + continue; + } + + if (szFormat[i + 1] != '%') + { + uiArgs++; /* Found an argument */ + } + + i++; /* Move past format specifier or non-argument '%' */ + } + } + + uiLength = i + 1; /* Null termination */ + + return prvTraceVPrintF(xChannel, szFormat, uiLength, uiArgs, &xVL); +} + +static traceResult prvTraceVPrintF(TraceStringHandle_t xChannel, const char* szFormat, uint32_t uiLength, uint32_t uiArgs, va_list *pxVL) +{ + TraceEventHandle_t xEventHandle = 0; + uint32_t i, uiRemaining; + uint32_t uiValue; + uint32_t uiEventCode = PSF_EVENT_USER_EVENT + 1 + uiArgs; /* Add channel (1) */ + uint32_t uiSize = sizeof(void*) + uiArgs * sizeof(TraceUnsignedBaseType_t) + uiLength; /* Add channel (sizeof(void*)) */ + + if (xChannel == 0) + { + if (pxPrintInfo->defaultChannel == 0) + { + /* Channel is not present */ + if (xTraceStringRegister("Default", &pxPrintInfo->defaultChannel) == TRC_FAIL) + { + return TRC_FAIL; + } + } + + xChannel = pxPrintInfo->defaultChannel; + } + + /* Added channel to uiEventCode and uiSize */ + if (xTraceEventBegin(uiEventCode, uiSize , &xEventHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + /* Add xChannel */ + xTraceEventAddPointer(xEventHandle, (void*)xChannel); + + /* Add all arguments */ + for (i = 0; i < uiArgs; i++) + { + xTraceEventAddUnsignedBaseType(xEventHandle, va_arg(*pxVL, TraceUnsignedBaseType_t)); + } + + xTraceEventPayloadRemaining(xEventHandle, &uiRemaining); + if (uiRemaining < uiLength) + { + uiLength = uiRemaining - 1; /* Make room for null termination */ + } + + /* Add format string */ + xTraceEventAddData(xEventHandle, (void*)szFormat, uiLength); + + /* Check if we can truncate */ + xTraceEventPayloadRemaining(xEventHandle, &uiValue); + if (uiValue > 0) + { + xTraceEventAdd8(xEventHandle, 0); + } + + xTraceEventEnd(xEventHandle); + + return TRC_SUCCESS; +} + +#endif /* (TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#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 ef49f2de76..f6c69f6f59 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c @@ -1,3074 +1,3317 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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)*/ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The generic core of the trace recorder's snapshot mode. + */ + +#include + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#include +#include + +#ifndef TRC_CFG_RECORDER_DATA_INIT +#define TRC_CFG_RECORDER_DATA_INIT 1 +#endif + +#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 7 + +/* Keeps track of the task's stack low mark */ +typedef struct { + void* tcb; + uint32_t uiPreviousLowMark; +} TaskStackMonitorEntry_t; + +TraceKernelPortDataBuffer_t xKernelPortDataBuffer; + +#if (TRC_CFG_INCLUDE_ISR_TRACING == 1) +/******************************************************************************* +* isrstack +* +* Keeps track of nested interrupts. +******************************************************************************/ +static traceHandle isrstack[TRC_CFG_MAX_ISR_NESTING]; + +/******************************************************************************* +* isPendingContextSwitch +* +* Used to indicate if there is a pending context switch. +* If there is a pending context switch the recorder will not create an event +* when returning from the ISR. +******************************************************************************/ +int32_t isPendingContextSwitch = 0; +#endif /* (TRC_CFG_INCLUDE_ISR_TRACING == 1) */ + +/******************************************************************************* +* readyEventsEnabled +* +* This can be used to dynamically disable ready events. +******************************************************************************/ +#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; + +/******************************************************************************* +* trace_disable_timestamp +* +* This can be used to disable timestamps as it will cause +* prvTracePortGetTimeStamp() to return the previous timestamp. +******************************************************************************/ +uint32_t trace_disable_timestamp = 0; + +/******************************************************************************* +* last_timestamp +* +* The most recent timestamp. +******************************************************************************/ +static uint32_t last_timestamp = 0; + +/******************************************************************************* +* uiTraceSystemState +* +* Indicates if we are currently performing a context switch or just running application code. +******************************************************************************/ +volatile uint32_t uiTraceSystemState = TRC_STATE_IN_STARTUP; + +/******************************************************************************* +* recorder_busy +* +* Flag that shows if inside a critical section of the recorder. +******************************************************************************/ +volatile int recorder_busy = 0; + +/******************************************************************************* +* timestampFrequency +* +* Holds the value set by vTraceSetFrequency. +******************************************************************************/ +uint32_t timestampFrequency = 0; + +/******************************************************************************* +* nISRactive +* +* The number of currently active (including preempted) ISRs. +******************************************************************************/ +int8_t nISRactive = 0; + +/******************************************************************************* +* handle_of_last_logged_task +* +* The current task. +******************************************************************************/ +traceHandle handle_of_last_logged_task = 0; + +/******************************************************************************* +* vTraceStopHookPtr +* +* Called when the recorder is stopped, set by vTraceSetStopHook. +******************************************************************************/ +TRACE_STOP_HOOK vTraceStopHookPtr = (TRACE_STOP_HOOK)0; + +/******************************************************************************* +* init_hwtc_count +* +* 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; + +/******************************************************************************* +* CurrentFilterMask +* +* The filter mask that will be checked against each object's FilterGroup to see +* if they should be included in the trace or not. +******************************************************************************/ +uint16_t CurrentFilterMask TRC_CFG_RECORDER_DATA_ATTRIBUTE; + +/******************************************************************************* +* CurrentFilterGroup +* +* The current filter group that will be assigned to newly created objects. +******************************************************************************/ +uint16_t CurrentFilterGroup TRC_CFG_RECORDER_DATA_ATTRIBUTE; + +/******************************************************************************* +* objectHandleStacks +* +* 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 TRC_CFG_RECORDER_DATA_ATTRIBUTE; + +/******************************************************************************* +* traceErrorMessage +* +* The last error message of the recorder. NULL if no error message. +******************************************************************************/ +const char* traceErrorMessage TRC_CFG_RECORDER_DATA_ATTRIBUTE; + +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) +/******************************************************************************* +* tasksInStackMonitor +* +* Keeps track of all stack low marks for tasks. +******************************************************************************/ +TaskStackMonitorEntry_t tasksInStackMonitor[TRC_CFG_STACK_MONITOR_MAX_TASKS] TRC_CFG_RECORDER_DATA_ATTRIBUTE; + +/******************************************************************************* +* tasksNotIncluded +* +* The number of tasks that did not fit in the stack monitor. +******************************************************************************/ +int tasksNotIncluded TRC_CFG_RECORDER_DATA_ATTRIBUTE; +#endif /* defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ + +/******************************************************************************* +* 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 TRC_CFG_RECORDER_DATA_ATTRIBUTE; +#endif + +/* Pointer to the main data structure, when in snapshot mode */ +RecorderDataType* RecorderDataPtr TRC_CFG_RECORDER_DATA_ATTRIBUTE; + +#if (TRC_CFG_RECORDER_DATA_INIT != 0) +uint32_t RecorderInitialized = 0; +#else /* (TRC_CFG_RECORDER_DATA_INIT != 0) */ +uint32_t RecorderInitialized TRC_CFG_RECORDER_DATA_ATTRIBUTE; +#endif /* (TRC_CFG_RECORDER_DATA_INIT != 0) */ + +/*************** 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 TraceStringHandle_t prvTraceOpenSymbol(const char* name, TraceStringHandle_t 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 TraceStringHandle_t prvTraceCreateSymbolTableEntry(const char* name, + uint8_t crc6, + uint8_t len, + TraceStringHandle_t channel); + +static TraceStringHandle_t prvTraceLookupSymbolTableEntry(const char* name, + uint8_t crc6, + uint8_t len, + TraceStringHandle_t 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_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); + +/******************************************************************************* +* prvTraceInitTimestamps +* +* This will only be called once the recorder is started, and we can assume that +* all hardware has been initialized. +******************************************************************************/ +static void prvTraceInitTimestamps(void); + +static void prvTraceStart(void); + +static void prvTraceStop(void); + +#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, TraceStringHandle_t eventLabel, TraceStringHandle_t 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)) */ + +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); + +/********* Public Functions **************************************************/ + +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) +traceResult xTraceSetBuffer(TraceRecorderDataBuffer_t* pxBuffer) +{ + if (pxBuffer == 0) + { + return TRC_FAIL; + } + + RecorderDataPtr = (RecorderDataType*)pxBuffer; + + return TRC_SUCCESS; +} +#endif + +traceResult xTraceGetEventBuffer(void** ppvBuffer, TraceUnsignedBaseType_t* puiSize) +{ + if (ppvBuffer == 0 || puiSize == 0) + { + return TRC_FAIL; + } + + *ppvBuffer = (void*)RecorderDataPtr; + *puiSize = sizeof(RecorderDataType); + + return TRC_SUCCESS; +} + +traceResult xTraceEnable(uint32_t uiStartOption) +{ + /* Make sure recorder data is initialized */ + if (xTraceInitialize() == TRC_FAIL) + { + return TRC_FAIL; + } + + if (uiStartOption == TRC_START) + { + if (xTraceKernelPortEnable() == TRC_FAIL) + { + return TRC_FAIL; + } + + prvTraceInitTimestamps(); + + prvTraceStart(); + } + else if (uiStartOption == TRC_START_AWAIT_HOST) + { + prvTraceError("xTraceEnable(TRC_START_AWAIT_HOST) not allowed in Snapshot mode"); + + return TRC_FAIL; + } + else if (uiStartOption != TRC_START_FROM_HOST) + { + prvTraceError("xTraceEnable(TRC_START_FROM_HOST) not allowed in Snapshot mode"); + + return TRC_FAIL; + } + + return TRC_SUCCESS; +} + + +traceResult xTraceDisable(void) +{ + prvTraceStop(); + + return TRC_SUCCESS; +} + +void vTraceSetStopHook(TRACE_STOP_HOOK stopHookFunction) +{ + vTraceStopHookPtr = stopHookFunction; +} + +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 = 0; + RecorderDataPtr->internalErrorOccured = 0; + (void)memset(RecorderDataPtr->eventData, 0, RecorderDataPtr->maxEvents * 4); + handle_of_last_logged_task = 0; + trcCRITICAL_SECTION_END(); +} + +static void prvTraceStart(void) +{ + traceHandle handle; + TRACE_ALLOC_CRITICAL_SECTION(); + + handle = 0; + + if (RecorderDataPtr == 0) + { + TRACE_ASSERT(RecorderDataPtr != 0, "Recorder not initialized. Use vTraceEnable() instead!", TRC_UNUSED); + return; + } + + if (RecorderDataPtr->recorderActive == 1) + return; /* Already running */ + + if (traceErrorMessage == 0) + { + 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(); + } +} + +/******************************************************************************* + * prvTraceStop + * + * Stops the recorder. The recording can be resumed by calling vTraceStart. + * This does not reset the recorder. Use vTraceClear if that is desired. + ******************************************************************************/ +static void prvTraceStop(void) +{ + if (RecorderDataPtr != 0) + { + RecorderDataPtr->recorderActive = 0; + } + + if (vTraceStopHookPtr != (TRACE_STOP_HOOK)0) + { + (*vTraceStopHookPtr)(); /* An application call-back function. */ + } +} + +/******************************************************************************* +* xTraceIsRecorderEnabled +* Returns true (1) if the recorder is enabled (i.e. is recording), otherwise 0. +******************************************************************************/ +uint32_t xTraceIsRecorderEnabled(void) +{ + if (RecorderInitialized == 1 && RecorderDataPtr != 0) + { + return RecorderDataPtr->recorderActive; + } + else + { + return 0; + } +} + +/****************************************************************************** +* xTraceIsRecorderInitialized +* +* Returns true (1) if the recorder is initialized. +******************************************************************************/ +uint32_t xTraceIsRecorderInitialized(void) +{ + return RecorderInitialized; +} + +/******************************************************************************* + * xTraceErrorGetLast + * + * 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* xTraceErrorGetLast(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 = 0; + if (RecorderDataPtr != 0) + { + 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); +} + +/******************************************************************************* +* prvTraceInitTimestamps +* +* If vTraceEnable(TRC_INIT) was called BEFORE the clock was initialized, this +* function must be called AFTER the clock is initialized to set a proper +* initial timestamp value. If vTraceEnable(...) is only called AFTER clock is +* initialized, there is no need to call this function. +******************************************************************************/ +static void prvTraceInitTimestamps(void) +{ + init_hwtc_count = TRC_HWTC_COUNT; +} + +/****************************************************************************** + * 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 != 0) + { + if (direct == 0) + tis->type = TASK_INSTANCE_FINISHED_NEXT_KSE; + else + tis->type = TASK_INSTANCE_FINISHED_DIRECT; + + tis->dts = dts45; + prvTraceUpdateCounters(); + } + } + trcCRITICAL_SECTION_END(); +} + +/****************************************************************************** + * xTraceTaskInstanceFinishedNext(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); + * xTraceTaskInstanceFinishedNext(); + * } + *****************************************************************************/ +traceResult xTraceTaskInstanceFinishedNext(void) +{ + prvTraceTaskInstanceFinish(0); + + return TRC_SUCCESS; +} + +/****************************************************************************** + * xTraceTaskInstanceFinishedNow(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 xTraceTaskInstanceFinishedNow(), while the second + * instance ends at the next xQueueReceive call. + * + * while (1) + * { + * xQueueReceive(CommandQueue, &command, timeoutDuration); + * ProcessCommand(command); + * xTraceTaskInstanceFinishedNow(); + * DoSometingElse(); + * xTraceTaskInstanceFinishedNext(); + * } + *****************************************************************************/ +traceResult xTraceTaskInstanceFinishedNow(void) +{ + prvTraceTaskInstanceFinish(1); + + return TRC_SUCCESS; +} + +/******************************************************************************* + * 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 != 0, "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 != 0, "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 != 0) + { + 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? If so, we will not create an event since we will get an event when that context switch is executed. */ + 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) || (xTraceKernelPortIsSchedulerSuspended())) + { + /* 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 != 0) + { + 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 != 0, "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 != 0, "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 != 0, "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 != 0, "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 != 0, "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': + { + TraceStringHandle_t xString; + xTraceStringRegister((char*)va_arg(vl, char*), &xString); + + i = writeInt16(buffer, + i, + (uint16_t)xString); + } + 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 + default: + break; + } + 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; + + default: + 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; + + default: + break; + } + break; + default: + /* False alarm: this wasn't a valid format specifier */ + argCounter--; + break; + } + + if (argCounter > 15) + { + prvTraceError("xTracePrintF - Too many arguments, max 15 allowed!"); + return 0; + } + } + else + break; + } + formatStrIndex++; + if (i == 255) + { + prvTraceError("xTracePrintF - 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 != 0, + "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, TraceStringHandle_t eventLabel, TraceStringHandle_t 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(TraceStringHandle_t channel, TraceStringHandle_t 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 xTracePrintF() 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) +{ + TraceStringHandle_t channel; + TraceStringHandle_t 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 + +/****************************************************************************** + * xTracePrintF + * + * 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 xTraceStringRegister. + * Example: + * + * TraceStringHandle_t adc_uechannel; + * xTraceStringRegister("ADC User Events", &adc_uechannel); + * ... + * xTracePrintF(adc_uechannel, + * "ADC channel %d: %lf volts", + * ch, (double)adc_reading/(double)scale); + * + * Calling xTraceStringRegister 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 xTracePrint - 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)) +traceResult xTracePrintF(TraceStringHandle_t eventLabel, const char* formatStr, ...) +{ + va_list vl; + + va_start(vl, formatStr); + xTraceVPrintF(eventLabel, formatStr, vl); + va_end(vl); + + return TRC_SUCCESS; +} +#endif + +/****************************************************************************** + * xTraceVPrintF + * + * xTracePrintF variant that accepts a va_list. + * See xTracePrintF documentation for further details. + * + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +traceResult xTraceVPrintF(TraceStringHandle_t 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 != 0, "vTraceVPrintF: formatStr == NULL", TRC_FAIL); + + 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 */ + TraceStringHandle_t formatLabel; + traceUBChannel channel; + + if (RecorderDataPtr->recorderActive && handle_of_last_logged_task) + { + xTraceStringRegister(formatStr, &formatLabel); + + channel = xTraceRegisterUBChannel(eventLabel, formatLabel); + + prvTraceUBHelper1(channel, eventLabel, formatLabel, vl); + } +#endif + + return TRC_SUCCESS; +} +#endif + +/****************************************************************************** + * xTracePrint + * + * Basic user event + * + * Generates a User Event with a text label. The label is created/looked up + * in the symbol table using xTraceStringRegister. + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +traceResult xTracePrint(TraceStringHandle_t 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 != 0) + { + 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) + { + TraceStringHandle_t 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 + + return TRC_SUCCESS; +} +#endif + +/******************************************************************************* + * xTraceStringRegister + * + * Register strings in the recorder, e.g. for names of user event channels. + * + * Example: + * xTraceStringRegister("MyUserEvent", &myStringHandle); + * ... + * xTracePrintF(myEventHandle, "My value is: %d", myValue); + ******************************************************************************/ +#if ((TRC_CFG_SCHEDULING_ONLY == 0) && (TRC_CFG_INCLUDE_USER_EVENTS == 1)) +traceResult xTraceStringRegister(const char* label, TraceStringHandle_t *pxString) +{ + TRACE_ASSERT(label != 0, "xTraceStringRegister: label == NULL", TRC_FAIL); + TRACE_ASSERT(RecorderDataPtr != 0, "Recorder not initialized, call vTraceEnable() first!", TRC_FAIL); + + *pxString = prvTraceOpenSymbol(label, 0); + + return TRC_SUCCESS; +} + +/* DEPRECATED */ +TraceStringHandle_t xTraceRegisterString(const char* name) +{ + TraceStringHandle_t trcStr = 0; + xTraceStringRegister(name, &trcStr); + + return trcStr; +} +#endif + +traceResult xTraceInitialize() +{ +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) + uint32_t i; +#endif /* defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ + + if (RecorderInitialized != 0) + { + return TRC_SUCCESS; + } + + /* These are set on init so they aren't overwritten by late initialization values. */ + CurrentFilterMask = 0xFFFF; + CurrentFilterGroup = FilterGroup0; + traceErrorMessage = 0; + +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) + tasksNotIncluded = 0; + + for (i = 0; i < TRC_CFG_STACK_MONITOR_MAX_TASKS; i++) + { + tasksInStackMonitor[i].tcb = 0; + tasksInStackMonitor[i].uiPreviousLowMark = 0; + } +#endif /* defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0) */ + +#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 TRC_FAIL; + } +#elif (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) + if (!RecorderDataPtr) + { + prvTraceError("Recorder data pointer not set! Use vTraceSetRecorderDataBuffer()."); + return TRC_FAIL; + } +#endif + + init_hwtc_count = TRC_HWTC_COUNT; + + if (xTraceKernelPortInitialize(&xKernelPortDataBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + (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 */ + xTraceKernelPortInitObjectPropertyTable(); + + 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 */ + xTraceKernelPortInitObjectHandleStack(); + + + /* 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 != 0) + { + // 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; + prvTraceStop(); + } + +#ifdef TRC_PORT_SPECIFIC_INIT + TRC_PORT_SPECIFIC_INIT(); +#endif + + RecorderInitialized = 1; + + return TRC_SUCCESS; +} + +#if ((!defined TRC_CFG_INCLUDE_READY_EVENTS) || (TRC_CFG_INCLUDE_READY_EVENTS == 1)) + +void prvTraceSetReadyEventsEnabled(uint32_t flag) +{ + readyEventsEnabled = flag; +} + +/******************************************************************************* + * 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 != 0) + { + 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 != 0) + { + 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 == 0) + { + /* 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) + { + RecorderDataPtr->heapMemUsage += (uint32_t)signed_size; + + if (RecorderDataPtr->heapMemUsage > RecorderDataPtr->heapMemMaxUsage) + { + RecorderDataPtr->heapMemMaxUsage = RecorderDataPtr->heapMemUsage; + } + } + + if (RecorderDataPtr->recorderActive) + { + dts1 = (uint8_t)prvTraceGetDTS(0xFF); + size_low = (uint16_t)prvTraceGetParam(0xFFFF, size); + ms = (MemEventSize *)prvTraceNextFreeEventBufferSlot(); + + if (ms != 0) + { + 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 != 0) + { + ma->addr_low = addr_low; + ma->addr_high = addr_high; + ma->type = (uint8_t) (ecode + 1); /* Note this! */ + ms->type = (uint8_t) ecode; /* Set type of first event */ + prvTraceUpdateCounters(); + } + } + } + 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(); + + /* Avoids warnings when asserts are disabled */ + (void)objectClass; + + 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 != 0) + { + 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(); + + /* Avoids warnings when asserts are disabled */ + (void)objectClass; + + 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 != 0) + { + 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 != 0) + { + 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 != 0) + { + 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 != 0) + { + 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; + TraceStringHandle_t 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 != 0) + { + 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 != 0) + { + 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) +{ + /* Avoids warnings when asserts are disabled */ + (void)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 +} + +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 0; + } + + if (RecorderDataPtr->nextFreeIndex >= (TRC_CFG_EVENT_BUFFER_SIZE)) + { + prvTraceError("Attempt to index outside event buffer!"); + return 0; + } + return (void*)(&RecorderDataPtr->eventData[RecorderDataPtr->nextFreeIndex*4]); +} + +uint16_t uiIndexOfObject(traceHandle objecthandle, uint8_t objectclass) +{ + uint16_t index; + 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])) + { + index = (uint16_t)(RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[objectclass] + + (RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[objectclass] * (objecthandle - 1))); + return index; + } + + 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 != 0, "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(RecorderDataPtr != 0, "Recorder not initialized, call vTraceEnable() first!", TRC_UNUSED); + 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; + + if (name == 0) + { + name = ""; + } + + 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 == 0) + { + prvStrncpy((char*)&(RecorderDataPtr->ObjectPropertyTable.objbytes[idx]), + name, + RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[ objectclass ]); + } + } +} + +TraceStringHandle_t prvTraceOpenSymbol(const char* name, TraceStringHandle_t userEventChannel) +{ + uint16_t result; + uint8_t len; + uint8_t crc; + TRACE_ALLOC_CRITICAL_SECTION(); + + len = 0; + crc = 0; + + TRACE_ASSERT(name != 0, "prvTraceOpenSymbol: name == NULL", (TraceStringHandle_t)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 xTraceErrorGetLast() + * 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 != 0) + { + xTraceDisable(); + } + + /* If first error only... */ + if (traceErrorMessage == 0) + { + traceErrorMessage = (char*)(intptr_t) msg; + if (RecorderDataPtr != 0) + { + 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 != 0) + { + 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 xTracePrintF + * format strings only (the handle of the destination channel). + * byte 4..(4 + length): the string (object name or user event label), with + * zero-termination + ******************************************************************************/ +TraceStringHandle_t prvTraceLookupSymbolTableEntry(const char* name, + uint8_t crc6, + uint8_t len, + TraceStringHandle_t chn) +{ + uint16_t i = RecorderDataPtr->SymbolTable.latestEntryOfChecksum[ crc6 ]; + + TRACE_ASSERT(name != 0, "prvTraceLookupSymbolTableEntry: name == NULL", (TraceStringHandle_t)0); + TRACE_ASSERT(len != 0, "prvTraceLookupSymbolTableEntry: len == 0", (TraceStringHandle_t)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 xTracePrintF + * format strings only (the handle of the destination channel). + * byte 4..(4 + length): the string (object name or user event label), with + * zero-termination + ******************************************************************************/ +TraceStringHandle_t prvTraceCreateSymbolTableEntry(const char* name, + uint8_t crc6, + uint8_t len, + TraceStringHandle_t channel) +{ + TraceStringHandle_t ret = 0; + + TRACE_ASSERT(name != 0, "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 != 0, "prvTraceGetChecksum: pname == NULL", TRC_UNUSED); + TRACE_ASSERT(pcrc != 0, "prvTraceGetChecksum: pcrc == NULL", TRC_UNUSED); + TRACE_ASSERT(plength != 0, "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 != 0) + { + 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 xTraceHardwarePortInitCortexM() +{ + /* 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; +} + +#if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 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 == 0) + { + 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 = 0; + 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 != 0) + { + /* Get the amount of unused stack */ + uint32_t unusedStackSpace; + xTraceKernelPortGetUnusedStack(tasksInStackMonitor[i].tcb, &unusedStackSpace); + + /* Store for later use */ + if (tasksInStackMonitor[i].uiPreviousLowMark > unusedStackSpace) + tasksInStackMonitor[i].uiPreviousLowMark = unusedStackSpace; + + prvTraceStoreKernelCallWithParam(TRACE_UNUSED_STACK, TRACE_CLASS_TASK, TRACE_GET_TASK_NUMBER(tasksInStackMonitor[i].tcb), tasksInStackMonitor[i].uiPreviousLowMark); + + 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) */ + + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStackMonitor.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStackMonitor.c new file mode 100644 index 0000000000..ea8ceba0c0 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStackMonitor.c @@ -0,0 +1,218 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for the stack monitor. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#if (((TRC_CFG_ENABLE_STACK_MONITOR) == 1) && ((TRC_CFG_SCHEDULING_ONLY) == 0)) + +typedef struct TraceStackMonitorEntry +{ + void *pvTask; + TraceUnsignedBaseType_t uxPreviousLowWaterMark; +} TraceStackMonitorEntry_t; + +typedef struct TraceStackMonitor +{ + TraceStackMonitorEntry_t xEntries[TRC_CFG_STACK_MONITOR_MAX_TASKS]; + + uint32_t uiEntryCount; +} TraceStackMonitor_t; + +static TraceStackMonitor_t* pxStackMonitor; + +traceResult xTraceStackMonitorInitialize(TraceStackMonitorBuffer_t *pxBuffer) +{ + uint32_t i; + + TRC_ASSERT_EQUAL_SIZE(TraceStackMonitorBuffer_t, TraceStackMonitor_t); + + /* This should never fail */ + TRC_ASSERT(pxBuffer != 0); + + pxStackMonitor = (TraceStackMonitor_t*)pxBuffer; + + pxStackMonitor->uiEntryCount = 0; + + for (i = 0; i < (TRC_CFG_STACK_MONITOR_MAX_TASKS); i++) + { + pxStackMonitor->xEntries[i].pvTask = 0; + } + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_STACK_MONITOR); + + return TRC_SUCCESS; +} + +traceResult xTraceStackMonitorAdd(void *pvTask) +{ + TraceUnsignedBaseType_t uxLowMark; + + TRACE_ALLOC_CRITICAL_SECTION(); + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_STACK_MONITOR)); + + if (pvTask == 0) + { + /* We don't add null addresses */ + return TRC_FAIL; + } + + TRACE_ENTER_CRITICAL_SECTION(); + + if (pxStackMonitor->uiEntryCount >= (TRC_CFG_STACK_MONITOR_MAX_TASKS)) + { + xTraceDiagnosticsIncrease(TRC_DIAGNOSTICS_STACK_MONITOR_NO_SLOTS); + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; + } + + if (xTraceKernelPortGetUnusedStack(pvTask, &uxLowMark) == TRC_SUCCESS) + { + pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount].pvTask = pvTask; + pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount].uxPreviousLowWaterMark = uxLowMark; + + pxStackMonitor->uiEntryCount++; + } + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_SUCCESS; +} + +traceResult xTraceStackMonitorRemove(void* pvTask) +{ + uint32_t i; + + TRACE_ALLOC_CRITICAL_SECTION(); + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_STACK_MONITOR)); + + if (pvTask == 0) + { + /* We don't add null addresses */ + return TRC_FAIL; + } + + TRACE_ENTER_CRITICAL_SECTION(); + + for (i = 0; i < pxStackMonitor->uiEntryCount; i++) + { + if (pxStackMonitor->xEntries[i].pvTask == pvTask) + { + if (pxStackMonitor->uiEntryCount > 1 && i != (pxStackMonitor->uiEntryCount - 1)) + { + /* There are more entries and this is NOT the last entry. Move last entry to this slot. */ + pxStackMonitor->xEntries[i].pvTask = pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount - 1].pvTask; + pxStackMonitor->xEntries[i].uxPreviousLowWaterMark = pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount - 1].uxPreviousLowWaterMark; + + /* Clear old entry that was moved */ + pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount - 1].pvTask = 0; + pxStackMonitor->xEntries[pxStackMonitor->uiEntryCount - 1].uxPreviousLowWaterMark = 0; + } + else + { + /* No other entries or last entry. */ + pxStackMonitor->xEntries[i].pvTask = 0; + pxStackMonitor->xEntries[i].uxPreviousLowWaterMark = 0; + } + + pxStackMonitor->uiEntryCount--; + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_SUCCESS; + } + } + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_FAIL; +} + +traceResult xTraceStackMonitorGetAtIndex(uint32_t uiIndex, void **ppvTask, TraceUnsignedBaseType_t *puxLowWaterMark) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_STACK_MONITOR)); + + /* This should never fail */ + TRC_ASSERT(ppvTask != 0); + + /* This should never fail */ + TRC_ASSERT(puxLowWaterMark != 0); + + /* This should never fail */ + TRC_ASSERT(uiIndex < (TRC_CFG_STACK_MONITOR_MAX_TASKS)); + + *ppvTask = pxStackMonitor->xEntries[uiIndex].pvTask; + *puxLowWaterMark = pxStackMonitor->xEntries[uiIndex].uxPreviousLowWaterMark; + + return TRC_SUCCESS; +} + +traceResult xTraceStackMonitorReport(void) +{ + TraceUnsignedBaseType_t uxLowWaterMark; + TraceEventHandle_t xEventHandle = 0; + TraceStackMonitorEntry_t *pxStackMonitorEntry; + uint32_t uiToReport; + uint32_t i; + static uint32_t uiCurrentIndex = 0; + + TRACE_ALLOC_CRITICAL_SECTION(); + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_STACK_MONITOR)); + + TRACE_ENTER_CRITICAL_SECTION(); + + /* Never report more than there are entries */ + uiToReport = TRC_CFG_STACK_MONITOR_MAX_REPORTS <= pxStackMonitor->uiEntryCount ? TRC_CFG_STACK_MONITOR_MAX_REPORTS : pxStackMonitor->uiEntryCount; + + for (i = 0; i < uiToReport; i++) + { + /* If uiCurrentIndex is too large, reset it */ + uiCurrentIndex = uiCurrentIndex < pxStackMonitor->uiEntryCount ? uiCurrentIndex : 0; + + pxStackMonitorEntry = &pxStackMonitor->xEntries[uiCurrentIndex]; + + xTraceKernelPortGetUnusedStack(pxStackMonitorEntry->pvTask, &uxLowWaterMark); + + if (uxLowWaterMark < pxStackMonitorEntry->uxPreviousLowWaterMark) + { + pxStackMonitorEntry->uxPreviousLowWaterMark = uxLowWaterMark; + } + + if (xTraceEventBegin(PSF_EVENT_UNUSED_STACK, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, pxStackMonitorEntry->pvTask); + xTraceEventAdd32(xEventHandle, (uint32_t)pxStackMonitorEntry->uxPreviousLowWaterMark); + xTraceEventEnd(xEventHandle); + } + + uiCurrentIndex++; + } + + TRACE_EXIT_CRITICAL_SECTION(); + + return TRC_SUCCESS; +} +#endif /* (((TRC_CFG_ENABLE_STACK_MONITOR) == 1) && ((TRC_CFG_SCHEDULING_ONLY) == 0)) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStateMachine.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStateMachine.c new file mode 100644 index 0000000000..7504746a3e --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStateMachine.c @@ -0,0 +1,99 @@ +/* +* Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation of state machines. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#define TRC_STATE_MACHINE_STATE_INDEX 0 +#define TRC_STATE_MACHINE_INDEX 0 + +traceResult xTraceStateMachineCreate(const char *szName, TraceStateMachineHandle_t *pxStateMachineHandle) +{ + TraceObjectHandle_t xObjectHandle; + + /* This should never fail */ + TRC_ASSERT(pxStateMachineHandle != 0); + + /* We need to check this */ + if (xTraceObjectRegister(PSF_EVENT_STATEMACHINE_CREATE , 0, szName, 0, &xObjectHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetOptions((TraceEntryHandle_t)xObjectHandle, (uint32_t)TRC_ENTRY_OPTION_STATE_MACHINE) == TRC_SUCCESS); + + *pxStateMachineHandle = (TraceStateMachineHandle_t)xObjectHandle; + + return TRC_SUCCESS; +} + +traceResult xTraceStateMachineStateCreate(TraceStateMachineHandle_t xStateMachineHandle, const char* szName, TraceStateMachineStateHandle_t* pxStateHandle) +{ + TraceObjectHandle_t xObjectHandle; + + /* This should never fail */ + TRC_ASSERT(xStateMachineHandle != 0); + + /* This should never fail */ + TRC_ASSERT(pxStateHandle != 0); + + /* We need to check this */ + if (xTraceObjectRegister(PSF_EVENT_STATEMACHINE_STATE_CREATE, 0, szName, (TraceUnsignedBaseType_t)xStateMachineHandle, &xObjectHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetOptions((TraceEntryHandle_t)xObjectHandle, (uint32_t)TRC_ENTRY_OPTION_STATE_MACHINE_STATE) == TRC_SUCCESS); + + *pxStateHandle = (TraceStateMachineHandle_t)xObjectHandle; + + return TRC_SUCCESS; +} + +traceResult xTraceStateMachineSetState(TraceStateMachineHandle_t xStateMachineHandle, TraceStateMachineStateHandle_t xStateHandle) +{ + TraceEventHandle_t xEventHandle = 0; + TraceUnsignedBaseType_t uxStateMachine; + + /* This should never fail */ + TRC_ASSERT(xStateMachineHandle != 0); + + /* This should never fail */ + TRC_ASSERT(xStateHandle != 0); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetState((TraceEntryHandle_t)xStateHandle, TRC_STATE_MACHINE_INDEX, &uxStateMachine) == TRC_SUCCESS); + + /* Verify that this state machine state was meant to be used with this state machine */ + /* This should never fail */ + TRC_ASSERT(xStateMachineHandle == (TraceStateMachineHandle_t)uxStateMachine); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState((TraceEntryHandle_t)xStateMachineHandle, TRC_STATE_MACHINE_STATE_INDEX, (TraceUnsignedBaseType_t)xStateHandle) == TRC_SUCCESS); + + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_STATEMACHINE_STATECHANGE, sizeof(void*) + sizeof(void*), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, (void*)xStateMachineHandle); + xTraceEventAddPointer(xEventHandle, (void*)xStateHandle); + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStaticBuffer.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStaticBuffer.c new file mode 100644 index 0000000000..e6fbf5b7cc --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStaticBuffer.c @@ -0,0 +1,57 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for the static buffer. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +TraceStaticBufferTable_t *pxTraceStaticBufferTable; + +traceResult xTraceStaticBufferInitialize(TraceStaticBufferBuffer_t *pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceStaticBufferBuffer_t, TraceStaticBufferTable_t); + + /* This should never fail */ + TRC_ASSERT(pxBuffer != 0); + + pxTraceStaticBufferTable = (TraceStaticBufferTable_t*)pxBuffer; + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_STATIC_BUFFER); + + return TRC_SUCCESS; +} + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +/* Returns a pointer to a maximum sized static buffer */ +traceResult xTraceStaticBufferGet(void **ppvBuffer) +{ + int32_t ISR_nesting; + + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_STATIC_BUFFER)); + + TRC_ASSERT(ppvBuffer != 0); + + TRC_ASSERT(xTraceISRGetCurrentNesting(&ISR_nesting) == TRC_SUCCESS); + + /* Task dummy events begin at 0, ISR dummy events begin at index 1 */ + *ppvBuffer = (void*)&pxTraceStaticBufferTable->coreDummyEvents[TRC_CFG_GET_CURRENT_CORE()].dummyEvents[ISR_nesting + 1]; + + return TRC_SUCCESS; +} + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c index 5526530a2d..e9f9a74b14 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c @@ -1,2035 +1,596 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.4.0 - * 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)*/ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * The generic core of the trace recorder's streaming mode. + */ + +#include + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +typedef struct TraceHeader +{ + uint32_t uiPSF; + uint16_t uiVersion; + uint16_t uiPlatform; + uint32_t uiOptions; + uint32_t uiNumCores; + uint32_t isrTailchainingThreshold; + char platformCfg[8]; + uint16_t uiPlatformCfgPatch; + uint8_t uiPlatformCfgMinor; + uint8_t uiPlatformCfgMajor; +} TraceHeader_t; + +/* The data structure for commands (a bit overkill) */ +typedef struct TraceCommandType_t +{ + unsigned char cmdCode; + unsigned char param1; + unsigned char param2; + unsigned char param3; + unsigned char param4; + unsigned char param5; + unsigned char checksumLSB; + unsigned char checksumMSB; +} TraceCommand_t; + +#ifndef TRC_CFG_RECORDER_DATA_INIT +#define TRC_CFG_RECORDER_DATA_INIT 1 +#endif + +/* Used to interpret the data format */ +#define TRACE_FORMAT_VERSION ((uint16_t)0x000A) + +/* Used to determine endian of data (big/little) */ +#define TRACE_PSF_ENDIANESS_IDENTIFIER ((uint32_t)0x50534600) + +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC) +static TraceRecorderData_t xRecorderData TRC_CFG_RECORDER_DATA_ATTRIBUTE; +TraceRecorderData_t* pxTraceRecorderData = &xRecorderData; +#else +/* If using DYNAMIC or CUSTOM allocation */ +TraceRecorderData_t* pxTraceRecorderData TRC_CFG_RECORDER_DATA_ATTRIBUTE; +#endif + +static TraceHeader_t* pxHeader; + +/******************************************************************************* +* RecorderInitialized +* +* Makes sure the recorder data is only initialized once. +* +* NOTE: RecorderInitialized is only initialized to 0 if +* TRC_CFG_RECORDER_DATA_INIT is non-zero. +* This will avoid issues where the recorder must be started before main(), +* which can lead to RecorderInitialized be cleared by late initialization after +* xTraceEnable(TRC_INIT) was called and assigned RecorderInitialized its' +* value. +******************************************************************************/ +#if (TRC_CFG_RECORDER_DATA_INIT != 0) +uint32_t RecorderInitialized = 0; +#else /* (TRC_CFG_RECORDER_DATA_INIT != 0) */ +uint32_t RecorderInitialized TRC_CFG_RECORDER_DATA_ATTRIBUTE; +#endif /* (TRC_CFG_RECORDER_DATA_INIT != 0) */ + +#if (TRC_EXTERNAL_BUFFERS == 0) +/* Stores the header information on Start */ +static void prvTraceStoreHeader(void); + +/* Store the Timestamp info */ +static void prvTraceStoreTimestampInfo(void); + +/* Stores the entry table on Start */ +static void prvTraceStoreEntryTable(void); + +#else /* (TRC_EXTERNAL_BUFFERS == 0) */ + +#define prvTraceStoreHeader() +#define prvTraceStoreTimestampInfo() +#define prvTraceStoreEntryTable() + +#endif /* (TRC_EXTERNAL_BUFFERS == 0) */ + +/* Store start event. */ +static void prvTraceStoreStartEvent(void); + +/* Checks if the provided command is a valid command */ +static int prvIsValidCommand(TraceCommand_t* cmd); + +/* Executed the received command (Start or Stop) */ +static void prvProcessCommand(TraceCommand_t* cmd); + +/* Internal function for starting the recorder */ +static void prvSetRecorderEnabled(void); + +/* Internal function for stopping the recorder */ +static void prvSetRecorderDisabled(void); + +/****************************************************************************** +* xTraceInitialize +* +* Initializes the recorder data. +* This function will be called by xTraceEnable(...). +* Only needs to be called manually if traced objects are created before the +* trace recorder can be enabled, at which point make sure to call this function +* as early as possible. +* See TRC_CFG_RECORDER_DATA_INIT in trcConfig.h. +******************************************************************************/ +traceResult xTraceInitialize(void) +{ + TRC_ASSERT_EQUAL_SIZE(TraceRecorderDataBuffer_t, TraceRecorderData_t); + + if (RecorderInitialized != 0) + { + return TRC_SUCCESS; + } + +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC) + pxRecorderData = TRC_MALLOC(sizeof(TraceRecorderData_t)); +#endif + + /* These are set on init so they aren't overwritten by late initialization values. */ + pxTraceRecorderData->uiSessionCounter = 0; + pxTraceRecorderData->uiRecorderEnabled = 0; + pxTraceRecorderData->uiTraceSystemState = TRC_STATE_IN_STARTUP; + +#if (TRC_EXTERNAL_BUFFERS == 0) + if (xTraceHeaderInitialize(&pxTraceRecorderData->xHeaderBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceEntryTableInitialize(&pxTraceRecorderData->xEntryTableBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceTimestampInitialize(&pxTraceRecorderData->xTimestampBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } +#endif + + if (xTraceStackMonitorInitialize(&pxTraceRecorderData->xStackMonitorBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceStreamPortInitialize(&pxTraceRecorderData->xStreamPortBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceAssertInitialize(&pxTraceRecorderData->xAssertBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceDiagnosticsInitialize(&pxTraceRecorderData->xDiagnosticsBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceStaticBufferInitialize(&pxTraceRecorderData->xStaticBufferBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceEventInitialize(&pxTraceRecorderData->xEventDataBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTracePrintInitialize(&pxTraceRecorderData->xPrintBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceErrorInitialize(&pxTraceRecorderData->xErrorBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceISRInitialize(&pxTraceRecorderData->xISRInfoBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceTaskInitialize(&pxTraceRecorderData->xTaskInfoBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + if (xTraceKernelPortInitialize(&pxTraceRecorderData->xKernelPortBuffer) == TRC_FAIL) + { + return TRC_FAIL; + } + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_CORE); + + return TRC_SUCCESS; +} + +traceResult xTraceHeaderInitialize(TraceHeaderBuffer_t *pxBuffer) +{ + uint32_t i; + char* platform_cfg = TRC_PLATFORM_CFG; + + TRC_ASSERT_EQUAL_SIZE(TraceHeaderBuffer_t, TraceHeader_t); + + if (pxBuffer == 0) + { + return TRC_FAIL; + } + + pxHeader = (TraceHeader_t*)pxBuffer; + + pxHeader->uiPSF = TRACE_PSF_ENDIANESS_IDENTIFIER; + pxHeader->uiVersion = TRACE_FORMAT_VERSION; + pxHeader->uiPlatform = TRACE_KERNEL_VERSION; + + for (i = 0; i < TRC_PLATFORM_CFG_LENGTH; i++) + { + pxHeader->platformCfg[i] = platform_cfg[i]; + if (platform_cfg[i] == 0) + { + break; + } + } + pxHeader->uiPlatformCfgPatch = TRC_PLATFORM_CFG_PATCH; + pxHeader->uiPlatformCfgMinor = TRC_PLATFORM_CFG_MINOR; + pxHeader->uiPlatformCfgMajor = TRC_PLATFORM_CFG_MAJOR; + pxHeader->uiNumCores = TRC_CFG_CORE_COUNT; + pxHeader->isrTailchainingThreshold = TRC_CFG_ISR_TAILCHAINING_THRESHOLD; + + /* Lowest bit used for TRC_IRQ_PRIORITY_ORDER */ + pxHeader->uiOptions = ((TRC_IRQ_PRIORITY_ORDER) << 0); + + /* 3rd bit used for TRC_CFG_TEST_MODE */ + pxHeader->uiOptions |= ((TRC_CFG_TEST_MODE) << 2); + + return TRC_SUCCESS; +} + +traceResult xTraceEnable(uint32_t uiStartOption) +{ + TraceCommand_t xCommand; + int32_t iBytes = 0; + + if (xTraceInitialize() == TRC_FAIL) + { + return TRC_FAIL; + } + + xTraceStreamPortOnEnable(uiStartOption); + + if (xTraceKernelPortEnable() == TRC_FAIL) + { + return TRC_FAIL; + } + + if (uiStartOption == TRC_START_AWAIT_HOST) + { + /* We keep trying to read commands from host until the recorder has been started */ + do + { + iBytes = 0; + + if (xTraceStreamPortReadData(&xCommand, sizeof(TraceCommand_t), (int32_t*)&iBytes) == TRC_FAIL) + { + xTraceWarning(TRC_WARNING_STREAM_PORT_READ); + } + + if (iBytes == sizeof(TraceCommand_t)) + { + if (prvIsValidCommand(&xCommand)) + { + if (xCommand.cmdCode == CMD_SET_ACTIVE && xCommand.param1 == 1) + { + /* On start, init and reset the timestamping */ + TRC_PORT_SPECIFIC_INIT(); + } + + prvProcessCommand(&xCommand); + } + } + } while (pxTraceRecorderData->uiRecorderEnabled == 0); + } + else if (uiStartOption == TRC_START) + { + /* We start streaming directly - this assumes that the host interface is ready! */ + TRC_PORT_SPECIFIC_INIT(); + + xCommand.cmdCode = CMD_SET_ACTIVE; + xCommand.param1 = 1; + prvProcessCommand(&xCommand); + } + else if (uiStartOption == TRC_START_FROM_HOST) + { + /* We prepare the system to receive commands from host, but let system resume execution until that happens */ + TRC_PORT_SPECIFIC_INIT(); + } + + return TRC_SUCCESS; +} + +traceResult xTraceDisable(void) +{ + prvSetRecorderDisabled(); + + xTraceStreamPortOnDisable(); + + return TRC_SUCCESS; +} + +#if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM) +traceResult xTraceSetBuffer(TraceRecorderDataBuffer_t* pxBuffer) +{ + if (pxBuffer == 0) + { + return TRC_FAIL; + } + + pxTraceRecorderData = (TraceRecorderData_t*)pxBuffer; + + return TRC_SUCCESS; +} +#endif + +traceResult xTraceGetEventBuffer(void **ppvBuffer, TraceUnsignedBaseType_t *puiSize) +{ + if (pxTraceRecorderData == 0 || ppvBuffer == 0 || puiSize == 0) + { + return TRC_FAIL; + } + + /* Returns the xStreamPortBuffer since that is the one containing trace data */ + *ppvBuffer = (void*)&pxTraceRecorderData->xStreamPortBuffer; + *puiSize = sizeof(pxTraceRecorderData->xStreamPortBuffer); + + return TRC_SUCCESS; +} + +traceResult xTraceTzCtrl(void) +{ + TraceCommand_t xCommand; + int32_t iBytes = 0; + + do + { + /* Listen for new commands */ + iBytes = 0; + if (xTraceStreamPortReadData(&xCommand, sizeof(TraceCommand_t), &iBytes) == TRC_FAIL) + { + /* The connection has failed, stop tracing */ + xTraceDisable(); + + return TRC_FAIL; + } + + if (iBytes == sizeof(TraceCommand_t)) + { + if (prvIsValidCommand(&xCommand)) + { + prvProcessCommand(&xCommand); /* Start or Stop currently... */ + } + } + +#if (TRC_USE_INTERNAL_BUFFER == 1) + xTraceInternalEventBufferTransfer(&iBytes); +#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 (iBytes != 0); + + if (xTraceIsRecorderEnabled()) + { + xTraceDiagnosticsCheckStatus(); + xTraceStackMonitorReport(); + } + + return TRC_SUCCESS; +} + +void vTraceSetFilterGroup(uint16_t filterGroup) +{ + (void)filterGroup; +} + +void vTraceSetFilterMask(uint16_t filterMask) +{ + (void)filterMask; +} + +/******************************************************************************/ +/*** INTERNAL FUNCTIONS *******************************************************/ +/******************************************************************************/ +/* Internal function for starting/stopping the recorder. */ +static void prvSetRecorderEnabled(void) +{ + uint32_t timestampFrequency = 0; + + TRACE_ALLOC_CRITICAL_SECTION(); + + if (pxTraceRecorderData->uiRecorderEnabled == 1) + { + return; + } + + xTraceTimestampGetFrequency(×tampFrequency); + /* If not overridden using xTraceTimestampSetFrequency(...), use default value */ + if (timestampFrequency == 0) + { + timestampFrequency = TRC_HWTC_FREQ_HZ; + xTraceTimestampSetFrequency(timestampFrequency); + } + + TRACE_ENTER_CRITICAL_SECTION(); + + /* If the internal event buffer is used, we must clear it */ + xTraceInternalEventBufferClear(); + + xTraceStreamPortOnTraceBegin(); + + prvTraceStoreHeader(); + prvTraceStoreTimestampInfo(); + prvTraceStoreEntryTable(); + prvTraceStoreStartEvent(); + + pxTraceRecorderData->uiSessionCounter++; + + pxTraceRecorderData->uiRecorderEnabled = 1; + + TRACE_EXIT_CRITICAL_SECTION(); +} + +static void prvSetRecorderDisabled(void) +{ + TRACE_ALLOC_CRITICAL_SECTION(); + + if (pxTraceRecorderData->uiRecorderEnabled == 0) + { + return; + } + + TRACE_ENTER_CRITICAL_SECTION(); + + pxTraceRecorderData->uiRecorderEnabled = 0; + + xTraceStreamPortOnTraceEnd(); + + TRACE_EXIT_CRITICAL_SECTION(); +} + +#if (TRC_EXTERNAL_BUFFERS == 0) +/* Stores the header information on Start */ +static void prvTraceStoreHeader(void) +{ + TraceEventHandle_t xEventHandle; + + if (xTraceEventBeginRawOfflineBlocking(sizeof(TraceHeader_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddData(xEventHandle, pxHeader, sizeof(TraceHeader_t)); + xTraceEventEndOfflineBlocking(xEventHandle); + } +} + +/* Store the Timestamp */ +static void prvTraceStoreTimestampInfo(void) +{ + TraceEventHandle_t xEventHandle; + uint32_t timestampFrequency = 0; + + xTraceTimestampGetFrequency(×tampFrequency); + + if (xTraceEventBeginRawOfflineBlocking(sizeof(TraceTimestampBuffer_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddData(xEventHandle, &pxTraceRecorderData->xTimestampBuffer, sizeof(TraceTimestampBuffer_t)); + xTraceEventEndOfflineBlocking(xEventHandle); + } +} + +/* Stores the entry table on Start */ +static void prvTraceStoreEntryTable(void) +{ + uint32_t i = 0; + TraceEventHandle_t xEventHandle; + TraceEntryHandle_t xEntryHandle; + uint32_t uiEntryCount; + void *pvEntryAddress; + + xTraceEntryGetCount(&uiEntryCount); + + if (xTraceEventBeginRawOfflineBlocking(sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAdd32(xEventHandle, uiEntryCount); + xTraceEventAdd32(xEventHandle, TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE); + xTraceEventAdd32(xEventHandle, TRC_ENTRY_TABLE_STATE_COUNT); + xTraceEventEndOfflineBlocking(xEventHandle); + } + + for (i = 0; i < (TRC_ENTRY_TABLE_SLOTS); i++) + { + xTraceEntryGetAtIndex(i, &xEntryHandle); + xTraceEntryGetAddress(xEntryHandle, &pvEntryAddress); + /* We only send used entry slots */ + if (pvEntryAddress != 0) + { + /* Send entry */ + if (xTraceEventBeginRawOfflineBlocking(sizeof(TraceEntry_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddData(xEventHandle, (void*)xEntryHandle, sizeof(TraceEntry_t)); + xTraceEventEndOfflineBlocking(xEventHandle); + } + } + } +} +#endif /* (TRC_EXTERNAL_BUFFERS == 0) */ + +static void prvTraceStoreStartEvent() +{ + TraceEventHandle_t xEventHandle; + void* pvCurrentTask; + + xTraceTaskGetCurrent(&pvCurrentTask); + + if (xTraceEventBeginOffline(PSF_EVENT_TRACE_START, sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAdd32(xEventHandle, (uint32_t)pvCurrentTask); + xTraceEventEndOffline(xEventHandle); + } +} + +/* Checks if the provided command is a valid command */ +static int prvIsValidCommand(TraceCommand_t* 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) */ +static void prvProcessCommand(TraceCommand_t* cmd) +{ + switch(cmd->cmdCode) + { + case CMD_SET_ACTIVE: + if (cmd->param1 == 1) + { + prvSetRecorderEnabled(); + } + else + { + prvSetRecorderDisabled(); + } + break; + default: + break; + } +} + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ + +#endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcString.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcString.c new file mode 100644 index 0000000000..6182d20afa --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcString.c @@ -0,0 +1,74 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for strings. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +traceResult xTraceStringRegister(const char* szString, TraceStringHandle_t *pString) +{ + TraceEntryHandle_t xEntryHandle; + TraceEventHandle_t xEventHandle = 0; + uint32_t i = 0, uiLength = 0, uiValue = 0; + + /* This should never fail */ + TRC_ASSERT(szString != 0); + + /* This should never fail */ + TRC_ASSERT(pString != 0); + + /* We need to check this */ + if (xTraceEntryCreate(&xEntryHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + /* The address to the available symbol table slot is the address we use */ + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetSymbol(xEntryHandle, szString) == TRC_SUCCESS); + + *pString = (TraceStringHandle_t)xEntryHandle; + + for (i = 0; (szString[i] != 0) && (i < (TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE)); i++) {} + + uiLength = i; + + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_OBJ_NAME, sizeof(void*) + uiLength, &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, (void*)xEntryHandle); + xTraceEventAddData(xEventHandle, (void*)szString, uiLength); + + /* Check if we can truncate */ + xTraceEventPayloadRemaining(xEventHandle, &uiValue); + if (uiValue > 0) + { + xTraceEventAdd8(xEventHandle, 0); + } + + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +TraceStringHandle_t xTraceRegisterString(const char *name) +{ + TraceStringHandle_t trcStr = 0; + xTraceStringRegister(name, &trcStr); + + return trcStr; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcTask.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcTask.c new file mode 100644 index 0000000000..ce89872521 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcTask.c @@ -0,0 +1,193 @@ +/* +* Percepio Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation for tasks. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +/* 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 TRACE_HANDLE_NO_TASK ((void*)2) + +#define TRC_TASK_STATE_INDEX_PRIORITY 0 +#define TRC_TASK_STATE_INDEX_UNUSED_STACK 1 + +TraceTaskInfo_t* pxTraceTaskInfo; + +traceResult xTraceTaskInitialize(TraceTaskInfoBuffer_t *pxBuffer) +{ + uint32_t i; + + TRC_ASSERT_EQUAL_SIZE(TraceTaskInfoBuffer_t, TraceTaskInfo_t); + + /* This should never fail */ + TRC_ASSERT(pxBuffer != 0); + + pxTraceTaskInfo = (TraceTaskInfo_t*)pxBuffer; + + for (i = 0; i < TRC_CFG_CORE_COUNT; i++) + { + pxTraceTaskInfo->coreTasks[i] = TRACE_HANDLE_NO_TASK; + } + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_TASK); + + return TRC_SUCCESS; +} + +traceResult xTraceTaskUnregister(TraceTaskHandle_t xTaskHandle, TraceUnsignedBaseType_t uxPriority) +{ + void* pvTask; + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xTaskHandle, &pvTask) == TRC_SUCCESS); + + xTraceStackMonitorRemove(pvTask); + + return xTraceObjectUnregister((TraceObjectHandle_t)xTaskHandle, PSF_EVENT_TASK_DELETE, uxPriority); +} + +traceResult xTraceTaskSetPriority(TraceTaskHandle_t xTaskHandle, TraceUnsignedBaseType_t uxPriority) +{ + TraceEventHandle_t xEventHandle = 0; + void *pvTask; + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceObjectSetState((TraceObjectHandle_t)xTaskHandle, uxPriority) == TRC_SUCCESS); + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xTaskHandle, &pvTask) == TRC_SUCCESS); + + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_TASK_PRIORITY, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, pvTask); + xTraceEventAdd32(xEventHandle, (uint32_t)uxPriority); + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +traceResult xTraceTaskSetPriorityWithoutHandle(void* pvTask, TraceUnsignedBaseType_t uxPriority) +{ + TraceEventHandle_t xEventHandle = 0; + TraceEntryHandle_t xEntryHandle; + + if (xTraceEntryFind(pvTask, &xEntryHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + /* This should never fail */ + TRC_ASSERT_ALWAYS_EVALUATE(xTraceObjectSetState((TraceObjectHandle_t)xEntryHandle, uxPriority) == TRC_SUCCESS); + + /* We need to check this */ + if (xTraceEventBegin(PSF_EVENT_TASK_PRIORITY, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, pvTask); + xTraceEventAdd32(xEventHandle, (uint32_t)uxPriority); + xTraceEventEnd(xEventHandle); + } + + return TRC_SUCCESS; +} + +traceResult xTraceTaskSwitch(void *pvTask, TraceUnsignedBaseType_t uxPriority) +{ + traceResult xResult = TRC_FAIL; + TraceEventHandle_t xEventHandle = 0; + void* pvCurrent = 0; + + (void)pvTask; + (void)uxPriority; + + TRACE_ALLOC_CRITICAL_SECTION(); + + if (xTraceIsRecorderEnabled() == 0) + { + return xResult; + } + + TRACE_ENTER_CRITICAL_SECTION(); + + xTraceStateSet(TRC_STATE_IN_TASKSWITCH); + + xTraceTaskGetCurrent(&pvCurrent); + if (pvCurrent != pvTask) + { + xTraceTaskSetCurrent(pvTask); + + if (xTraceEventBegin(PSF_EVENT_TASK_ACTIVATE, sizeof(void*) + sizeof(uint32_t), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, pvTask); + xTraceEventAdd32(xEventHandle, (uint32_t)uxPriority); + xTraceEventEnd(xEventHandle); + xResult = TRC_SUCCESS; + } + } + + xTraceStateSet(TRC_STATE_IN_APPLICATION); + + TRACE_EXIT_CRITICAL_SECTION(); + + return xResult; +} + +#if (TRC_CFG_INCLUDE_READY_EVENTS == 1) +traceResult xTraceTaskReady(void *pvTask) +{ + traceResult xResult = TRC_FAIL; + TraceEventHandle_t xEventHandle = 0; + + if (xTraceEventBegin(PSF_EVENT_TASK_READY, sizeof(void*), &xEventHandle) == TRC_SUCCESS) + { + xTraceEventAddPointer(xEventHandle, pvTask); + xTraceEventEnd(xEventHandle); + xResult = TRC_SUCCESS; + } + + return xResult; +} +#endif /* (TRC_CFG_INCLUDE_READY_EVENTS == 1) */ + +traceResult xTraceTaskInstanceFinishedNow(void) +{ + TraceEventHandle_t xEventHandle = 0; + + if (xTraceEventBegin(PSF_EVENT_IFE_DIRECT, 0, &xEventHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + xTraceEventEnd(xEventHandle); + + return TRC_SUCCESS; +} + +traceResult xTraceTaskInstanceFinishedNext(void) +{ + TraceEventHandle_t xEventHandle = 0; + + if (xTraceEventBegin(PSF_EVENT_IFE_NEXT, 0, &xEventHandle) == TRC_FAIL) + { + return TRC_FAIL; + } + + xTraceEventEnd(xEventHandle); + + return TRC_SUCCESS; +} + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcTimestamp.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcTimestamp.c new file mode 100644 index 0000000000..488729848f --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/trcTimestamp.c @@ -0,0 +1,173 @@ +/* +* Trace Recorder for Tracealyzer v4.6.0 +* Copyright 2021 Percepio AB +* www.percepio.com +* +* SPDX-License-Identifier: Apache-2.0 +* +* The implementation of timestamps. +*/ + +#include + +#if (TRC_USE_TRACEALYZER_RECORDER == 1) + +#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) + +TraceTimestamp_t *pxTraceTimestamp; + +traceResult xTraceTimestampInitialize(TraceTimestampBuffer_t *pxBuffer) +{ + TRC_ASSERT_EQUAL_SIZE(TraceTimestampBuffer_t, TraceTimestamp_t); + + /* This should never fail */ + TRC_ASSERT(pxBuffer != 0); + + pxTraceTimestamp = (TraceTimestamp_t*)pxBuffer; + pxTraceTimestamp->frequency = 0; + pxTraceTimestamp->period = TRC_HWTC_PERIOD; + pxTraceTimestamp->osTickHz = TRC_TICK_RATE_HZ; + pxTraceTimestamp->osTickCount = 0; + pxTraceTimestamp->wraparounds = 0; + pxTraceTimestamp->type = TRC_HWTC_TYPE; + +#if (TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_INCR || TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_INCR) + pxTraceTimestamp->latestTimestamp = 0; +#elif (TRC_HWTC_TYPE == TRC_FREE_RUNNING_32BIT_DECR || TRC_HWTC_TYPE == TRC_CUSTOM_TIMER_DECR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR) + pxTraceTimestamp->latestTimestamp = pxTraceTimestamp->period - 1; +#endif + + xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_TIMESTAMP); + + return TRC_SUCCESS; +} + +#if ((TRC_CFG_USE_TRACE_ASSERT) == 1) + +traceResult xTraceTimestampGet(uint32_t *puiTimestamp) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_TIMESTAMP)); + + /* This should never fail */ + TRC_ASSERT(puiTimestamp != 0); + + switch (pxTraceTimestamp->type) + { + case TRC_FREE_RUNNING_32BIT_INCR: + case TRC_CUSTOM_TIMER_INCR: + *puiTimestamp = TRC_HWTC_COUNT; + if (*puiTimestamp < pxTraceTimestamp->latestTimestamp) + { + pxTraceTimestamp->wraparounds++; + } + break; + case TRC_FREE_RUNNING_32BIT_DECR: + case TRC_CUSTOM_TIMER_DECR: + *puiTimestamp = TRC_HWTC_COUNT; + if (*puiTimestamp > pxTraceTimestamp->latestTimestamp) + { + pxTraceTimestamp->wraparounds++; + } + break; + case TRC_OS_TIMER_INCR: + case TRC_OS_TIMER_DECR: + *puiTimestamp = ((TRC_HWTC_COUNT) & 0x00FFFFFFU) + ((pxTraceTimestamp->osTickCount & 0x000000FFU) << 24); + pxTraceTimestamp->wraparounds = pxTraceTimestamp->osTickCount; + break; + default: + return TRC_FAIL; + } + + pxTraceTimestamp->latestTimestamp = *puiTimestamp; + + return TRC_SUCCESS; +} + +traceResult xTraceTimestampGetWraparounds(uint32_t* puiTimerWraparounds) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_TIMESTAMP)); + + /* This should never fail */ + TRC_ASSERT(puiTimerWraparounds != 0); + + *puiTimerWraparounds = pxTraceTimestamp->wraparounds; + + return TRC_SUCCESS; +} + +traceResult xTraceTimestampSetFrequency(TraceUnsignedBaseType_t uxFrequency) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_TIMESTAMP)); + + pxTraceTimestamp->frequency = uxFrequency; + + return TRC_SUCCESS; +} + +traceResult xTraceTimestampSetPeriod(uint32_t uiPeriod) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_TIMESTAMP)); + + pxTraceTimestamp->period = uiPeriod; + + return TRC_SUCCESS; +} + +traceResult xTraceTimestampSetOsTickCount(uint32_t uiOsTickCount) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_TIMESTAMP)); + + pxTraceTimestamp->osTickCount = uiOsTickCount; + + return TRC_SUCCESS; +} + +traceResult xTraceTimestampGetFrequency(TraceUnsignedBaseType_t *puxFrequency) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_TIMESTAMP)); + + /* This should never fail */ + TRC_ASSERT(puxFrequency != 0); + + *puxFrequency = pxTraceTimestamp->frequency; + + return TRC_SUCCESS; +} + +traceResult xTraceTimestampGetPeriod(uint32_t *puiPeriod) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_TIMESTAMP)); + + /* This should never fail */ + TRC_ASSERT(puiPeriod != 0); + + *puiPeriod = pxTraceTimestamp->period; + + return TRC_SUCCESS; +} + +traceResult xTraceTimestampGetOsTickCount(uint32_t* puiOsTickCount) +{ + /* This should never fail */ + TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_TIMESTAMP)); + + /* This should never fail */ + TRC_ASSERT(puiOsTickCount != 0); + + *puiOsTickCount = pxTraceTimestamp->osTickCount; + + return TRC_SUCCESS; +} + +#endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */ + +#endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */ + +#endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */ diff --git a/FreeRTOS/Demo/CORTEX_LM3S6965_GCC_QEMU/trcConfig.h b/FreeRTOS/Demo/CORTEX_LM3S6965_GCC_QEMU/trcConfig.h index e2be22d2cf..d9192bab62 100644 --- a/FreeRTOS/Demo/CORTEX_LM3S6965_GCC_QEMU/trcConfig.h +++ b/FreeRTOS/Demo/CORTEX_LM3S6965_GCC_QEMU/trcConfig.h @@ -52,8 +52,6 @@ extern "C" { #endif -#include "trcPortDefines.h" - /****************************************************************************** * Include of processor header file * diff --git a/FreeRTOS/Demo/Posix_GCC/Makefile b/FreeRTOS/Demo/Posix_GCC/Makefile index 6804c6a3aa..734e69509b 100644 --- a/FreeRTOS/Demo/Posix_GCC/Makefile +++ b/FreeRTOS/Demo/Posix_GCC/Makefile @@ -18,6 +18,9 @@ INCLUDE_DIRS += -I${KERNEL_DIR}/portable/ThirdParty/GCC/Posix INCLUDE_DIRS += -I${KERNEL_DIR}/portable/ThirdParty/GCC/Posix/utils INCLUDE_DIRS += -I${FREERTOS_DIR}/Demo/Common/include INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/Include +INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/config +INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/streamports/File/include +INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/streamports/File/config SOURCE_FILES := $(wildcard *.c) SOURCE_FILES += $(wildcard ${FREERTOS_DIR}/Source/*.c) @@ -73,9 +76,7 @@ else CPPFLAGS += -DprojCOVERAGE_TEST=0 # Trace library. SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcKernelPort.c - SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c - SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c - SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c + SOURCE_FILES += $(wildcard ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/*.c ) endif ifdef PROFILE diff --git a/FreeRTOS/Demo/Posix_GCC/main.c b/FreeRTOS/Demo/Posix_GCC/main.c index c257366007..ee330f5ddd 100644 --- a/FreeRTOS/Demo/Posix_GCC/main.c +++ b/FreeRTOS/Demo/Posix_GCC/main.c @@ -58,6 +58,7 @@ #include #include #include +#include /* FreeRTOS kernel includes. */ #include "FreeRTOS.h" @@ -66,6 +67,10 @@ /* Local includes. */ #include "console.h" +#if ( projCOVERAGE_TEST != 1 ) + #include +#endif + #define BLINKY_DEMO 0 #define FULL_DEMO 1 @@ -140,6 +145,9 @@ StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; static BaseType_t xTraceRunning = pdTRUE; #endif +static clockid_t cid = CLOCK_THREAD_CPUTIME_ID; +static uint32_t frequency; + /*-----------------------------------------------------------*/ int main( void ) @@ -161,7 +169,6 @@ int main( void ) #if ( TRACE_ON_ENTER == 1 ) printf( "\r\nThe trace will be dumped to disk if Enter is hit.\r\n" ); #endif - uiTraceStart(); } #endif /* if ( projCOVERAGE_TEST != 1 ) */ @@ -352,6 +359,7 @@ static void prvSaveTraceFile( void ) #if ( projCOVERAGE_TEST != 1 ) { FILE * pxOutputFile; + extern RecorderDataType* RecorderDataPtr; vTraceStop(); @@ -437,3 +445,58 @@ void handle_sigint( int signal ) exit( 2 ); } + +void vTraceTimerReset( void ) +{ + int xRet; + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 0; + + xRet = clock_settime( cid, &ts ); + if( xRet != 0 ) + { + printf( "Could not reset time: %s\n", strerror( errno ) ); + } +} + +uint32_t uiTraceTimerGetFrequency( void ) +{ + struct timespec res; + int xRet; + + res.tv_nsec = 0; + res.tv_sec = 0; + + xRet = clock_getres( cid, &res ); + if( xRet == 0 ) + { + // calculate frequency from timer definition + frequency = (uint64_t) 1000000000 / res.tv_nsec; + } + else + { + printf( "Could not get clock frequency: %s\n", strerror( errno ) ); + } + return frequency; +} + +uint32_t uiTraceTimerGetValue( void ) +{ + int xRet; + struct timespec tp; + uint32_t result = 0; + + xRet = clock_gettime( cid, &tp ); + if( xRet == 0 ) + { + result = tp.tv_nsec / frequency; + result += (tp.tv_sec * 1000000000) / frequency; + } + else + { + printf( "Could not get time: %s\n", strerror( errno ) ); + } + return result; +} + diff --git a/FreeRTOS/Demo/Posix_GCC/trcConfig.h b/FreeRTOS/Demo/Posix_GCC/trcConfig.h index d39de12cff..52df20e7f4 100644 --- a/FreeRTOS/Demo/Posix_GCC/trcConfig.h +++ b/FreeRTOS/Demo/Posix_GCC/trcConfig.h @@ -1,310 +1,320 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v3.1.2 - * 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, 2016. - * 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_Win32 - -/******************************************************************************* - * 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 TRC_FREERTOS_VERSION_10_4_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 1 - -/***************************************************************************** -* 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 1 - -/***************************************************************************** -* 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 1 - -/******************************************************************************* - * 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 1 - -/******************************************************************************* - * 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 for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Main configuration parameters for the trace recorder library. + * More settings can be found in trcStreamingConfig.h and trcSnapshotConfig.h. + */ + +#ifndef TRC_CONFIG_H +#define TRC_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * 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." */ + +/** + * @def TRC_CFG_HARDWARE_PORT + * @brief 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_Win64 + +/** + * @def TRC_CFG_SCHEDULING_ONLY + * @brief 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 + +/** + * @def TRC_CFG_INCLUDE_MEMMANG_EVENTS + * @brief 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 + +/** + * @def TRC_CFG_INCLUDE_USER_EVENTS + * @brief 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 xTraceErrorGetLast + * or by putting breakpoints in xTraceError and xTraceWarning. + * + * Default value is 1. + */ +#define TRC_CFG_INCLUDE_USER_EVENTS 1 + +/** + * @def TRC_CFG_INCLUDE_ISR_TRACING + * @brief 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 + +/** + * @def TRC_CFG_INCLUDE_READY_EVENTS + * @brief 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 + +/** + * @def TRC_CFG_INCLUDE_OSTICK_EVENTS + * @brief 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 + +/** + * @def TRC_CFG_ENABLE_STACK_MONITOR + * @brief 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 + +/** + * @def TRC_CFG_STACK_MONITOR_MAX_TASKS + * @brief 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 + +/** + * @def TRC_CFG_STACK_MONITOR_MAX_REPORTS + * @brief 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 + +/** + * @def TRC_CFG_CTRL_TASK_PRIORITY + * @brief 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 + +/** + * @def TRC_CFG_CTRL_TASK_DELAY + * @brief 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 2 + +/** + * @def TRC_CFG_CTRL_TASK_STACK_SIZE + * @brief 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 1024 + +/** + * @def TRC_CFG_RECORDER_BUFFER_ALLOCATION + * @brief 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 + +/** + * @def TRC_CFG_MAX_ISR_NESTING + * @brief 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 + +/** + * @def TRC_CFG_ISR_TAILCHAINING_THRESHOLD + * @brief 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 + +/** + * @def TRC_CFG_RECORDER_DATA_INIT + * @brief Macro which states wether the recorder data should have an initial value. + * + * In very specific cases where traced objects are created before main(), + * the recorder will need to be started even before that. In these cases, + * the recorder data would be initialized by vTraceEnable(TRC_INIT) but could + * then later be overwritten by the initialization value. + * If this is an issue for you, set TRC_CFG_RECORDER_DATA_INIT to 0. + * The following code can then be used before any traced objects are created: + * + * extern uint32_t RecorderEnabled; + * RecorderEnabled = 0; + * xTraceInitialize(); + * + * After the clocks are properly initialized, use vTraceEnable(...) to start + * the tracing. + * + * Default value is 1. + */ +#define TRC_CFG_RECORDER_DATA_INIT 1 + +/** + * @def TRC_CFG_RECORDER_DATA_ATTRIBUTE + * @brief When setting TRC_CFG_RECORDER_DATA_INIT to 0, you might also need to make + * sure certain recorder data is placed in a specific RAM section to avoid being + * zeroed out after initialization. Define TRC_CFG_RECORDER_DATA_ATTRIBUTE as + * that attribute. + * + * Example: + * #define TRC_CFG_RECORDER_DATA_ATTRIBUTE __attribute__((section(".bss.trace_recorder_data"))) + * + * Default value is empty. + */ +#define TRC_CFG_RECORDER_DATA_ATTRIBUTE + +/** + * @def TRC_CFG_USE_TRACE_ASSERT + * @brief Enable or disable debug asserts. Information regarding any assert that is + * triggered will be in trcAssert.c. + */ +#define TRC_CFG_USE_TRACE_ASSERT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* _TRC_CONFIG_H */ diff --git a/FreeRTOS/Demo/Posix_GCC/trcKernelPortConfig.h b/FreeRTOS/Demo/Posix_GCC/trcKernelPortConfig.h new file mode 100644 index 0000000000..b0c7d22164 --- /dev/null +++ b/FreeRTOS/Demo/Posix_GCC/trcKernelPortConfig.h @@ -0,0 +1,116 @@ +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com + * + * SPDX-License-Identifier: Apache-2.0 + * + * Configuration parameters for the kernel port. + * More settings can be found in trcKernelPortStreamingConfig.h and + * trcKernelPortSnapshotConfig.h. + */ + +#ifndef TRC_KERNEL_PORT_CONFIG_H +#define TRC_KERNEL_PORT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def TRC_CFG_RECORDER_MODE + * @brief 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 + +/** + * @def TRC_CFG_FREERTOS_VERSION + * @brief 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 + * TRC_FREERTOS_VERSION_10_4_1 If using FreeRTOS v10.4.1 or later + */ +#define TRC_CFG_FREERTOS_VERSION TRC_FREERTOS_VERSION_10_4_1 + +/** + * @def TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_TIMER_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS + * @brief 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 1 + +/** + * @def TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND + * @brief 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 */ + +#ifdef __cplusplus +} +#endif + +#endif /* TRC_KERNEL_PORT_CONFIG_H */ diff --git a/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcConfig.h b/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcConfig.h index 56c5705ef7..fdf48cbfcb 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcConfig.h +++ b/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcConfig.h @@ -52,8 +52,6 @@ extern "C" { #endif -#include "trcPortDefines.h" - /****************************************************************************** * Include of processor header file * diff --git a/FreeRTOS/Demo/WIN32-MingW/Trace_Recorder_Configuration/trcConfig.h b/FreeRTOS/Demo/WIN32-MingW/Trace_Recorder_Configuration/trcConfig.h index 3dba4a472b..5acd22bc86 100644 --- a/FreeRTOS/Demo/WIN32-MingW/Trace_Recorder_Configuration/trcConfig.h +++ b/FreeRTOS/Demo/WIN32-MingW/Trace_Recorder_Configuration/trcConfig.h @@ -52,8 +52,6 @@ extern "C" { #endif -#include "trcPortDefines.h" - /****************************************************************************** * Include of processor header file *