From 228f76cbe3c24a441ee73307cb1361b7c4d3535c Mon Sep 17 00:00:00 2001 From: jasonpcarroll <23126711+jasonpcarroll@users.noreply.github.com> Date: Wed, 7 Dec 2022 10:29:12 -0800 Subject: Fix and improve WIN32-MSVC demo in FreeRTOS/Demo. (#891) * Fix WIN32-MSVC demo in FreeRTOS/Demo. * Add comments. * Fix corechecks * Re-work trace and keyboard input. * Remove unneeded line from trcConfig.h * Fix formatting in trcConfig.h * Fix heap issues, add FreeRTOS task to simulate keyboard interrupts. * Update comment on main_blinky. * Fix spelling. * Make keyboard input thread block on input. * Set thread affinity of keyboard input thread to not run on the same core as FreeRTOS. * Adjust heap regions and total heap size. * Fix spelling. Co-authored-by: Jason Carroll --- .github/scripts/core_checker.py | 4 +- FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h | 2 +- .../Trace_Recorder_Configuration/trcConfig.h | 384 +++++++------ .../trcKernelPortConfig.h | 116 ++++ .../trcKernelPortSnapshotConfig.h | 69 +++ .../trcSnapshotConfig.h | 303 +++------- FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj | 5 + FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters | 18 + FreeRTOS/Demo/WIN32-MSVC/main.c | 625 +++++++++++++-------- FreeRTOS/Demo/WIN32-MSVC/main_blinky.c | 92 ++- lexicon.txt | 3 + 11 files changed, 941 insertions(+), 680 deletions(-) create mode 100644 FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcKernelPortConfig.h create mode 100644 FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcKernelPortSnapshotConfig.h diff --git a/.github/scripts/core_checker.py b/.github/scripts/core_checker.py index 901e65dcd..a2e787a54 100755 --- a/.github/scripts/core_checker.py +++ b/.github/scripts/core_checker.py @@ -270,6 +270,7 @@ FREERTOS_IGNORED_PATTERNS = [ r'.*/trcConfig\.c.*', r'.*/trcSnapshotConfig\.h.*', r'.*/trcKernelPortConfig\.h.*', + r'.*/trcKernelPortSnapshotConfig\.h.*', r'.*/MicroZed_hw_platform.*', r'.*/ThirdParty/.*', r'FreeRTOS\-Plus/Demo/Common/WinPCap/.*', @@ -302,7 +303,8 @@ FREERTOS_IGNORED_FILES = [ 'FreeRTOS_asm_vectors.S', 'interrupt_vector.s', 'reg_test.S', - 'gdbinit' + 'gdbinit', + ] FREERTOS_HEADER = [ diff --git a/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h b/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h index 2c3d39208..b336180d0 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h +++ b/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h @@ -46,7 +46,7 @@ #define configUSE_DAEMON_TASK_STARTUP_HOOK 1 #define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */ #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */ -#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 52 * 1024 ) ) /* This demo tests heap_5 so places multiple blocks within this total heap size. See mainREGION_1_SIZE to mainREGION_3_SIZE definitions in main.c. */ +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 49 * 1024 ) ) /* This demo tests heap_5 so places multiple blocks within this total heap size. See mainREGION_1_SIZE to mainREGION_3_SIZE definitions in main.c. */ #define configMAX_TASK_NAME_LEN ( 12 ) #define configUSE_TRACE_FACILITY 1 #define configUSE_16_BIT_TICKS 0 diff --git a/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcConfig.h b/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcConfig.h index fdf48cbfc..f73d385e1 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcConfig.h +++ b/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcConfig.h @@ -1,49 +1,13 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.1.4 - * Percepio AB, www.percepio.com +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com * - * trcConfig.h + * 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. - * - * 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 @@ -59,12 +23,10 @@ extern "C" { * 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"). +/** + * @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 @@ -78,78 +40,34 @@ extern "C" { * * 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 + */ +#define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_Win32 -/******************************************************************************* - * TRC_CFG_SCHEDULING_ONLY - * - * Macro which should be defined as an integer value. +/** + * @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 + */ +#define TRC_CFG_SCHEDULING_ONLY 0 - /****************************************************************************** - * TRC_CFG_INCLUDE_MEMMANG_EVENTS - * - * Macro which should be defined as either zero (0) or one (1). +/** + * @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 + */ +#define TRC_CFG_INCLUDE_MEMMANG_EVENTS 1 - /****************************************************************************** - * TRC_CFG_INCLUDE_USER_EVENTS - * - * Macro which should be defined as either zero (0) or one (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 @@ -164,32 +82,37 @@ extern "C" { * 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. + * 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 + */ +#define TRC_CFG_INCLUDE_USER_EVENTS 1 - /***************************************************************************** - * TRC_CFG_INCLUDE_ISR_TRACING - * - * Macro which should be defined as either zero (0) or one (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. + * 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 + */ +#define TRC_CFG_INCLUDE_ISR_TRACING 1 - /***************************************************************************** - * TRC_CFG_INCLUDE_READY_EVENTS - * - * Macro which should be defined as either zero (0) or one (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 @@ -198,72 +121,102 @@ extern "C" { * longer traces in the same amount of RAM. * * Default value is 1. - *****************************************************************************/ -#define TRC_CFG_INCLUDE_READY_EVENTS 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). +/** + * @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 + */ +#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 +/** + * @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 - /***************************************************************************** - * TRC_CFG_INCLUDE_TIMER_EVENTS - * - * Macro which should be defined as either zero (0) or one (1). +/** + * @def TRC_CFG_STACK_MONITOR_MAX_TASKS + * @brief Macro which should be defined as a non-zero integer value. * - * If this is zero (0), the trace will exclude any Timer events. + * 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 0 since dependent on timers.c - *****************************************************************************/ -#define TRC_CFG_INCLUDE_TIMER_EVENTS 1 + * Default value is 10. + */ +#define TRC_CFG_STACK_MONITOR_MAX_TASKS 50 - /***************************************************************************** - * TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS +/** + * @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. * - * 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 + * Default value is 1. + */ +#define TRC_CFG_STACK_MONITOR_MAX_REPORTS 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 +/** + * @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 -/******************************************************************************* - * Configuration Macro: TRC_CFG_RECORDER_BUFFER_ALLOCATION - * - * Specifies how the recorder buffer is allocated (also in case of streaming, in +/** + * @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: @@ -275,13 +228,12 @@ extern "C" { * (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 + */ +#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 +/** + * @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 @@ -290,15 +242,75 @@ extern "C" { * This value must be a non-zero positive constant, at least 1. * * Default value: 8 - *****************************************************************************/ -#define TRC_CFG_MAX_ISR_NESTING 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 +/** + * @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 } diff --git a/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcKernelPortConfig.h b/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcKernelPortConfig.h new file mode 100644 index 000000000..387df1ab6 --- /dev/null +++ b/FreeRTOS/Demo/WIN32-MSVC/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 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/trcKernelPortSnapshotConfig.h b/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcKernelPortSnapshotConfig.h new file mode 100644 index 000000000..023a80316 --- /dev/null +++ b/FreeRTOS/Demo/WIN32-MSVC/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/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcSnapshotConfig.h b/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcSnapshotConfig.h index a96d641c3..8d7449a4c 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcSnapshotConfig.h +++ b/FreeRTOS/Demo/WIN32-MSVC/Trace_Recorder_Configuration/trcSnapshotConfig.h @@ -1,58 +1,24 @@ -/******************************************************************************* - * Trace Recorder Library for Tracealyzer v4.1.4 - * Percepio AB, www.percepio.com +/* + * Trace Recorder for Tracealyzer v4.6.0 + * Copyright 2021 Percepio AB + * www.percepio.com * - * trcSnapshotConfig.h + * 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/ - * - * 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) +#ifdef __cplusplus + extern "C" { +#endif -/****************************************************************************** - * TRC_CFG_SNAPSHOT_MODE - * - * Macro which should be defined as one of: +/** + * @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. @@ -66,13 +32,12 @@ * 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 + */ +#define TRC_CFG_SNAPSHOT_MODE TRC_SNAPSHOT_MODE_RING_BUFFER -/******************************************************************************* - * TRC_CFG_EVENT_BUFFER_SIZE - * - * Macro which should be defined as an integer value. +/** + * @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 @@ -81,46 +46,12 @@ * * Default value is 1000, which means that 4000 bytes is allocated for the * event buffer. - ******************************************************************************/ -#define TRC_CFG_EVENT_BUFFER_SIZE 50000 - -/******************************************************************************* - * 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 + */ +#define TRC_CFG_EVENT_BUFFER_SIZE 250000 - -/****************************************************************************** - * TRC_CFG_INCLUDE_FLOAT_SUPPORT - * - * Macro which should be defined as either zero (0) or one (1). +/** + * @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 @@ -132,13 +63,12 @@ * vTracePrintF can be used with integer and string arguments in either case. * * Default value is 0. - *****************************************************************************/ -#define TRC_CFG_INCLUDE_FLOAT_SUPPORT 0 + */ +#define TRC_CFG_INCLUDE_FLOAT_SUPPORT 0 -/******************************************************************************* - * TRC_CFG_SYMBOL_TABLE_SIZE - * - * Macro which should be defined as an integer value. +/** + * @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 @@ -148,30 +78,13 @@ * 32-bit pointer, i.e., using 4 bytes rather than 0. * * Default value is 800. - ******************************************************************************/ -#define TRC_CFG_SYMBOL_TABLE_SIZE 8000 + */ +#define TRC_CFG_SYMBOL_TABLE_SIZE 8000 -#if (TRC_CFG_SYMBOL_TABLE_SIZE == 0) -#error "TRC_CFG_SYMBOL_TABLE_SIZE may not be zero!" +#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 ******************************************************** ****************************************************************************** @@ -180,37 +93,35 @@ * 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 +/** + * @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. * - * Macro which should be defined as either zero (0) or one (1). + * 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 vTraceInstanceFinishedNow and vTraceInstanceFinishedNext. + * 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 vTraceInstanceFinishedNow/Next for one + * 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 vTraceInstanceFinishedNow or - * vTraceInstanceFinishedNext to manually group the events into instances, + * 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": @@ -218,16 +129,12 @@ * - 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 + */ +#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). +/** + * @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 @@ -245,31 +152,12 @@ * 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 + */ +#define TRC_CFG_USE_16BIT_OBJECT_HANDLES 0 -/******************************************************************************* - * TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER - * - * Macro which should be defined as an integer value. +/** + * @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). @@ -292,14 +180,17 @@ * repeating events, using the same format string within each channel. * * Examples: - * - * traceString chn1 = xTraceRegisterString("Channel 1"); - * traceString fmt1 = xTraceRegisterString("Event!"); + * TraceStringHandle_t chn1; + * TraceStringHandle_t fmt1; + * xTraceStringRegister("Channel 1", &chn1); + * xTraceStringRegister("Event!", &fmt1); * traceUBChannel UBCh1 = xTraceRegisterUBChannel(chn1, fmt1); * - * traceString chn2 = xTraceRegisterString("Channel 2"); - * traceString fmt2 = xTraceRegisterString("X: %d, Y: %d"); - * traceUBChannel UBCh2 = xTraceRegisterUBChannel(chn2, fmt2); + * 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); @@ -307,7 +198,7 @@ * // Result in "[Channel 2] X: 23, Y: 19" * vTraceUBData(UBCh2, 23, 19); * - * You can also use the other user event functions, like vTracePrintF. + * 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 @@ -316,30 +207,27 @@ * 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); + * xTracePrintF(chn2, "%Z: %d", value1); * * // Finds the existing UB channel - * vTracePrintF(chn2, "%Z: %d", value2); - - ******************************************************************************/ -#define TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER 0 + * xTracePrintF(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. +/** + * @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 + */ +#define TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE 200 -/******************************************************************************* - * TRC_CFG_UB_CHANNELS - * - * Macro which should be defined as an integer value. +/** + * @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 @@ -347,32 +235,11 @@ * 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 + */ +#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 +#ifdef __cplusplus +} +#endif #endif /*TRC_SNAPSHOT_CONFIG_H*/ diff --git a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj index 1f5b89a58..0b8ff54c7 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj +++ b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj @@ -131,6 +131,8 @@ + + @@ -145,6 +147,9 @@ + + + diff --git a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters index d6fafd96c..0c2c777f5 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters +++ b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters @@ -38,6 +38,9 @@ {fb86fa48-ac27-4f87-9215-ce9e1a1a85f9} + + {5cb8735d-498f-40aa-bf5c-9d41923b7968} + @@ -204,6 +207,21 @@ FreeRTOS Source\Include + + Configuration Files + + + Configuration Files + + + Configuration Files + + + Demo App Source\FreeRTOS+Trace Recorder\include + + + Demo App Source\FreeRTOS+Trace Recorder\include + diff --git a/FreeRTOS/Demo/WIN32-MSVC/main.c b/FreeRTOS/Demo/WIN32-MSVC/main.c index f13d07280..600e7b09e 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/main.c +++ b/FreeRTOS/Demo/WIN32-MSVC/main.c @@ -53,33 +53,44 @@ #include /* Visual studio intrinsics used so the __debugbreak() function is available -should an assert get hit. */ + * should an assert get hit. */ #include /* FreeRTOS kernel includes. */ #include "FreeRTOS.h" #include "task.h" -/* This project provides two demo applications. A simple blinky style demo -application, and a more comprehensive test and demo application. The -mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two. - -If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is 1 then the blinky demo will be built. -The blinky demo is implemented and described in main_blinky.c. +/* FreeRTOS+Trace includes. */ +#include "trcRecorder.h" -If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is not 1 then the comprehensive test and -demo application will be built. The comprehensive test and demo application is -implemented and described in main_full.c. */ -#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 1 +/* This project provides two demo applications. A simple blinky style demo + * application, and a more comprehensive test and demo application. The + * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two. + * + * If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is 1 then the blinky demo will be built. + * The blinky demo is implemented and described in main_blinky.c. + * + * If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is not 1 then the comprehensive test and + * demo application will be built. The comprehensive test and demo application is + * implemented and described in main_full.c. */ +#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0 /* This demo uses heap_5.c, and these constants define the sizes of the regions -that make up the total heap. heap_5 is only used for test and example purposes -as this demo could easily create one large heap region instead of multiple -smaller heap regions - in which case heap_4.c would be the more appropriate -choice. See http://www.freertos.org/a00111.html for an explanation. */ -#define mainREGION_1_SIZE 8201 -#define mainREGION_2_SIZE 31905 -#define mainREGION_3_SIZE 7807 + * that make up the total heap. heap_5 is only used for test and example purposes + * as this demo could easily create one large heap region instead of multiple + * smaller heap regions - in which case heap_4.c would be the more appropriate + * choice. See http://www.freertos.org/a00111.html for an explanation. */ +#define mainREGION_1_SIZE 8201 +#define mainREGION_2_SIZE 23905 +#define mainREGION_3_SIZE 16807 + +/* This demo allows for users to perform actions with the keyboard. */ +#define mainNO_KEY_PRESS_VALUE -1 +#define mainOUTPUT_TRACE_KEY 't' +#define mainKEYBOARD_INTERRUPT_YIELD_MS 200 + +/* This demo allows to save a trace file. */ +#define mainTRACE_FILE_NAME "Trace.dump" /*-----------------------------------------------------------*/ @@ -94,8 +105,8 @@ extern void main_full( void ); * Only the comprehensive demo uses application hook (callback) functions. See * https://www.FreeRTOS.org/a00016.html for more information. */ -void vFullDemoTickHookFunction( void ); -void vFullDemoIdleFunction( void ); +extern void vFullDemoTickHookFunction( void ); +extern void vFullDemoIdleFunction( void ); /* * This demo uses heap_5.c, so start by defining some heap regions. It is not @@ -103,7 +114,7 @@ void vFullDemoIdleFunction( void ); * region. Heap_5 is only used for test and example purposes. See * https://www.FreeRTOS.org/a00111.html for an explanation. */ -static void prvInitialiseHeap( void ); +static void prvInitialiseHeap( void ); /* * Prototypes for the standard FreeRTOS application hook (callback) functions @@ -111,10 +122,15 @@ static void prvInitialiseHeap( void ); */ void vApplicationMallocFailedHook( void ); void vApplicationIdleHook( void ); -void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ); +void vApplicationStackOverflowHook( TaskHandle_t pxTask, + char * pcTaskName ); void vApplicationTickHook( void ); -void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); -void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ); +void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize ); +void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, + StackType_t ** ppxTimerTaskStackBuffer, + uint32_t * pulTimerTaskStackSize ); /* * Writes trace data to a disk file when the trace recording is stopped. @@ -122,288 +138,409 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack */ static void prvSaveTraceFile( void ); +/* + * Windows thread function to capture keyboard input from outside of the + * FreeRTOS simulator. This thread passes data safely into the FreeRTOS + * simulator using a stream buffer. + */ +static DWORD WINAPI prvWindowsKeyboardInputThread( void * pvParam ); + +/* + * FreeRTOS task function that simulates keyboard interrupts by + * periodically polling data coming from the Windows thread + * capturing keyboard input. + */ +static void prvKeyboardInterruptSimulatorTask( void * pvParam ); + +/* + * Keyboard interrupt handler for the blinky demo. + */ +extern void vBlinkyKeyboardInterruptHandler( int xKeyPressed ); + /*-----------------------------------------------------------*/ /* When configSUPPORT_STATIC_ALLOCATION is set to 1 the application writer can -use a callback function to optionally provide the memory required by the idle -and timer tasks. This is the stack that will be used by the timer task. It is -declared here, as a global, so it can be checked by a test that is implemented -in a different file. */ + * use a callback function to optionally provide the memory required by the idle + * and timer tasks. This is the stack that will be used by the timer task. It is + * declared here, as a global, so it can be checked by a test that is implemented + * in a different file. */ StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; -/* Notes if the trace is running or not. */ -static BaseType_t xTraceRunning = pdTRUE; + +/* Thread handle for the keyboard input Windows thread. */ +static HANDLE xWindowsKeyboardInputThreadHandle = NULL; + +/* This stores the last key pressed that has not been handled. + * Keyboard input is retrieved by the prvWindowsKeyboardInputThread + * Windows thread and stored here. This is then read by the idle + * task and handled appropriately. */ +static int xKeyPressed = mainNO_KEY_PRESS_VALUE; /*-----------------------------------------------------------*/ int main( void ) { - /* This demo uses heap_5.c, so start by defining some heap regions. heap_5 - is only used for test and example reasons. Heap_4 is more appropriate. See - http://www.freertos.org/a00111.html for an explanation. */ - prvInitialiseHeap(); - - /* Initialise the trace recorder. Use of the trace recorder is optional. - See http://www.FreeRTOS.org/trace for more information. */ - vTraceEnable( TRC_START ); - - /* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top - of this file. */ - #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) - { - main_blinky(); - } - #else - { - /* Start the trace recording - the recording is written to a file if - configASSERT() is called. */ - printf( "\r\nTrace started.\r\nThe trace will be dumped to disk if a call to configASSERT() fails.\r\n" ); - printf( "Uncomment the call to kbhit() in this file to also dump trace with a key press.\r\n" ); - uiTraceStart(); - - main_full(); - } - #endif - - return 0; + /* This demo uses heap_5.c, so start by defining some heap regions. heap_5 + * is only used for test and example reasons. Heap_4 is more appropriate. See + * http://www.freertos.org/a00111.html for an explanation. */ + prvInitialiseHeap(); + + /* Initialise the trace recorder. Use of the trace recorder is optional. + * See http://www.FreeRTOS.org/trace for more information. */ + vTraceEnable( TRC_START ); + + /* Start the trace recording - the recording is written to a file if + * configASSERT() is called. */ + printf( + "Trace started.\r\n" + "The trace will be dumped to the file \"%s\" whenever a call to configASSERT()\r\n" + "fails or the \'%c\' key is pressed.\r\n" + "Note that the trace output uses the ring buffer mode, meaning that the output trace\r\n" + "will only be the most recent data able to fit within the trace recorder buffer.\r\n", + mainTRACE_FILE_NAME, mainOUTPUT_TRACE_KEY ); + + traceSTART(); + + /* Start keyboard input handling thread. */ + xWindowsKeyboardInputThreadHandle = CreateThread( + NULL, /* Pointer to thread security attributes. */ + 0, /* Initial thread stack size, in bytes. */ + prvWindowsKeyboardInputThread, /* Pointer to thread function. */ + NULL, /* Argument for new thread. */ + 0, /* Creation flags. */ + NULL); + + /* Use the cores that are not used by the FreeRTOS tasks. */ + SetThreadAffinityMask( xWindowsKeyboardInputThreadHandle, ~0x01u ); + + /* Start keyboard interrupt simulator task. */ + xTaskCreate( + prvKeyboardInterruptSimulatorTask, /* The function that implements the task. */ + "KeyboardInterrupt", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ + configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */ + NULL, /* The parameter passed to the task - not used in this simple case. */ + configMAX_PRIORITIES - 1, /* The priority assigned to the task. The priority is very high as this task simulates an interrupt coming from the keyboard. */ + NULL); /* The task handle is not required, so NULL is passed. */ + + /* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top + * of this file. */ + #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) + { + main_blinky(); + } + #else + { + main_full(); + } + #endif /* if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) */ + + return 0; } /*-----------------------------------------------------------*/ void vApplicationMallocFailedHook( void ) { - /* vApplicationMallocFailedHook() will only be called if - configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook - function that will get called if a call to pvPortMalloc() fails. - pvPortMalloc() is called internally by the kernel whenever a task, queue, - timer or semaphore is created. It is also called by various parts of the - demo application. If heap_1.c, heap_2.c or heap_4.c is being used, then the - size of the heap available to pvPortMalloc() is defined by - configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize() - API function can be used to query the size of free heap space that remains - (although it does not provide information on how the remaining heap might be - fragmented). See http://www.freertos.org/a00111.html for more - information. */ - vAssertCalled( __LINE__, __FILE__ ); + /* vApplicationMallocFailedHook() will only be called if + * configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook + * function that will get called if a call to pvPortMalloc() fails. + * pvPortMalloc() is called internally by the kernel whenever a task, queue, + * timer or semaphore is created. It is also called by various parts of the + * demo application. If heap_1.c, heap_2.c or heap_4.c is being used, then the + * size of the heap available to pvPortMalloc() is defined by + * configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize() + * API function can be used to query the size of free heap space that remains + * (although it does not provide information on how the remaining heap might be + * fragmented). See http://www.freertos.org/a00111.html for more + * information. */ + vAssertCalled( __LINE__, __FILE__ ); } /*-----------------------------------------------------------*/ void vApplicationIdleHook( void ) { - /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set - to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle - task. It is essential that code added to this hook function never attempts - to block in any way (for example, call xQueueReceive() with a block time - specified, or call vTaskDelay()). If application tasks make use of the - vTaskDelete() API function to delete themselves then it is also important - that vApplicationIdleHook() is permitted to return to its calling function, - because it is the responsibility of the idle task to clean up memory - allocated by the kernel to any task that has since deleted itself. */ - - /* Uncomment the following code to allow the trace to be stopped with any - key press. The code is commented out by default as the kbhit() function - interferes with the run time behaviour. */ - /* - if( _kbhit() != pdFALSE ) - { - if( xTraceRunning == pdTRUE ) - { - vTraceStop(); - prvSaveTraceFile(); - xTraceRunning = pdFALSE; - } - } - */ - - #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 ) - { - /* Call the idle task processing used by the full demo. The simple - blinky demo does not use the idle task hook. */ - vFullDemoIdleFunction(); - } - #endif + /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set + * to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle + * task. It is essential that code added to this hook function never attempts + * to block in any way (for example, call xQueueReceive() with a block time + * specified, or call vTaskDelay()). If application tasks make use of the + * vTaskDelete() API function to delete themselves then it is also important + * that vApplicationIdleHook() is permitted to return to its calling function, + * because it is the responsibility of the idle task to clean up memory + * allocated by the kernel to any task that has since deleted itself. */ + + #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 ) + { + /* Call the idle task processing used by the full demo. The simple + * blinky demo does not use the idle task hook. */ + vFullDemoIdleFunction(); + } + #endif } + /*-----------------------------------------------------------*/ -void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ) +void vApplicationStackOverflowHook( TaskHandle_t pxTask, + char * pcTaskName ) { - ( void ) pcTaskName; - ( void ) pxTask; - - /* Run time stack overflow checking is performed if - configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook - function is called if a stack overflow is detected. This function is - provided as an example only as stack overflow checking does not function - when running the FreeRTOS Windows port. */ - vAssertCalled( __LINE__, __FILE__ ); + ( void ) pcTaskName; + ( void ) pxTask; + + /* Run time stack overflow checking is performed if + * configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook + * function is called if a stack overflow is detected. This function is + * provided as an example only as stack overflow checking does not function + * when running the FreeRTOS Windows port. */ + vAssertCalled( __LINE__, __FILE__ ); } /*-----------------------------------------------------------*/ void vApplicationTickHook( void ) { - /* This function will be called by each tick interrupt if - configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be - added here, but the tick hook is called from an interrupt context, so - code must not attempt to block, and only the interrupt safe FreeRTOS API - functions can be used (those that end in FromISR()). */ - - #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 ) - { - vFullDemoTickHookFunction(); - } - #endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY */ + /* This function will be called by each tick interrupt if + * configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be + * added here, but the tick hook is called from an interrupt context, so + * code must not attempt to block, and only the interrupt safe FreeRTOS API + * functions can be used (those that end in FromISR()). */ + + #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 ) + { + vFullDemoTickHookFunction(); + } + #endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY */ } /*-----------------------------------------------------------*/ void vApplicationDaemonTaskStartupHook( void ) { - /* This function will be called once only, when the daemon task starts to - execute (sometimes called the timer task). This is useful if the - application includes initialisation code that would benefit from executing - after the scheduler has been started. */ + /* This function will be called once only, when the daemon task starts to + * execute (sometimes called the timer task). This is useful if the + * application includes initialisation code that would benefit from executing + * after the scheduler has been started. */ } /*-----------------------------------------------------------*/ -void vAssertCalled( unsigned long ulLine, const char * const pcFileName ) +void vAssertCalled( unsigned long ulLine, + const char * const pcFileName ) { -static BaseType_t xPrinted = pdFALSE; -volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0; - - /* Called if an assertion passed to configASSERT() fails. See - http://www.freertos.org/a00110.html#configASSERT for more information. */ - - /* Parameters are not used. */ - ( void ) ulLine; - ( void ) pcFileName; - - printf( "ASSERT! Line %ld, file %s, GetLastError() %ld\r\n", ulLine, pcFileName, GetLastError() ); - - taskENTER_CRITICAL(); - { - /* Stop the trace recording. */ - if( xPrinted == pdFALSE ) - { - xPrinted = pdTRUE; - if( xTraceRunning == pdTRUE ) - { - vTraceStop(); - prvSaveTraceFile(); - } - } - - /* Cause debugger break point if being debugged. */ - __debugbreak(); - - /* You can step out of this function to debug the assertion by using - the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero - value. */ - while( ulSetToNonZeroInDebuggerToContinue == 0 ) - { - __asm{ NOP }; - __asm{ NOP }; - } - } - taskEXIT_CRITICAL(); + static BaseType_t xPrinted = pdFALSE; + volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0; + + /* Called if an assertion passed to configASSERT() fails. See + * http://www.freertos.org/a00110.html#configASSERT for more information. */ + + /* Parameters are not used. */ + ( void ) ulLine; + ( void ) pcFileName; + + taskENTER_CRITICAL(); + { + printf("ASSERT! Line %ld, file %s, GetLastError() %ld\r\n", ulLine, pcFileName, GetLastError()); + + /* Stop the trace recording and save the trace. */ + vTraceStop(); + prvSaveTraceFile(); + + /* Cause debugger break point if being debugged. */ + __debugbreak(); + + /* You can step out of this function to debug the assertion by using + * the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero + * value. */ + while( ulSetToNonZeroInDebuggerToContinue == 0 ) + { + __asm { + NOP + }; + __asm { + NOP + }; + } + + /* Re-enable the trace recording. */ + vTraceEnable( TRC_START ); + } + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ static void prvSaveTraceFile( void ) { -FILE* pxOutputFile; - - fopen_s( &pxOutputFile, "Trace.dump", "wb"); - - if( pxOutputFile != NULL ) - { - fwrite( RecorderDataPtr, sizeof( RecorderDataType ), 1, pxOutputFile ); - fclose( pxOutputFile ); - printf( "\r\nTrace output saved to Trace.dump\r\n" ); - } - else - { - printf( "\r\nFailed to create trace dump file\r\n" ); - } + FILE * pxOutputFile; + + fopen_s( &pxOutputFile, mainTRACE_FILE_NAME, "wb" ); + + if( pxOutputFile != NULL ) + { + fwrite( RecorderDataPtr, sizeof( RecorderDataType ), 1, pxOutputFile ); + fclose( pxOutputFile ); + printf( "\r\nTrace output saved to %s\r\n\r\n", mainTRACE_FILE_NAME ); + } + else + { + printf( "\r\nFailed to create trace dump file\r\n\r\n" ); + } } /*-----------------------------------------------------------*/ -static void prvInitialiseHeap( void ) +static void prvInitialiseHeap( void ) { /* The Windows demo could create one large heap region, in which case it would -be appropriate to use heap_4. However, purely for demonstration purposes, -heap_5 is used instead, so start by defining some heap regions. No -initialisation is required when any other heap implementation is used. See -http://www.freertos.org/a00111.html for more information. - -The xHeapRegions structure requires the regions to be defined in start address -order, so this just creates one big array, then populates the structure with -offsets into the array - with gaps in between and messy alignment just for test -purposes. */ -static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; -volatile uint32_t ulAdditionalOffset = 19; /* Just to prevent 'condition is always true' warnings in configASSERT(). */ -const HeapRegion_t xHeapRegions[] = -{ - /* Start address with dummy offsets Size */ - { ucHeap + 1, mainREGION_1_SIZE }, - { ucHeap + 15 + mainREGION_1_SIZE, mainREGION_2_SIZE }, - { ucHeap + 19 + mainREGION_1_SIZE + mainREGION_2_SIZE, mainREGION_3_SIZE }, - { NULL, 0 } -}; - - /* Sanity check that the sizes and offsets defined actually fit into the - array. */ - configASSERT( ( ulAdditionalOffset + mainREGION_1_SIZE + mainREGION_2_SIZE + mainREGION_3_SIZE ) < configTOTAL_HEAP_SIZE ); - - /* Prevent compiler warnings when configASSERT() is not defined. */ - ( void ) ulAdditionalOffset; - - vPortDefineHeapRegions( xHeapRegions ); + * be appropriate to use heap_4. However, purely for demonstration purposes, + * heap_5 is used instead, so start by defining some heap regions. No + * initialisation is required when any other heap implementation is used. See + * http://www.freertos.org/a00111.html for more information. + * + * The xHeapRegions structure requires the regions to be defined in start address + * order, so this just creates one big array, then populates the structure with + * offsets into the array - with gaps in between and messy alignment just for test + * purposes. */ + static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; + volatile uint32_t ulAdditionalOffset = 19; /* Just to prevent 'condition is always true' warnings in configASSERT(). */ + const HeapRegion_t xHeapRegions[] = + { + /* Start address with dummy offsets Size */ + { ucHeap + 1, mainREGION_1_SIZE }, + { ucHeap + 15 + mainREGION_1_SIZE, mainREGION_2_SIZE }, + { ucHeap + 19 + mainREGION_1_SIZE + mainREGION_2_SIZE, mainREGION_3_SIZE }, + { NULL, 0 } + }; + + /* Sanity check that the sizes and offsets defined actually fit into the + * array. */ + configASSERT( ( ulAdditionalOffset + mainREGION_1_SIZE + mainREGION_2_SIZE + mainREGION_3_SIZE ) < configTOTAL_HEAP_SIZE ); + + /* Prevent compiler warnings when configASSERT() is not defined. */ + ( void ) ulAdditionalOffset; + + vPortDefineHeapRegions( xHeapRegions ); } /*-----------------------------------------------------------*/ /* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an -implementation of vApplicationGetIdleTaskMemory() to provide the memory that is -used by the Idle task. */ -void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) + * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is + * used by the Idle task. */ +void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize ) { /* If the buffers to be provided to the Idle task are declared inside this -function then they must be declared static - otherwise they will be allocated on -the stack and so not exists after this function exits. */ -static StaticTask_t xIdleTaskTCB; -static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; - - /* Pass out a pointer to the StaticTask_t structure in which the Idle task's - state will be stored. */ - *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; - - /* Pass out the array that will be used as the Idle task's stack. */ - *ppxIdleTaskStackBuffer = uxIdleTaskStack; - - /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. - Note that, as the array is necessarily of type StackType_t, - configMINIMAL_STACK_SIZE is specified in words, not bytes. */ - *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + * state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + * Note that, as the array is necessarily of type StackType_t, + * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; } /*-----------------------------------------------------------*/ /* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the -application must provide an implementation of vApplicationGetTimerTaskMemory() -to provide the memory that is used by the Timer service task. */ -void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) + * application must provide an implementation of vApplicationGetTimerTaskMemory() + * to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, + StackType_t ** ppxTimerTaskStackBuffer, + uint32_t * pulTimerTaskStackSize ) { /* If the buffers to be provided to the Timer task are declared inside this -function then they must be declared static - otherwise they will be allocated on -the stack and so not exists after this function exits. */ -static StaticTask_t xTimerTaskTCB; + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + * task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + * Note that, as the array is necessarily of type StackType_t, + * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} +/*-----------------------------------------------------------*/ + +/* + * Windows thread function to capture keyboard input from outside of the + * FreeRTOS simulator. This thread passes data into the simulator using + * an integer. + */ +static DWORD WINAPI prvWindowsKeyboardInputThread( void * pvParam ) +{ + ( void ) pvParam; + + for ( ; ; ) + { + xKeyPressed = _getch(); + } +} + +/*-----------------------------------------------------------*/ - /* Pass out a pointer to the StaticTask_t structure in which the Timer - task's state will be stored. */ - *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; +static void prvKeyboardInterruptSimulatorTask( void * pvParam ) +{ + ( void ) pvParam; + + for ( ; ; ) + { + /* Handle keyboard input. */ + switch ( xKeyPressed ) + { + case mainNO_KEY_PRESS_VALUE: + break; + case mainOUTPUT_TRACE_KEY: + /* Saving the trace file requires Windows system calls, so enter a critical + section to prevent deadlock or errors resulting from calling a Windows + system call from within the FreeRTOS simulator. */ + taskENTER_CRITICAL(); + { + vTraceStop(); + prvSaveTraceFile(); + vTraceEnable(TRC_START); + } + taskEXIT_CRITICAL(); + break; + default: + #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) + { + /* Call the keyboard interrupt handler for the blinky demo. */ + vBlinkyKeyboardInterruptHandler(xKeyPressed); + } + #endif + break; + } + + /* Clear the handled key press. */ + xKeyPressed = mainNO_KEY_PRESS_VALUE; + + /* Yield to allow other tasks to run. */ + vTaskDelay( pdMS_TO_TICKS( mainKEYBOARD_INTERRUPT_YIELD_MS ) ); + } +} - /* Pass out the array that will be used as the Timer task's stack. */ - *ppxTimerTaskStackBuffer = uxTimerTaskStack; +/* The below code is used by the trace recorder for timing. */ +static uint32_t ulEntryTime = 0; - /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. - Note that, as the array is necessarily of type StackType_t, - configMINIMAL_STACK_SIZE is specified in words, not bytes. */ - *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +void vTraceTimerReset( void ) +{ + ulEntryTime = xTaskGetTickCount(); } +uint32_t uiTraceTimerGetFrequency( void ) +{ + return configTICK_RATE_HZ; +} + +uint32_t uiTraceTimerGetValue( void ) +{ + return( xTaskGetTickCount() - ulEntryTime ); +} diff --git a/FreeRTOS/Demo/WIN32-MSVC/main_blinky.c b/FreeRTOS/Demo/WIN32-MSVC/main_blinky.c index 4c08ef5bd..e50fbb581 100644 --- a/FreeRTOS/Demo/WIN32-MSVC/main_blinky.c +++ b/FreeRTOS/Demo/WIN32-MSVC/main_blinky.c @@ -108,6 +108,10 @@ queue send software timer respectively. */ #define mainVALUE_SENT_FROM_TASK ( 100UL ) #define mainVALUE_SENT_FROM_TIMER ( 200UL ) +/* This demo allows for users to perform actions with the keyboard. */ +#define mainNO_KEY_PRESS_VALUE ( -1 ) +#define mainRESET_TIMER_KEY ( 'r' ) + /*-----------------------------------------------------------*/ /* @@ -136,6 +140,8 @@ void main_blinky( void ) { const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS; + printf( "\r\nStarting the blinky demo. Press \'%c\' to reset the software timer used in this demo.\r\n\r\n", mainRESET_TIMER_KEY ); + /* Create the queue. */ xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) ); @@ -155,7 +161,7 @@ const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS; /* Create the software timer, but don't start it yet. */ xTimer = xTimerCreate( "Timer", /* The text name assigned to the software timer - for debug only as it is not used by the kernel. */ xTimerPeriod, /* The period of the software timer in ticks. */ - pdFALSE, /* xAutoReload is set to pdFALSE, so this is a one-shot timer. */ + pdTRUE, /* xAutoReload is set to pdTRUE, so this timer goes off periodically with a period of xTimerPeriod ticks. */ NULL, /* The timer's ID is not used. */ prvQueueSendTimerCallback );/* The function executed when the timer expires. */ @@ -237,37 +243,63 @@ uint32_t ulReceivedValue; Blocked state. */ xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY ); - /* To get here something must have been received from the queue, but - is it an expected value? Normally calling printf() from a task is not - a good idea. Here there is lots of stack space and only one task is - using console IO so it is ok. However, note the comments at the top of - this file about the risks of making Windows system calls (such as - console output) from a FreeRTOS task. */ - if( ulReceivedValue == mainVALUE_SENT_FROM_TASK ) - { - printf( "Message received from task - idle time %llu%%\r\n", ulTaskGetIdleRunTimePercent() ); - } - else if( ulReceivedValue == mainVALUE_SENT_FROM_TIMER ) - { - printf( "Message received from software timer\r\n" ); - } - else - { - printf( "Unexpected message\r\n" ); - } - - /* Reset the timer if a key has been pressed. The timer will write - mainVALUE_SENT_FROM_TIMER to the queue when it expires. */ - if( _kbhit() != 0 ) - { - /* Remove the key from the input buffer. */ - ( void ) _getch(); - - /* Reset the software timer. */ - xTimerReset( xTimer, portMAX_DELAY ); - } + /* Enter critical section to use printf. Not doing this could potentially cause + a deadlock if the FreeRTOS simulator switches contexts and another task + tries to call printf - it should be noted that use of printf within + the FreeRTOS simulator is unsafe, but used here for simplicity. */ + taskENTER_CRITICAL(); + { + /* To get here something must have been received from the queue, but + is it an expected value? Normally calling printf() from a task is not + a good idea. Here there is lots of stack space and only one task is + using console IO so it is ok. However, note the comments at the top of + this file about the risks of making Windows system calls (such as + console output) from a FreeRTOS task. */ + if (ulReceivedValue == mainVALUE_SENT_FROM_TASK) + { + printf("Message received from task - idle time %llu%%\r\n", ulTaskGetIdleRunTimePercent()); + } + else if (ulReceivedValue == mainVALUE_SENT_FROM_TIMER) + { + printf("Message received from software timer\r\n"); + } + else + { + printf("Unexpected message\r\n"); + } + } + taskEXIT_CRITICAL(); } } /*-----------------------------------------------------------*/ +/* Called from prvKeyboardInterruptSimulatorTask(), which is defined in main.c. */ +void vBlinkyKeyboardInterruptHandler( int xKeyPressed ) +{ + /* Handle keyboard input. */ + switch ( xKeyPressed ) + { + case mainRESET_TIMER_KEY: + + if ( xTimer != NULL ) + { + /* Critical section around printf to prevent a deadlock + on context switch. */ + taskENTER_CRITICAL(); + { + printf("\r\nResetting software timer.\r\n\r\n"); + } + taskEXIT_CRITICAL(); + + /* Reset the software timer. */ + xTimerReset( xTimer, portMAX_DELAY ); + } + + break; + + default: + break; + } +} + diff --git a/lexicon.txt b/lexicon.txt index d0161c920..43a371b9b 100644 --- a/lexicon.txt +++ b/lexicon.txt @@ -1132,6 +1132,7 @@ juse katy kbhit keil +keyboardinterrupt keygen keytype khz @@ -1918,6 +1919,7 @@ prvisrblocktask prvisroneshottimercallback prvisrtriggeredtask prvjobsdemotask +prvkeyboardinterruptsimulatortask prvlcdtask prvlcdtaskline prvledtimercallback @@ -2029,6 +2031,7 @@ prvunlockqueue prvupdateacceptedhandler prvupdatedeltahandler prvwin +prvwindowskeyboardinputthread prvwinpcaprecvthread prvwinpcapsendthread prvzerocopyechoclienttask -- cgit v1.2.1