diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt index 716d83bfab..8b711b9ee8 100644 --- a/components/app_trace/CMakeLists.txt +++ b/components/app_trace/CMakeLists.txt @@ -4,14 +4,14 @@ if(${target} STREQUAL "linux") return() # This component is not supported by the POSIX/Linux simulator endif() -if(CONFIG_APPTRACE_ENABLE) +if(CONFIG_ESP_TRACE_TRANSPORT_APPTRACE) set(srcs "app_trace.c" "app_trace_util.c" "host_file_io.c" ) - if(NOT CONFIG_APPTRACE_DEST_UART) # JTAG or ALL + if(NOT CONFIG_APPTRACE_DEST_UART) # JTAG or None if(CONFIG_IDF_TARGET_ARCH_XTENSA) list(APPEND srcs "port/xtensa/port_jtag.c") elseif(CONFIG_IDF_TARGET_ARCH_RISCV) @@ -20,7 +20,7 @@ if(CONFIG_APPTRACE_ENABLE) list(APPEND srcs "app_trace_membufs_proto.c") endif() - if(NOT CONFIG_APPTRACE_DEST_JTAG) # UART or ALL + if(NOT CONFIG_APPTRACE_DEST_JTAG) # UART or None list(APPEND srcs "port/port_uart.c") endif() endif() @@ -33,7 +33,7 @@ set(include_dirs "include") set(priv_include_dirs "private_include" "port/include") -if(CONFIG_APPTRACE_SV_ENABLE) +if(CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW) list(APPEND include_dirs sys_view/Config sys_view/SEGGER diff --git a/components/app_trace/Kconfig b/components/app_trace/Kconfig deleted file mode 100644 index 3bf9024500..0000000000 --- a/components/app_trace/Kconfig +++ /dev/null @@ -1,330 +0,0 @@ -menu "Application Level Tracing" - - config APPTRACE_ENABLE - bool "Enable Application Level Tracing" - default n - help - Enables/disable application tracing module. - This must be enabled to use any tracing library. - - choice APPTRACE_DESTINATION - prompt "Data Destination" - default APPTRACE_DEST_JTAG if !PM_ENABLE - default APPTRACE_DEST_UART if PM_ENABLE - depends on APPTRACE_ENABLE - help - Select destination for application trace: JTAG or UART. - When SystemView is enabled, this also controls the SystemView destination. - - config APPTRACE_DEST_JTAG - bool "JTAG" - select APPTRACE_TRAX_ENABLE if IDF_TARGET_ARCH_XTENSA - depends on !PM_ENABLE - - config APPTRACE_DEST_UART - bool "UART" - - config APPTRACE_DEST_NONE - bool "None (runtime selection)" - help - Compile both JTAG and UART interfaces. Increases IRAM usage. - Allows runtime selection via esp_apptrace_get_user_params(). - - With this option, destination and configuration must be provided - at runtime. Default JTAG and UART settings are defined in - components/app_trace/include/esp_app_trace_config.h. - - Override these by implementing esp_apptrace_get_user_params() - in your application. - endchoice - - config APPTRACE_BUF_SIZE - int "Size of the apptrace buffer" - depends on APPTRACE_DEST_JTAG && !APPTRACE_TRAX_ENABLE - default 16384 - help - Size of the memory buffer for trace data in bytes. - - config APPTRACE_DEST_UART_NUM - int "UART port number" - depends on APPTRACE_DEST_UART - range 0 1 if (SOC_UART_NUM <= 2) - range 0 2 if (SOC_UART_NUM <= 3) - range 0 5 if (SOC_UART_NUM <= 6) - default 1 - help - UART communication port number for the apptrace destination. - See UART documentation for available port numbers. - - config APPTRACE_UART_TX_GPIO - int "UART TX on GPIO" - depends on APPTRACE_DEST_UART - range 0 46 - default 12 - help - This GPIO is used for UART TX pin. - - config APPTRACE_UART_RX_GPIO - int "UART RX on GPIO" - depends on APPTRACE_DEST_UART - range 0 46 - default 13 - help - This GPIO is used for UART RX pin. - - config APPTRACE_UART_BAUDRATE - int - prompt "UART baud rate" if APPTRACE_DEST_UART - depends on APPTRACE_DEST_UART - default 1000000 - range 1200 8000000 - range 1200 1000000 - help - This baud rate is used for UART. - - The app's maximum baud rate depends on the UART clock source. If Power Management is disabled, - the UART clock source is the APB clock and all baud rates in the available range will be sufficiently - accurate. If Power Management is enabled, REF_TICK clock source is used so the baud rate is divided - from 1MHz. Baud rates above 1Mbps are not possible and values between 500Kbps and 1Mbps may not be - accurate. - - config APPTRACE_UART_RX_BUFF_SIZE - int - prompt "UART RX ring buffer size" if APPTRACE_DEST_UART - depends on APPTRACE_DEST_UART - default 128 - range 64 32768 - help - Size of the UART input ring buffer. - This size related to the baudrate, system tick frequency and amount of data to transfer. - The data placed to this buffer before sent out to the interface. - - config APPTRACE_UART_TX_BUFF_SIZE - int - prompt "UART TX ring buffer size" if APPTRACE_DEST_UART - depends on APPTRACE_DEST_UART - default 4096 - range 2048 32768 - help - Size of the UART output ring buffer. - This size related to the baudrate, system tick frequency and amount of data to transfer. - - config APPTRACE_UART_TX_MSG_SIZE - int - prompt "UART TX message size" if APPTRACE_DEST_UART - depends on APPTRACE_DEST_UART - default 128 - range 64 32768 - help - Maximum size of the single message to transfer. - - config APPTRACE_UART_TASK_PRIO - int - prompt "UART Task Priority" if APPTRACE_DEST_UART - depends on APPTRACE_DEST_UART - default 1 - range 1 32 - help - UART task priority. In case of high events rate, - this parameter could be changed up to (configMAX_PRIORITIES-1). - - config APPTRACE_TRAX_ENABLE - bool - depends on IDF_TARGET_ARCH_XTENSA && !ESP32_TRAX && !ESP32S2_TRAX && !ESP32S3_TRAX - select ESP32_MEMMAP_TRACEMEM - select ESP32S2_MEMMAP_TRACEMEM - select ESP32S3_MEMMAP_TRACEMEM - select ESP32_MEMMAP_TRACEMEM_TWOBANKS - select ESP32S2_MEMMAP_TRACEMEM_TWOBANKS - select ESP32S3_MEMMAP_TRACEMEM_TWOBANKS - default n - help - Enables/disable TRAX tracing HW. - - config APPTRACE_LOCK_ENABLE - bool "Internal Sync Lock Enable" - depends on APPTRACE_ENABLE - default n - help - Enables/disable application tracing module internal sync lock. - Keep in mind this will slow down the trace data transfer to the host. - - config APPTRACE_ONPANIC_HOST_FLUSH_TMO - int "Timeout for flushing last trace data to host on panic" - depends on APPTRACE_ENABLE - range -1 5000 - default -1 - help - Timeout for flushing last trace data to host in case of panic. In ms. - Use -1 to disable timeout and wait forever. - - config APPTRACE_POSTMORTEM_FLUSH_THRESH - int "Threshold for flushing last trace data to host on panic" - depends on APPTRACE_ENABLE - range 0 16384 - default 0 - help - Threshold for flushing last trace data to host on panic in post-mortem mode. - This is minimal amount of data needed to perform flush. In bytes. - - menu "FreeRTOS SystemView Tracing" - depends on APPTRACE_ENABLE - config APPTRACE_SV_ENABLE - bool "SystemView Tracing Enable" - depends on APPTRACE_ENABLE - default n - help - Enables support for SEGGER SystemView tracing functionality. - - choice APPTRACE_SV_CPU - prompt "CPU to trace" - depends on APPTRACE_SV_ENABLE && APPTRACE_DEST_UART && !ESP_SYSTEM_SINGLE_CORE_MODE - default APPTRACE_SV_DEST_CPU_0 - help - Define the CPU to trace by SystemView. - - config APPTRACE_SV_DEST_CPU_0 - bool "CPU0" - help - Send SEGGER SystemView events for Pro CPU. - - config APPTRACE_SV_DEST_CPU_1 - bool "CPU1" - help - Send SEGGER SystemView events for App CPU. - - endchoice - - choice APPTRACE_SV_TS_SOURCE - prompt "Timer to use as timestamp source" - depends on APPTRACE_SV_ENABLE - default APPTRACE_SV_TS_SOURCE_CCOUNT if ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 - default APPTRACE_SV_TS_SOURCE_GPTIMER if !ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 - default APPTRACE_SV_TS_SOURCE_ESP_TIMER if PM_ENABLE || IDF_TARGET_ESP32C3 - help - SystemView needs to use a hardware timer as the source of timestamps - when tracing. This option selects the timer for it. - - config APPTRACE_SV_TS_SOURCE_CCOUNT - bool "CPU cycle counter (CCOUNT)" - depends on ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 - - config APPTRACE_SV_TS_SOURCE_GPTIMER - bool "General Purpose Timer (Timer Group)" - depends on !PM_ENABLE && !IDF_TARGET_ESP32C3 - - config APPTRACE_SV_TS_SOURCE_ESP_TIMER - bool "esp_timer high resolution timer" - - endchoice - - config APPTRACE_SV_MAX_TASKS - int "Maximum supported tasks" - depends on APPTRACE_SV_ENABLE - range 1 64 - default 16 - help - Configures maximum supported tasks in sysview debug - - config APPTRACE_SV_BUF_WAIT_TMO - int "Trace buffer wait timeout" - depends on APPTRACE_SV_ENABLE - default 500 - help - Configures timeout (in us) to wait for free space in trace buffer. - Set to -1 to wait forever and avoid lost events. - - config APPTRACE_SV_EVT_OVERFLOW_ENABLE - bool "Trace Buffer Overflow Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Trace Buffer Overflow" event. - - config APPTRACE_SV_EVT_ISR_ENTER_ENABLE - bool "ISR Enter Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "ISR Enter" event. - - config APPTRACE_SV_EVT_ISR_EXIT_ENABLE - bool "ISR Exit Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "ISR Exit" event. - - config APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE - bool "ISR Exit to Scheduler Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "ISR to Scheduler" event. - - config APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE - bool "Task Start Execution Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Start Execution" event. - - config APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE - bool "Task Stop Execution Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Stop Execution" event. - - config APPTRACE_SV_EVT_TASK_START_READY_ENABLE - bool "Task Start Ready State Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Start Ready State" event. - - config APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE - bool "Task Stop Ready State Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Stop Ready State" event. - - config APPTRACE_SV_EVT_TASK_CREATE_ENABLE - bool "Task Create Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Create" event. - - config APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE - bool "Task Terminate Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Terminate" event. - - config APPTRACE_SV_EVT_IDLE_ENABLE - bool "System Idle Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "System Idle" event. - - config APPTRACE_SV_EVT_TIMER_ENTER_ENABLE - bool "Timer Enter Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Timer Enter" event. - - config APPTRACE_SV_EVT_TIMER_EXIT_ENABLE - bool "Timer Exit Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Timer Exit" event. - - endmenu - -endmenu diff --git a/components/app_trace/Kconfig.apptrace b/components/app_trace/Kconfig.apptrace new file mode 100644 index 0000000000..ca609cfb72 --- /dev/null +++ b/components/app_trace/Kconfig.apptrace @@ -0,0 +1,144 @@ +menu "Application Level Tracing" + depends on ESP_TRACE_TRANSPORT_APPTRACE + choice APPTRACE_DESTINATION + prompt "Data Destination" + default APPTRACE_DEST_JTAG if !PM_ENABLE + default APPTRACE_DEST_UART if PM_ENABLE + help + Select destination for application trace: JTAG, UART, or both. + + config APPTRACE_DEST_JTAG + bool "JTAG" + select APPTRACE_TRAX_ENABLE if IDF_TARGET_ARCH_XTENSA + depends on !PM_ENABLE + + config APPTRACE_DEST_UART + bool "UART" + + config APPTRACE_DEST_ALL + bool "All (runtime selection)" + help + Compile both JTAG and UART interfaces in advance (higher IRAM usage). + Allows runtime switching between JTAG and UART via esp_apptrace_get_user_params(). + + If esp_apptrace_get_user_params() is not provided by the + application, JTAG is used by default with the default + configuration defined in components/app_trace/include/esp_app_trace_config.h. + endchoice + + config APPTRACE_BUF_SIZE + int "Size of the apptrace buffer" + depends on APPTRACE_DEST_JTAG && !APPTRACE_TRAX_ENABLE + default 16384 + help + Size of the memory buffer for trace data in bytes. + + config APPTRACE_DEST_UART_NUM + int "UART port number" + depends on APPTRACE_DEST_UART + range 0 1 if (SOC_UART_NUM <= 2) + range 0 2 if (SOC_UART_NUM <= 3) + range 0 5 if (SOC_UART_NUM <= 6) + default 1 + help + UART communication port number for the apptrace destination. + See UART documentation for available port numbers. + + config APPTRACE_UART_TX_GPIO + int "UART TX on GPIO" + depends on APPTRACE_DEST_UART + range 0 46 + default 12 + help + This GPIO is used for UART TX pin. + + config APPTRACE_UART_RX_GPIO + int "UART RX on GPIO" + depends on APPTRACE_DEST_UART + range 0 46 + default 13 + help + This GPIO is used for UART RX pin. + + config APPTRACE_UART_BAUDRATE + int + prompt "UART baud rate" if APPTRACE_DEST_UART + depends on APPTRACE_DEST_UART + default 1000000 + range 1200 8000000 + range 1200 1000000 + help + This baud rate is used for UART. + + The app's maximum baud rate depends on the UART clock source. If Power Management is disabled, + the UART clock source is the APB clock and all baud rates in the available range will be sufficiently + accurate. If Power Management is enabled, REF_TICK clock source is used so the baud rate is divided + from 1MHz. Baud rates above 1Mbps are not possible and values between 500Kbps and 1Mbps may not be + accurate. + + config APPTRACE_UART_TX_BUFF_SIZE + int + prompt "UART TX ring buffer size" if APPTRACE_DEST_UART + depends on APPTRACE_DEST_UART + default 4096 + range 2048 32768 + help + Size of the UART output ring buffer. + This size related to the baudrate, system tick frequency and amount of data to transfer. + + config APPTRACE_UART_TX_MSG_SIZE + int + prompt "UART TX message size" if APPTRACE_DEST_UART + depends on APPTRACE_DEST_UART + default 128 + range 64 32768 + help + Maximum size of the single message to transfer. + + config APPTRACE_UART_TASK_PRIO + int + prompt "UART Task Priority" if APPTRACE_DEST_UART + depends on APPTRACE_DEST_UART + default 1 + range 1 32 + help + UART task priority. In case of high events rate, + this parameter could be changed up to (configMAX_PRIORITIES-1). + + config APPTRACE_TRAX_ENABLE + bool + depends on IDF_TARGET_ARCH_XTENSA && !ESP32_TRAX && !ESP32S2_TRAX && !ESP32S3_TRAX + select ESP32_MEMMAP_TRACEMEM + select ESP32S2_MEMMAP_TRACEMEM + select ESP32S3_MEMMAP_TRACEMEM + select ESP32_MEMMAP_TRACEMEM_TWOBANKS + select ESP32S2_MEMMAP_TRACEMEM_TWOBANKS + select ESP32S3_MEMMAP_TRACEMEM_TWOBANKS + default n + help + Enables/disable TRAX tracing HW. + + config APPTRACE_LOCK_ENABLE + bool "Internal Sync Lock Enable" + default n + help + Enables/disable application tracing module internal sync lock to prevent data corruption + when multiple tasks are writing to the same trace buffer. + Keep in mind this will slow down the trace data transfer to the host. + + config APPTRACE_ONPANIC_HOST_FLUSH_TMO + int "Timeout for flushing last trace data to host on panic" + range -1 5000 + default -1 + help + Timeout for flushing last trace data to host in case of panic. In ms. + Use -1 to disable timeout and wait forever. + + config APPTRACE_POSTMORTEM_FLUSH_THRESH + int "Threshold for flushing last trace data to host on panic" + range 0 16384 + default 0 + help + Threshold for flushing last trace data to host on panic in post-mortem mode. + This is minimal amount of data needed to perform flush. In bytes. +endmenu diff --git a/components/app_trace/app_trace.c b/components/app_trace/app_trace.c index cb8bb2b49d..4a2ff63dbd 100644 --- a/components/app_trace/app_trace.c +++ b/components/app_trace/app_trace.c @@ -32,7 +32,7 @@ typedef struct { static esp_apptrace_channel_t s_trace_ch; static volatile int s_trace_ch_hw_initialized = 0; -static esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config) +esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config) { __attribute__((unused)) void *hw_data = NULL; @@ -44,7 +44,7 @@ static esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config) const esp_apptrace_uart_config_t *uart_config = &config->dest_cfg.uart; s_trace_ch.hw = esp_apptrace_uart_hw_get(uart_config->uart_num, &hw_data); s_trace_ch.hw_data = hw_data; -#else // CONFIG_APPTRACE_DEST_NONE allows runtime selection +#else // CONFIG_APPTRACE_DEST_ALL allows runtime selection between destinations if (config->dest == ESP_APPTRACE_DEST_JTAG) { s_trace_ch.hw = esp_apptrace_jtag_hw_get(&hw_data); s_trace_ch.hw_data = hw_data; @@ -363,6 +363,11 @@ esp_err_t esp_apptrace_set_header_size(esp_apptrace_header_size_t header_size) return ESP_OK; } +/* If any trace library (sysview or external) is selected with the apptrace transport, + * initialization will be handled by the esp_trace component + */ +#if CONFIG_ESP_TRACE_LIB_NONE && CONFIG_ESP_TRACE_TRANSPORT_APPTRACE + esp_apptrace_config_t __attribute__((weak)) esp_apptrace_get_user_params(void) { esp_apptrace_config_t default_config = APPTRACE_CONFIG_DEFAULT(); @@ -374,3 +379,4 @@ ESP_SYSTEM_INIT_FN(apptrace_early_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 11 esp_apptrace_config_t config = esp_apptrace_get_user_params(); return esp_apptrace_init(&config); } +#endif diff --git a/components/app_trace/heap_trace_tohost.c b/components/app_trace/heap_trace_tohost.c index 8ee093b31b..7ee0bd893e 100644 --- a/components/app_trace/heap_trace_tohost.c +++ b/components/app_trace/heap_trace_tohost.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,8 +7,10 @@ #include "freertos/FreeRTOS.h" #include "esp_heap_trace.h" #include "esp_heap_caps.h" -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_TRANSPORT_APPTRACE #include "esp_app_trace.h" +#endif +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW #include "esp_sysview_trace.h" #endif @@ -16,7 +18,7 @@ #if CONFIG_HEAP_TRACING_TOHOST -#if !CONFIG_APPTRACE_SV_ENABLE +#if !CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW #error None of the heap tracing backends is enabled! You must enable SystemView compatible tracing to use this feature. #endif @@ -32,7 +34,7 @@ esp_err_t heap_trace_init_tohost(void) esp_err_t heap_trace_start(heap_trace_mode_t mode_param) { -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW esp_err_t ret = esp_sysview_heap_trace_start((uint32_t) -1); if (ret != ESP_OK) { return ret; @@ -45,7 +47,7 @@ esp_err_t heap_trace_start(heap_trace_mode_t mode_param) esp_err_t heap_trace_stop(void) { esp_err_t ret = ESP_ERR_NOT_SUPPORTED; -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW ret = esp_sysview_heap_trace_stop(); #endif s_tracing = false; @@ -88,7 +90,7 @@ static HEAP_IRAM_ATTR void record_allocation(const heap_trace_record_t *record) if (!s_tracing) { return; } -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW esp_sysview_heap_trace_alloc(record->address, record->size, record->alloced_by); #endif } @@ -103,7 +105,7 @@ static HEAP_IRAM_ATTR void record_free(void *p, void **callers) if (!s_tracing) { return; } -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW esp_sysview_heap_trace_free(p, callers); #endif } diff --git a/components/app_trace/include/esp_app_trace.h b/components/app_trace/include/esp_app_trace.h index ea84866ee0..45cac0526a 100644 --- a/components/app_trace/include/esp_app_trace.h +++ b/components/app_trace/include/esp_app_trace.h @@ -16,22 +16,19 @@ extern "C" { #endif /** - * @brief Get custom trace initialization parameters (optional callback) + * @brief Initializes application tracing module for the selected destination and configuration. * - * This is an optional callback function that user applications can implement to provide - * custom trace configuration. A weak default implementation exists in the app_trace component - * that returns menuconfig defaults (APPTRACE_CONFIG_DEFAULT()). User applications can override - * this by providing their own implementation. - * - * This function is called during early system initialization (before app_main) on all cores. + * @note Should be called before any esp_apptrace_xxx call. * + * @return ESP_OK on success, otherwise see esp_err_t */ -esp_apptrace_config_t esp_apptrace_get_user_params(void); +esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config); /** * @brief Configures down buffer. - * @note Needs to be called before attempting to receive any data using esp_apptrace_down_buffer_get and esp_apptrace_read. - * This function does not protect internal data by lock. + * + * @note Needs to be called before attempting to receive any data using esp_apptrace_down_buffer_get and + * esp_apptrace_read. This function does not protect internal data by lock. * * @param buf Address of buffer to use for down channel (host to target) data. * @param size Size of the buffer. @@ -262,8 +259,8 @@ int esp_apptrace_feof(void *stream); #define APPTRACE_JTAG_CONFIG_DEFAULT() { \ .dest = ESP_APPTRACE_DEST_JTAG, \ .dest_cfg.jtag = {0}, \ - .panic_flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \ - .panic_flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \ + .flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \ + .flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \ } #endif @@ -275,13 +272,12 @@ int esp_apptrace_feof(void *stream); .tx_pin_num = CONFIG_APPTRACE_UART_TX_GPIO, \ .rx_pin_num = CONFIG_APPTRACE_UART_RX_GPIO, \ .baud_rate = CONFIG_APPTRACE_UART_BAUDRATE, \ - .rx_buff_size = CONFIG_APPTRACE_UART_RX_BUFF_SIZE, \ .tx_buff_size = CONFIG_APPTRACE_UART_TX_BUFF_SIZE, \ .tx_msg_size = CONFIG_APPTRACE_UART_TX_MSG_SIZE, \ .task_prio = CONFIG_APPTRACE_UART_TASK_PRIO, \ }, \ - .panic_flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \ - .panic_flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \ + .flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \ + .flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \ } #endif diff --git a/components/app_trace/include/esp_app_trace_config.h b/components/app_trace/include/esp_app_trace_config.h index 0f827da97f..027868d2cb 100644 --- a/components/app_trace/include/esp_app_trace_config.h +++ b/components/app_trace/include/esp_app_trace_config.h @@ -8,10 +8,12 @@ #include "sdkconfig.h" -/* Default configurations for runtime selection (CONFIG_APPTRACE_DEST_NONE) - * These values are used when CONFIG_APPTRACE_DEST_NONE is selected in menuconfig. - * To customize at runtime, implement esp_apptrace_get_user_params() - * in your application. See esp_app_trace.h for details. +/* Default configurations for runtime selection (APPTRACE_DEST_ALL) + * These values are used when building with both JTAG and UART enabled + * to allow runtime selection. You can switch between destinations + * via esp_apptrace_get_user_params(). If this function is + * not provided by the application, JTAG is used by default with the + * configuration defined below. See esp_app_trace.h for details. */ #if !defined(CONFIG_APPTRACE_UART_TX_GPIO) || !defined(CONFIG_APPTRACE_UART_RX_GPIO) @@ -22,10 +24,6 @@ #define CONFIG_APPTRACE_BUF_SIZE 16384 #endif -#ifndef CONFIG_APPTRACE_UART_RX_BUFF_SIZE -#define CONFIG_APPTRACE_UART_RX_BUFF_SIZE 128 -#endif - #ifndef CONFIG_APPTRACE_UART_TX_BUFF_SIZE #define CONFIG_APPTRACE_UART_TX_BUFF_SIZE 4096 #endif @@ -54,8 +52,4 @@ #define CONFIG_APPTRACE_DEST_UART_NUM 1 #endif -#ifndef CONFIG_APPTRACE_SV_DEST_CPU_0 -#define CONFIG_APPTRACE_SV_DEST_CPU_0 1 -#endif - #endif /* ESP_APP_TRACE_CONFIG_H_ */ diff --git a/components/app_trace/include/esp_app_trace_types.h b/components/app_trace/include/esp_app_trace_types.h index ed48376bca..cd4b2dee6f 100644 --- a/components/app_trace/include/esp_app_trace_types.h +++ b/components/app_trace/include/esp_app_trace_types.h @@ -27,7 +27,7 @@ typedef struct { /** Tracing module synchronization lock */ typedef struct { spinlock_t mux; - unsigned int_state; + unsigned int int_state; } esp_apptrace_lock_t; /** Ring buffer control structure. @@ -59,7 +59,6 @@ typedef struct { int tx_pin_num; ///< TX pin number int rx_pin_num; ///< RX pin number int baud_rate; ///< Baud rate - uint32_t rx_buff_size; ///< RX ring buffer size uint32_t tx_buff_size; ///< TX ring buffer size uint32_t tx_msg_size; ///< Maximum size of the single message to transfer. int task_prio; ///< Task priority @@ -86,8 +85,8 @@ typedef struct { } jtag; } dest_cfg; ///< Destination-specific configuration - uint32_t panic_flush_tmo; ///< Panic flush timeout in milliseconds - uint32_t panic_flush_thresh; ///< Panic flush threshold in bytes + uint32_t flush_tmo; ///< Flush timeout in milliseconds + uint32_t flush_thresh; ///< Flush threshold in bytes } esp_apptrace_config_t; #ifdef __cplusplus diff --git a/components/app_trace/include/esp_sysview_trace.h b/components/app_trace/include/esp_sysview_trace.h index 98e2a9c908..3f6ea49b35 100644 --- a/components/app_trace/include/esp_sysview_trace.h +++ b/components/app_trace/include/esp_sysview_trace.h @@ -15,16 +15,37 @@ extern "C" { #include "SEGGER_RTT.h" // SEGGER_RTT_ESP_Flush #include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE +/* Forward declaration for esp_trace integration */ +typedef struct esp_trace_encoder esp_trace_encoder_t; + +/** + * @brief Inject encoder handle to SEGGER RTT layer. + * + * This maintains proper architectural layering. SEGGER RTT can accesses it's transport + * + * @param encoder Pointer to encoder instance from esp_trace + * + * @return 0 if successful, -1 if encoder is not initialized or missing required functions. + */ +int SEGGER_RTT_ESP_SetEncoder(esp_trace_encoder_t *encoder); + +/** + * @brief Get the encoder handle for accessing transport functions. + * + * This is used by SEGGER_SYSVIEW_Config_FreeRTOS.c to access transport lock functions. + * + * @return Pointer to encoder instance, or NULL if not initialized. + */ +esp_trace_encoder_t* SEGGER_SYSVIEW_GetEncoder(void); + /** * @brief Flushes remaining data in SystemView trace buffer to host. * - * @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely. - * * @return ESP_OK. */ -static inline esp_err_t esp_sysview_flush(uint32_t tmo) +static inline esp_err_t esp_sysview_flush(void) { - SEGGER_RTT_ESP_Flush(0, tmo); + SEGGER_RTT_ESP_Flush(); return ESP_OK; } diff --git a/components/app_trace/linker.lf b/components/app_trace/linker.lf index 4223e486de..51473c671c 100644 --- a/components/app_trace/linker.lf +++ b/components/app_trace/linker.lf @@ -1,24 +1,16 @@ [mapping:app_trace] archive: libapp_trace.a entries: - if APPTRACE_ENABLE = y: + if ESP_TRACE_TRANSPORT_APPTRACE = y: app_trace (noflash) app_trace_util (noflash) - if APPTRACE_DEST_JTAG = y || APPTRACE_DEST_NONE = y: + if APPTRACE_DEST_JTAG = y || APPTRACE_DEST_ALL = y: port_jtag (noflash) app_trace_membufs_proto (noflash) - if APPTRACE_DEST_UART = y || APPTRACE_DEST_NONE = y: + if APPTRACE_DEST_UART = y || APPTRACE_DEST_ALL = y: port_uart (noflash) - if APPTRACE_SV_ENABLE = y: - SEGGER_SYSVIEW (noflash) - SEGGER_RTT_esp (noflash) - SEGGER_SYSVIEW_Config_FreeRTOS (noflash) - SEGGER_SYSVIEW_FreeRTOS (noflash) - -[mapping:app_trace_driver] -archive: libesp_driver_gptimer.a -entries: - if APPTRACE_SV_TS_SOURCE_GPTIMER = y: - gptimer: gptimer_get_raw_count (noflash) - else: - * (default) + if ESP_TRACE_LIB_SEGGER_SYSVIEW = y: + SEGGER_SYSVIEW (noflash) + SEGGER_RTT_esp (noflash) + SEGGER_SYSVIEW_Config_FreeRTOS (noflash) + SEGGER_SYSVIEW_FreeRTOS (noflash) diff --git a/components/app_trace/port/port_uart.c b/components/app_trace/port/port_uart.c index f76edc51f0..c7b7920f80 100644 --- a/components/app_trace/port/port_uart.c +++ b/components/app_trace/port/port_uart.c @@ -286,10 +286,9 @@ static void esp_apptrace_uart_down_buffer_config(void *hw_data, uint8_t *buf, ui { esp_apptrace_uart_data_t *uart_data = hw_data; - uart_data->down_buffer = (uint8_t *)malloc(size); - if (uart_data->down_buffer == NULL) { - assert(false && "Failed to allocate apptrace uart down buffer!"); - } + assert(buf != NULL && "Down buffer cannot be NULL"); + + uart_data->down_buffer = buf; uart_data->down_buffer_size = size; } diff --git a/components/app_trace/sdkconfig.rename b/components/app_trace/sdkconfig.rename index 6b61ac0c22..59216fb3ff 100644 --- a/components/app_trace/sdkconfig.rename +++ b/components/app_trace/sdkconfig.rename @@ -3,27 +3,26 @@ CONFIG_ESP32_APPTRACE_DESTINATION CONFIG_APPTRACE_DESTINATION CONFIG_ESP32_APPTRACE_DEST_TRAX CONFIG_APPTRACE_DEST_JTAG -CONFIG_ESP32_APPTRACE_ENABLE CONFIG_APPTRACE_ENABLE +CONFIG_ESP32_APPTRACE_ENABLE CONFIG_ESP_TRACE_TRANSPORT_APPTRACE CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH -CONFIG_SYSVIEW_ENABLE CONFIG_APPTRACE_SV_ENABLE -CONFIG_SYSVIEW_TS_SOURCE CONFIG_APPTRACE_SV_TS_SOURCE -CONFIG_SYSVIEW_TS_SOURCE_CCOUNT CONFIG_APPTRACE_SV_TS_SOURCE_CCOUNT -CONFIG_SYSVIEW_TS_SOURCE_ESP_TIMER CONFIG_APPTRACE_SV_TS_SOURCE_ESP_TIMER -CONFIG_SYSVIEW_MAX_TASKS CONFIG_APPTRACE_SV_MAX_TASKS -CONFIG_SYSVIEW_BUF_WAIT_TMO CONFIG_APPTRACE_SV_BUF_WAIT_TMO -CONFIG_SYSVIEW_EVT_OVERFLOW_ENABLE CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE -CONFIG_SYSVIEW_EVT_ISR_ENTER_ENABLE CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE -CONFIG_SYSVIEW_EVT_ISR_EXIT_ENABLE CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE -CONFIG_SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE -CONFIG_SYSVIEW_EVT_TASK_START_EXEC_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE -CONFIG_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE -CONFIG_SYSVIEW_EVT_TASK_START_READY_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE -CONFIG_SYSVIEW_EVT_TASK_STOP_READY_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE -CONFIG_SYSVIEW_EVT_TASK_CREATE_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE -CONFIG_SYSVIEW_EVT_TASK_TERMINATE_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE -CONFIG_SYSVIEW_EVT_IDLE_ENABLE CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE -CONFIG_SYSVIEW_EVT_TIMER_ENTER_ENABLE CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE -CONFIG_SYSVIEW_EVT_TIMER_EXIT_ENABLE CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE +CONFIG_SYSVIEW_ENABLE CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +CONFIG_SYSVIEW_TS_SOURCE_CCOUNT CONFIG_ESP_TRACE_TS_SOURCE_CCOUNT +CONFIG_SYSVIEW_TS_SOURCE_ESP_TIMER CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER +CONFIG_SYSVIEW_MAX_TASKS CONFIG_SEGGER_SYSVIEW_MAX_TASKS +CONFIG_SYSVIEW_BUF_WAIT_TMO CONFIG_SEGGER_SYSVIEW_BUF_WAIT_TMO +CONFIG_SYSVIEW_EVT_OVERFLOW_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE +CONFIG_SYSVIEW_EVT_ISR_ENTER_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE +CONFIG_SYSVIEW_EVT_ISR_EXIT_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE +CONFIG_SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE +CONFIG_SYSVIEW_EVT_TASK_START_EXEC_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE +CONFIG_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE +CONFIG_SYSVIEW_EVT_TASK_START_READY_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE +CONFIG_SYSVIEW_EVT_TASK_STOP_READY_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE +CONFIG_SYSVIEW_EVT_TASK_CREATE_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE +CONFIG_SYSVIEW_EVT_TASK_TERMINATE_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE +CONFIG_SYSVIEW_EVT_IDLE_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_IDLE_ENABLE +CONFIG_SYSVIEW_EVT_TIMER_ENTER_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE +CONFIG_SYSVIEW_EVT_TIMER_EXIT_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE diff --git a/components/app_trace/sys_view/Kconfig.sysview b/components/app_trace/sys_view/Kconfig.sysview new file mode 100644 index 0000000000..f9366bb49c --- /dev/null +++ b/components/app_trace/sys_view/Kconfig.sysview @@ -0,0 +1,113 @@ +menu "SEGGER SystemView" + depends on ESP_TRACE_LIB_SEGGER_SYSVIEW + choice SEGGER_SYSVIEW_DEST_CPU + prompt "CPU to trace" + depends on ESP_TRACE_TRANSPORT_APPTRACE && APPTRACE_DEST_UART && !ESP_SYSTEM_SINGLE_CORE_MODE + default SEGGER_SYSVIEW_DEST_CPU_0 + help + Define the CPU to trace. + + config SEGGER_SYSVIEW_DEST_CPU_0 + bool "CPU0" + help + Send tracing data for Pro CPU. + + config SEGGER_SYSVIEW_DEST_CPU_1 + bool "CPU1" + help + Send tracing data for App CPU. + + endchoice + + config SEGGER_SYSVIEW_MAX_TASKS + int "Maximum supported tasks" + range 1 64 + default 16 + help + Configures maximum supported tasks in sysview debug + + config SEGGER_SYSVIEW_BUF_WAIT_TMO + int "Trace buffer wait timeout" + default 500 + help + Configures timeout (in us) to wait for free space in trace buffer. + Set to -1 to wait forever and avoid lost events. + + config SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE + bool "Trace Buffer Overflow Event" + default y + help + Enables "Trace Buffer Overflow" event. + + config SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE + bool "ISR Enter Event" + default y + help + Enables "ISR Enter" event. + + config SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE + bool "ISR Exit Event" + default y + help + Enables "ISR Exit" event. + + config SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE + bool "ISR Exit to Scheduler Event" + default y + help + Enables "ISR to Scheduler" event. + + config SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE + bool "Task Start Execution Event" + default y + help + Enables "Task Start Execution" event. + + config SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE + bool "Task Stop Execution Event" + default y + help + Enables "Task Stop Execution" event. + + config SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE + bool "Task Start Ready State Event" + default y + help + Enables "Task Start Ready State" event. + + config SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE + bool "Task Stop Ready State Event" + default y + help + Enables "Task Stop Ready State" event. + + config SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE + bool "Task Create Event" + default y + help + Enables "Task Create" event. + + config SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE + bool "Task Terminate Event" + default y + help + Enables "Task Terminate" event. + + config SEGGER_SYSVIEW_EVT_IDLE_ENABLE + bool "System Idle Event" + default y + help + Enables "System Idle" event. + + config SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE + bool "Timer Enter Event" + default y + help + Enables "Timer Enter" event. + + config SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE + bool "Timer Exit Event" + default y + help + Enables "Timer Exit" event. +endmenu diff --git a/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h b/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h index 6e1c758f0d..15d31ea411 100644 --- a/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h +++ b/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h @@ -401,8 +401,8 @@ unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); -void SEGGER_RTT_ESP_FlushNoLock (unsigned long min_sz, unsigned long tmo); -void SEGGER_RTT_ESP_Flush (unsigned long min_sz, unsigned long tmo); +void SEGGER_RTT_ESP_FlushNoLock (void); +void SEGGER_RTT_ESP_Flush (void); // // Function macro for performance optimization // diff --git a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c index 9761960d75..eb40b843ab 100644 --- a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c +++ b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c @@ -62,17 +62,20 @@ Revision: $Rev: 7745 $ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "SEGGER_SYSVIEW.h" -#include "esp_app_trace.h" -#include "esp_app_trace_util.h" #include "esp_intr_alloc.h" -#include "esp_clk_tree.h" -#include "esp_cpu.h" #include "soc/soc.h" #include "soc/interrupts.h" -#include "esp_private/esp_clk.h" +#include "esp_sysview_trace.h" +#include "esp_trace_port_encoder.h" +#include "esp_trace_port_transport.h" +#include "esp_trace_util.h" extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI; +/* Encoder reference for accessing lock functions + * This is set by SEGGER_RTT_ESP_SetEncoder() during encoder initialization */ +extern esp_trace_encoder_t* SEGGER_SYSVIEW_GetEncoder(void); + /********************************************************************* * * Defines, configurable @@ -87,39 +90,6 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI; // The target core name #define SYSVIEW_CORE_NAME "core0" // In dual core, this will be renamed by OpenOCD as core1 -// Determine which timer to use as timestamp source -#if CONFIG_APPTRACE_SV_TS_SOURCE_CCOUNT -#define TS_USE_CCOUNT 1 -#elif CONFIG_APPTRACE_SV_TS_SOURCE_ESP_TIMER -#define TS_USE_ESP_TIMER 1 -#else -#define TS_USE_TIMERGROUP 1 -#endif - -#if TS_USE_TIMERGROUP -#include "driver/gptimer.h" - -// Timer group timer divisor -#define SYSVIEW_TIMER_DIV 2 - -// GPTimer handle -gptimer_handle_t s_sv_gptimer; - -#endif // TS_USE_TIMERGROUP - -#if TS_USE_ESP_TIMER -// esp_timer provides 1us resolution -#define SYSVIEW_TIMESTAMP_FREQ (1000000) -#endif // TS_USE_ESP_TIMER - -#if TS_USE_CCOUNT -// CCOUNT is incremented at CPU frequency -#define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 1000000) -#endif // TS_USE_CCOUNT - -// System Frequency. -#define SYSVIEW_CPU_FREQ (esp_clk_cpu_freq()) - // The lowest RAM address used for IDs (pointers) #define SYSVIEW_RAM_BASE (SOC_DROM_LOW) @@ -139,9 +109,7 @@ gptimer_handle_t s_sv_gptimer; // disables IRQs (disables rescheduling globally). So we can not use finite timeouts for locks and return error // in case of expiration, because error will not be handled and SEGGER's code will go further implying that // everything is fine, so for multi-core env we have to wait on underlying lock forever -#define SEGGER_LOCK_WAIT_TMO ESP_APPTRACE_TMO_INFINITE - -static esp_apptrace_lock_t s_sys_view_lock = {.mux = portMUX_INITIALIZER_UNLOCKED, .int_state = 0}; +#define SEGGER_LOCK_WAIT_TMO ESP_TRACE_TMO_INFINITE /********************************************************************* * @@ -171,78 +139,51 @@ static void _cbSendSystemDesc(void) { * ********************************************************************** */ -static int SEGGER_SYSVIEW_TS_Init(void) -{ - /* We only need to initialize something if we use Timer Group. - * esp_timer and ccount can be used as is. - */ -#if TS_USE_TIMERGROUP - // get clock source frequency - uint32_t counter_src_hz = 0; - ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz( - (soc_module_clk_t)GPTIMER_CLK_SRC_DEFAULT, - ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz)); - gptimer_config_t config = { - .clk_src = GPTIMER_CLK_SRC_DEFAULT, - .direction = GPTIMER_COUNT_UP, - .resolution_hz = counter_src_hz / SYSVIEW_TIMER_DIV, - }; - // pick any free GPTimer instance - ESP_ERROR_CHECK(gptimer_new_timer(&config, &s_sv_gptimer)); - /* Start counting */ - gptimer_enable(s_sv_gptimer); - gptimer_start(s_sv_gptimer); - return config.resolution_hz; -#else - return SYSVIEW_TIMESTAMP_FREQ; -#endif // TS_USE_TIMERGROUP -} - void SEGGER_SYSVIEW_Conf(void) { U32 disable_evts = 0; - int timestamp_freq = SEGGER_SYSVIEW_TS_Init(); - SEGGER_SYSVIEW_Init(timestamp_freq, SYSVIEW_CPU_FREQ, + int timestamp_freq = esp_trace_timestamp_init(); + SEGGER_SYSVIEW_Init(timestamp_freq, esp_trace_cpu_freq_get(), &SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc); SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE); -#if !CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE disable_evts |= SYSVIEW_EVTMASK_OVERFLOW; #endif -#if !CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE disable_evts |= SYSVIEW_EVTMASK_ISR_ENTER; #endif -#if !CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE disable_evts |= SYSVIEW_EVTMASK_ISR_EXIT; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_START_EXEC; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_EXEC; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_START_READY; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_READY; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_CREATE; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_TERMINATE; #endif -#if !CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_IDLE_ENABLE disable_evts |= SYSVIEW_EVTMASK_IDLE; #endif -#if !CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE disable_evts |= SYSVIEW_EVTMASK_ISR_TO_SCHEDULER; #endif -#if !CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE disable_evts |= SYSVIEW_EVTMASK_TIMER_ENTER; #endif -#if !CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE disable_evts |= SYSVIEW_EVTMASK_TIMER_EXIT; #endif SEGGER_SYSVIEW_DisableEvents(disable_evts); @@ -250,15 +191,7 @@ void SEGGER_SYSVIEW_Conf(void) { U32 SEGGER_SYSVIEW_X_GetTimestamp(void) { -#if TS_USE_TIMERGROUP - uint64_t ts = 0; - gptimer_get_raw_count(s_sv_gptimer, &ts); - return (U32) ts; // return lower part of counter value -#elif TS_USE_CCOUNT - return esp_cpu_get_cycle_count(); -#elif TS_USE_ESP_TIMER - return (U32) esp_timer_get_time(); // return lower part of counter value -#endif + return esp_trace_timestamp_get(); } void SEGGER_SYSVIEW_X_RTT_Lock(void) @@ -271,17 +204,21 @@ void SEGGER_SYSVIEW_X_RTT_Unlock(void) unsigned SEGGER_SYSVIEW_X_SysView_Lock(void) { - esp_apptrace_tmo_t tmo; - esp_apptrace_tmo_init(&tmo, SEGGER_LOCK_WAIT_TMO); - esp_apptrace_lock_take(&s_sys_view_lock, &tmo); - // to be recursive save IRQ status on the stack of the caller to keep it from overwriting - return s_sys_view_lock.int_state; + esp_trace_encoder_t *encoder = SEGGER_SYSVIEW_GetEncoder(); + if (encoder) { + // Use encoder-level lock + return encoder->vt->take_lock(encoder, SEGGER_LOCK_WAIT_TMO); + } + return 0; } void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state) { - s_sys_view_lock.int_state = int_state; - esp_apptrace_lock_give(&s_sys_view_lock); + esp_trace_encoder_t *encoder = SEGGER_SYSVIEW_GetEncoder(); + if (encoder) { + // Use encoder-level unlock + encoder->vt->give_lock(encoder, int_state); + } } /*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h index 9bfa9b0a92..5d67e93e04 100644 --- a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h +++ b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h @@ -75,7 +75,7 @@ Notes: ********************************************************************** */ -#define SYSVIEW_FREERTOS_MAX_NOF_TASKS CONFIG_APPTRACE_SV_MAX_TASKS +#define SYSVIEW_FREERTOS_MAX_NOF_TASKS CONFIG_SEGGER_SYSVIEW_MAX_TASKS /********************************************************************* * diff --git a/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c b/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c index e6ab35f13d..fa93f452aa 100644 --- a/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c +++ b/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c @@ -10,10 +10,13 @@ #include "SEGGER_SYSVIEW.h" #include "SEGGER_SYSVIEW_Conf.h" -#include "esp_app_trace.h" #include "esp_log.h" #include "esp_cpu.h" +#include "esp_trace_port_transport.h" +#include "esp_trace_port_encoder.h" +#include "esp_trace_types.h" #include "esp_private/startup_internal.h" +#include "adapters/adapter_encoder_sysview.h" const static char *TAG = "segger_rtt"; @@ -21,22 +24,27 @@ const static char *TAG = "segger_rtt"; // size of down channel data buf #define SYSVIEW_DOWN_BUF_SIZE 32 -#define SEGGER_STOP_WAIT_TMO 1000000 //us -#if CONFIG_APPTRACE_SV_BUF_WAIT_TMO == -1 -#define SEGGER_HOST_WAIT_TMO ESP_APPTRACE_TMO_INFINITE +#if CONFIG_SEGGER_SYSVIEW_BUF_WAIT_TMO == -1 +#define SEGGER_HOST_WAIT_TMO ESP_TRACE_TMO_INFINITE #else -#define SEGGER_HOST_WAIT_TMO CONFIG_APPTRACE_SV_BUF_WAIT_TMO +#define SEGGER_HOST_WAIT_TMO CONFIG_SEGGER_SYSVIEW_BUF_WAIT_TMO #endif static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ]; static uint16_t s_events_buf_filled; static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE]; -#if CONFIG_APPTRACE_SV_DEST_CPU_0 || CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE -#define APPTRACE_SV_DEST_CPU 0 -#else -#define APPTRACE_SV_DEST_CPU 1 -#endif // CONFIG_APPTRACE_SV_DEST_CPU_0 +/** + * @brief Encoder reference for SEGGER RTT layer + * + * This maintains proper architectural layering: + * - SEGGER RTT is part of the SystemView encoder implementation + * - It accesses transport through the encoder's transport reference (s_encoder->tp) + * - NOT through global singleton (that would be a layer violation) + * + * Set by SEGGER_RTT_ESP_SetEncoder() during encoder init. + */ +static esp_trace_encoder_t *s_encoder = NULL; /********************************************************************* * @@ -45,6 +53,80 @@ static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE]; ********************************************************************** */ +/********************************************************************* +* +* SEGGER_RTT_ESP_SetEncoder() +* +* Function description +* Inject encoder handle from esp_trace adapter. +* This allows SEGGER RTT to access transport through the encoder's +* transport reference, maintaining proper architectural layering. +* +* Parameters +* encoder Pointer to encoder instance from esp_trace +* +* Return value +* 0 if successful, -1 if encoder is not initialized or missing required functions in transport. +*/ +int SEGGER_RTT_ESP_SetEncoder(esp_trace_encoder_t *encoder) +{ + /* Check if adapters have all required functions */ + if (!encoder || !encoder->ctx || + !encoder->vt->give_lock || + !encoder->vt->take_lock || + !encoder->tp->vt->down_buffer_config || + !encoder->tp->vt->write || + !encoder->tp->vt->flush_nolock || + !encoder->tp->vt->read || + !encoder->tp->vt->get_link_type) { + ESP_LOGE(TAG, "Encoder not initialized or missing required functions in transport"); + return -1; + } + + s_encoder = encoder; + + return 0; +} + +/********************************************************************* +* +* SEGGER_SYSVIEW_GetEncoder() +* +* Function description +* Returns the encoder handle for accessing transport functions. +* This is used by SEGGER_SYSVIEW_Config_FreeRTOS.c to access +* transport lock functions. +* +* Parameters +* None +* +* Return value +* Pointer to encoder instance, or NULL if not initialized. +*/ +esp_trace_encoder_t* SEGGER_SYSVIEW_GetEncoder(void) +{ + return s_encoder; +} + +/********************************************************************* +* +* SEGGER_RTT_ESP_GetDestCpu() +* +* Function description +* Gets the destination CPU from the encoder context. +* +* Parameters +* None +* +* Return value +* CPU ID (0 or 1) to trace +*/ +static int SEGGER_RTT_ESP_GetDestCpu(void) +{ + sysview_encoder_ctx_t *ctx = s_encoder->ctx; + return ctx->dest_cpu; +} + /********************************************************************* * * SEGGER_RTT_ESP_FlushNoLock() @@ -59,20 +141,29 @@ static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE]; * Return value * None. */ -void SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz, unsigned long tmo) +void SEGGER_RTT_ESP_FlushNoLock(void) { esp_err_t res; + + if (!s_encoder) { + ESP_LOGE(TAG, "Encoder not initialized"); + return; + } + + esp_trace_transport_t *tp = s_encoder->tp; + if (s_events_buf_filled > 0) { - res = esp_apptrace_write(s_events_buf, s_events_buf_filled, tmo); + res = tp->vt->write(tp, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO); if (res != ESP_OK) { - ESP_LOGE(TAG, "Failed to flush buffered events (%d)!", res); + ESP_LOGE(TAG, "Failed to write buffered events (%d)!", res); } } // flush even if we failed to write buffered events, because no new events will be sent after STOP - res = esp_apptrace_flush_nolock(min_sz, tmo); + res = tp->vt->flush_nolock(tp); if (res != ESP_OK) { - ESP_LOGE(TAG, "Failed to flush apptrace data (%d)!", res); + ESP_LOGE(TAG, "Failed to flush buffered events (%d)!", res); } + s_events_buf_filled = 0; } @@ -83,17 +174,14 @@ void SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz, unsigned long tmo) * Function description * Flushes buffered events. * -* Parameters -* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. JTAG destinations only. -* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely. * * Return value * None. */ -void SEGGER_RTT_ESP_Flush(unsigned long min_sz, unsigned long tmo) +void SEGGER_RTT_ESP_Flush(void) { SEGGER_SYSVIEW_LOCK(); - SEGGER_RTT_ESP_FlushNoLock(min_sz, tmo); + SEGGER_RTT_ESP_FlushNoLock(); SEGGER_SYSVIEW_UNLOCK(); } @@ -116,12 +204,12 @@ void SEGGER_RTT_ESP_Flush(unsigned long min_sz, unsigned long tmo) */ unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { - uint32_t size = BufferSize; - esp_err_t res = esp_apptrace_read(pData, &size, 0); - if (res != ESP_OK) { + if (!s_encoder) { return 0; } - return size; + size_t size = BufferSize; + esp_err_t res = s_encoder->tp->vt->read(s_encoder->tp, pData, &size, 0); + return res != ESP_OK ? 0 : size; } /********************************************************************* @@ -150,12 +238,18 @@ unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned Buffe */ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + if (!s_encoder) { + return 0; // Encoder is not initialized + } + + esp_trace_transport_t *tp = s_encoder->tp; uint8_t *pbuf = (uint8_t *)pBuffer; uint8_t event_id = *pbuf; - if (esp_apptrace_get_destination() == ESP_APPTRACE_DEST_UART) { + if (tp->vt->get_link_type(tp) == ESP_TRACE_LINK_UART) { + int dest_cpu = SEGGER_RTT_ESP_GetDestCpu(); if ( - (APPTRACE_SV_DEST_CPU != esp_cpu_get_core_id()) && + (dest_cpu != esp_cpu_get_core_id()) && ( (event_id == SYSVIEW_EVTID_ISR_ENTER) || (event_id == SYSVIEW_EVTID_ISR_EXIT) || @@ -185,7 +279,7 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes); return 0; } - if (esp_apptrace_get_destination() == ESP_APPTRACE_DEST_JTAG) { + if (tp->vt->get_link_type(tp) == ESP_TRACE_LINK_DEBUG_PROBE) { if (esp_cpu_get_core_id()) { // dual core specific code // use the highest - 1 bit of event ID to indicate core ID // the highest bit can not be used due to event ID encoding method @@ -199,7 +293,7 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) { - esp_err_t res = esp_apptrace_write(s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO); + esp_err_t res = tp->vt->write(tp, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO); if (res != ESP_OK) { return 0; // skip current data buffer only, accumulated events are kept } @@ -209,8 +303,8 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes); s_events_buf_filled += NumBytes; - if (esp_apptrace_get_destination() == ESP_APPTRACE_DEST_UART) { - esp_err_t res = esp_apptrace_write(pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO); + if (tp->vt->get_link_type(tp) == ESP_TRACE_LINK_UART) { + esp_err_t res = tp->vt->write(tp, pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO); if (res != ESP_OK) { return 0; // skip current data buffer only, accumulated events are kept } @@ -218,7 +312,7 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u } if (event_id == SYSVIEW_EVTID_TRACE_STOP) { - SEGGER_RTT_ESP_FlushNoLock(0, SEGGER_STOP_WAIT_TMO); + SEGGER_RTT_ESP_FlushNoLock(); } return NumBytes; } @@ -281,20 +375,8 @@ int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBu */ int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - return esp_apptrace_down_buffer_config(s_down_buf, sizeof(s_down_buf)); + if (!s_encoder) { + return -1; + } + return s_encoder->tp->vt->down_buffer_config(s_encoder->tp, s_down_buf, sizeof(s_down_buf)); } - -/*************************** Init hook **************************** - * - * This init function is placed here because this port file will be linked whenever SystemView is used. - * It is used to initialize SystemView and app trace configuration by the init hook function. - * Otherwise, SystemView and app trace initialization needs to be done later in the app_main. - */ -ESP_SYSTEM_INIT_FN(sysview_early_init, SECONDARY, BIT(0), 120) -{ - esp_apptrace_set_header_size(ESP_APPTRACE_HEADER_SIZE_16); - SEGGER_SYSVIEW_Conf(); - - return ESP_OK; -} -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/ext/heap_trace_module.c b/components/app_trace/sys_view/ext/heap_trace_module.c index cbe81723d8..fc149c2e49 100644 --- a/components/app_trace/sys_view/ext/heap_trace_module.c +++ b/components/app_trace/sys_view/ext/heap_trace_module.c @@ -51,7 +51,7 @@ esp_err_t esp_sysview_heap_trace_start(uint32_t tmo) esp_err_t esp_sysview_heap_trace_stop(void) { ESP_EARLY_LOGV(TAG, "%s", __func__); - SEGGER_RTT_ESP_Flush(0, ESP_APPTRACE_TMO_INFINITE); + SEGGER_RTT_ESP_Flush(); return ESP_OK; } diff --git a/components/app_trace/test_apps/main/CMakeLists.txt b/components/app_trace/test_apps/main/CMakeLists.txt index 4578149400..ea49d3b904 100644 --- a/components/app_trace/test_apps/main/CMakeLists.txt +++ b/components/app_trace/test_apps/main/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register(SRCS "test_app_trace_main.c" "test_trace.c" INCLUDE_DIRS "." - PRIV_REQUIRES app_trace unity esp_driver_gptimer + PRIV_REQUIRES esp_trace unity esp_driver_gptimer WHOLE_ARCHIVE) diff --git a/components/app_trace/test_apps/main/test_trace.c b/components/app_trace/test_apps/main/test_trace.c index c4d4fcf200..1748821522 100644 --- a/components/app_trace/test_apps/main/test_trace.c +++ b/components/app_trace/test_apps/main/test_trace.c @@ -65,7 +65,7 @@ const static char *TAG = "esp_apptrace_test"; #define ESP_APPTRACE_TEST_LOGV( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(V, ESP_LOG_VERBOSE, format, ##__VA_ARGS__) #define ESP_APPTRACE_TEST_LOGO( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(E, ESP_LOG_NONE, format, ##__VA_ARGS__) -#if CONFIG_APPTRACE_SV_ENABLE == 0 +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW == 0 #define ESP_APPTRACE_TEST_WRITE(_b_, _s_) esp_apptrace_write(_b_, _s_, ESP_APPTRACE_TMO_INFINITE) #define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(_b_, _s_, 0UL) #define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(_b_, _s_, 0) @@ -694,7 +694,7 @@ TEST_CASE("Log trace test (2 tasks)", "[trace][ignore]") vSemaphoreDelete(arg2.done); } -#else // #if CONFIG_APPTRACE_SV_ENABLE == 0 +#else // #if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW == 0 typedef struct { gptimer_handle_t gptimer; @@ -922,4 +922,4 @@ TEST_CASE("SysView trace test 2", "[trace][ignore]") TEST_ESP_OK(gptimer_disable(tim_arg2.gptimer)); TEST_ESP_OK(gptimer_del_timer(tim_arg2.gptimer)); } -#endif // #if CONFIG_APPTRACE_SV_ENABLE == 0 +#endif // CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW == 0 diff --git a/components/app_trace/test_apps/sdkconfig.ci.app_trace b/components/app_trace/test_apps/sdkconfig.ci.app_trace index ce6deb8676..c2a35aea83 100644 --- a/components/app_trace/test_apps/sdkconfig.ci.app_trace +++ b/components/app_trace/test_apps/sdkconfig.ci.app_trace @@ -1 +1,3 @@ -# app_trace is already enabled by sdkconfig.defaults, so no options are needed here +CONFIG_ESP_TRACE_LIB_NONE=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +CONFIG_APPTRACE_DEST_JTAG=y diff --git a/components/app_trace/test_apps/sdkconfig.ci.sysview b/components/app_trace/test_apps/sdkconfig.ci.sysview index 0308ac377b..73ca998c6c 100644 --- a/components/app_trace/test_apps/sdkconfig.ci.sysview +++ b/components/app_trace/test_apps/sdkconfig.ci.sysview @@ -1 +1,3 @@ -CONFIG_APPTRACE_SV_ENABLE=y +CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +CONFIG_APPTRACE_DEST_JTAG=y diff --git a/components/app_trace/test_apps/sdkconfig.defaults b/components/app_trace/test_apps/sdkconfig.defaults index 2931bc4052..4b6639bbc1 100644 --- a/components/app_trace/test_apps/sdkconfig.defaults +++ b/components/app_trace/test_apps/sdkconfig.defaults @@ -1,3 +1,2 @@ CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n -CONFIG_APPTRACE_ENABLE=y -CONFIG_APPTRACE_DEST_JTAG=y +CONFIG_ESP_TRACE_ENABLE=y diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index f55c35b632..942e681c4f 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/components/esp_hw_support/intr_alloc.c @@ -481,7 +481,7 @@ static void ESP_INTR_IRAM_ATTR shared_intr_isr(void *arg) esp_os_exit_critical_isr(&spinlock); } -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW //Common non-shared isr handler wrapper. static void ESP_INTR_IRAM_ATTR non_shared_intr_isr(void *arg) { @@ -489,7 +489,7 @@ static void ESP_INTR_IRAM_ATTR non_shared_intr_isr(void *arg) esp_os_enter_critical_isr(&spinlock); traceISR_ENTER(ns_isr_arg->source + ETS_INTERNAL_INTR_SOURCE_OFF); // FIXME: can we call ISR and check os_task_switch_is_pended() after releasing spinlock? - // when CONFIG_APPTRACE_SV_ENABLE = 0 ISRs for non-shared IRQs are called without spinlock + // when CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW = 0 ISRs for non-shared IRQs are called without spinlock ns_isr_arg->isr(ns_isr_arg->isr_arg); // check if we will return to scheduler or to interrupted task after ISR if (!os_task_switch_is_pended(esp_cpu_get_core_id())) { @@ -631,7 +631,7 @@ esp_err_t esp_intr_alloc_intrstatus_bind(int source, int flags, uint32_t intrsta //Mark as unusable for other interrupt sources. This is ours now! vd->flags = VECDESC_FL_NONSHARED; if (handler) { -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW non_shared_isr_arg_t *ns_isr_arg = heap_caps_malloc(sizeof(non_shared_isr_arg_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); if (!ns_isr_arg) { esp_os_exit_critical(&spinlock); @@ -831,7 +831,7 @@ static esp_err_t intr_free_for_current_cpu(intr_handle_t handle) if ((handle->vector_desc->flags & VECDESC_FL_NONSHARED) || free_shared_vector) { ESP_EARLY_LOGV(TAG, "esp_intr_free: Disabling int, killing handler"); -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW if (!free_shared_vector) { void *isr_arg = esp_cpu_intr_get_handler_arg(handle->vector_desc->intno); if (isr_arg) { diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index 971f51a17b..d09f05a906 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -130,8 +130,8 @@ target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_system_include_startup_ # [refactor-todo] requirements due to init code, should be removable # once link-time registration of component init functions is used. -if(CONFIG_APPTRACE_ENABLE) - idf_component_optional_requires(PRIVATE app_trace) +if(CONFIG_ESP_TRACE_ENABLE) + idf_component_optional_requires(PRIVATE esp_trace) endif() if(CONFIG_ESP_COREDUMP_ENABLE) diff --git a/components/esp_system/panic.c b/components/esp_system/panic.c index 660459b5eb..d269dd9c74 100644 --- a/components/esp_system/panic.c +++ b/components/esp_system/panic.c @@ -37,19 +37,10 @@ #include "esp_core_dump.h" #endif -#if CONFIG_APPTRACE_ENABLE -#include "esp_app_trace.h" -#if CONFIG_APPTRACE_SV_ENABLE -#include "SEGGER_RTT.h" +#if CONFIG_ESP_TRACE_ENABLE +#include "esp_trace.h" #endif -#if CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO == -1 -#define APPTRACE_ONPANIC_HOST_FLUSH_TMO ESP_APPTRACE_TMO_INFINITE -#else -#define APPTRACE_ONPANIC_HOST_FLUSH_TMO (1000*CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO) -#endif -#endif // CONFIG_APPTRACE_ENABLE - #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT #include "hal/uart_hal.h" #endif @@ -367,12 +358,9 @@ void esp_panic_handler(panic_info_t *info) panic_print_str("Setting breakpoint at 0x"); panic_print_hex((uint32_t)info->addr); panic_print_str(" and returning...\r\n"); -#if CONFIG_APPTRACE_ENABLE -#if CONFIG_APPTRACE_SV_ENABLE - SEGGER_RTT_ESP_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); -#else - esp_apptrace_flush_nolock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); -#endif + +#if CONFIG_ESP_TRACE_ENABLE + esp_trace_panic_handler(info); #endif disable_all_wdts(); @@ -408,14 +396,10 @@ void esp_panic_handler(panic_info_t *info) panic_print_str("\r\n"); -#if CONFIG_APPTRACE_ENABLE +#if CONFIG_ESP_TRACE_ENABLE esp_panic_handler_feed_wdts(); -#if CONFIG_APPTRACE_SV_ENABLE - SEGGER_RTT_ESP_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); -#else - esp_apptrace_flush_nolock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); + esp_trace_panic_handler(info); #endif -#endif // CONFIG_APPTRACE_ENABLE #if CONFIG_ESP_COREDUMP_ENABLE esp_panic_handler_feed_wdts(); @@ -479,12 +463,8 @@ void __attribute__((noreturn, no_sanitize_undefined)) panic_abort(const char *de g_panic_abort = true; g_panic_abort_details = (char *) details; -#if CONFIG_APPTRACE_ENABLE -#if CONFIG_APPTRACE_SV_ENABLE - SEGGER_RTT_ESP_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); -#else - esp_apptrace_flush_nolock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); -#endif +#if CONFIG_ESP_TRACE_ENABLE + esp_trace_panic_handler(NULL); #endif #ifdef __XTENSA__ diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index fd665d90d4..5e048324b9 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -91,9 +91,11 @@ SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/p SECONDARY: 107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0) SECONDARY: 108: sleep_mmu_startup_init in components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c on BIT(0) -# app_trace has to be initialized before systemview +# app_trace doesn't have init dependencies SECONDARY: 115: apptrace_early_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES -SECONDARY: 120: sysview_early_init in components/app_trace/sys_view/esp/SEGGER_RTT_esp.c on BIT(0) + +# esp_trace doesn't have init dependencies +SECONDARY: 120: esp_trace_early_init in components/esp_trace/src/core/esp_trace_core.c on ESP_SYSTEM_INIT_ALL_CORES # coredump doesn't have init dependencies SECONDARY: 130: init_coredump in components/espcoredump/src/core_dump_init.c on BIT(0) diff --git a/components/esp_trace/CMakeLists.txt b/components/esp_trace/CMakeLists.txt new file mode 100644 index 0000000000..f32c0d6d8d --- /dev/null +++ b/components/esp_trace/CMakeLists.txt @@ -0,0 +1,38 @@ +idf_build_get_property(target IDF_TARGET) + +if(${target} STREQUAL "linux") + return() +endif() + +if(CONFIG_ESP_TRACE_ENABLE) + set(srcs + "src/core/esp_trace_core.c" + "src/core/esp_trace_registry.c" + "src/ports/port_utils.c" + ) + + if(CONFIG_ESP_TRACE_TRANSPORT_APPTRACE) + list(APPEND srcs "adapters/transport/adapter_transport_apptrace.c") + endif() + + if(CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW) + list(APPEND srcs "adapters/encoder/adapter_encoder_sysview.c") + endif() + +endif() + +set(includes + "include" +) + +set(priv_requires "esp_driver_gptimer") +set(priv_includes "") +set(requires "app_trace") + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${includes} + PRIV_INCLUDE_DIRS ${priv_includes} + PRIV_REQUIRES ${priv_requires} + REQUIRES ${requires} + WHOLE_ARCHIVE TRUE + LDFRAGMENTS linker.lf) diff --git a/components/esp_trace/Kconfig b/components/esp_trace/Kconfig new file mode 100644 index 0000000000..b6f7ec9a9b --- /dev/null +++ b/components/esp_trace/Kconfig @@ -0,0 +1,90 @@ +menu "ESP Trace Configuration" + + choice ESP_TRACE_LIBRARY + prompt "Trace library" + default ESP_TRACE_LIB_NONE + help + Select the trace library to use. + + config ESP_TRACE_LIB_SEGGER_SYSVIEW + bool "SEGGER SystemView" + + config ESP_TRACE_LIB_EXTERNAL + bool "External library from component registry" + help + Use a custom encoder provided by an external component. + The trace core system will be enabled but no built-in encoder is included. + + The external component MUST provide a header file named + "esp_trace_freertos_impl.h" in its include directories that + defines all required FreeRTOS trace macros. + + config ESP_TRACE_LIB_NONE + bool "Disabled" + endchoice + + config ESP_TRACE_LIB_NAME + string + default "sysview" if ESP_TRACE_LIB_SEGGER_SYSVIEW + default "ext" if ESP_TRACE_LIB_EXTERNAL + default "none" if ESP_TRACE_LIB_NONE + + rsource "$IDF_PATH/components/app_trace/sys_view/Kconfig.sysview" + + choice ESP_TRACE_TRANSPORT + prompt "Trace transport" + default ESP_TRACE_TRANSPORT_NONE + help + Select the trace backend to use. + + config ESP_TRACE_TRANSPORT_APPTRACE + bool "ESP-IDF apptrace" + + config ESP_TRACE_TRANSPORT_EXTERNAL + bool "External transport from component registry" + depends on !ESP_TRACE_LIB_NONE + help + Use a transport registered by an external component. + The trace core system will be enabled but no built-in transport is included. + + config ESP_TRACE_TRANSPORT_NONE + bool "None" + endchoice + + config ESP_TRACE_TRANSPORT_NAME + string + default "apptrace" if ESP_TRACE_TRANSPORT_APPTRACE + default "ext" if ESP_TRACE_TRANSPORT_EXTERNAL + default "none" if ESP_TRACE_TRANSPORT_NONE + + config ESP_TRACE_ENABLE + bool + default !ESP_TRACE_LIB_NONE + help + Internal config to enable tracing dependency around components. + + rsource "$IDF_PATH/components/app_trace/Kconfig.apptrace" + + choice ESP_TRACE_TIMESTAMP_SOURCE + depends on ESP_TRACE_ENABLE + prompt "Trace timestamp source" + default ESP_TRACE_TS_SOURCE_CCOUNT if ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 + default ESP_TRACE_TS_SOURCE_GPTIMER if !ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 + default ESP_TRACE_TS_SOURCE_ESP_TIMER if PM_ENABLE || IDF_TARGET_ESP32C3 + help + Select the timestamp source for tracing. + + config ESP_TRACE_TS_SOURCE_CCOUNT + bool "CPU cycle counter (CCOUNT)" + depends on ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 + + config ESP_TRACE_TS_SOURCE_GPTIMER + bool "General Purpose Timer (Timer Group)" + depends on !PM_ENABLE && !IDF_TARGET_ESP32C3 + + config ESP_TRACE_TS_SOURCE_ESP_TIMER + bool "esp_timer high resolution timer" + + endchoice + +endmenu diff --git a/components/esp_trace/README.md b/components/esp_trace/README.md new file mode 100644 index 0000000000..3c6ca01c42 --- /dev/null +++ b/components/esp_trace/README.md @@ -0,0 +1,383 @@ +# ESP Trace Component + +The `esp_trace` component provides a unified tracing infrastructure for ESP-IDF. It acts as a central hub that coordinates different trace libraries (like SEGGER SystemView) and trace transports (like apptrace over JTAG/UART). + +## Overview + +The `esp_trace` component enables: +- Integration of multiple trace libraries through a common interface +- Flexible transport layer selection (JTAG, UART, or custom) +- Centralized trace configuration and management +- Support for both built-in and external trace libraries + +## Architecture + +The `esp_trace` component uses a **Port & Adapter** design pattern (also known as Hexagonal Architecture) to provide flexibility and extensibility: + +```mermaid +flowchart TB + +%% ======================= +%% Application Layer +%% ======================= +subgraph APP["📱 APPLICATION"] + app_main["app_main()"] + sysview_tracing["sysview_tracing.c"] + examples["tracing_heap_log.c"] + freertos_events["FreeRTOS Events"] +end + + +%% ======================= +%% Primary Port (Driver Port) +%% ======================= +subgraph PRIMARY["🔌 PUBLIC INTERFACE"] + api["- esp_trace.h + - esp_trace_init() + - esp_trace_record() + - esp_trace_write() + - esp_trace_flush() + - esp_trace_print()"] +end + +%% wiring: App uses API (labels land on the short pre-edges to api_in) +app_main -->|esp_trace.h| api +sysview_tracing -->|esp_trace.h| api +examples -->|esp_trace.h| api +freertos_events -->|trace macros| api +%% ======================= +%% Core Domain +%% ======================= +subgraph CORE["⚙️ CORE DOMAIN"] + corec["- esp_trace_core.c + - Creates encoder + transport instances + - Thread safe multi-core init + - Adapter coordination"] + regc["esp_trace_registry.c + - Runtime adapter discovery + - Maps names to vtables"] +end + +api --> corec +corec --- regc + +%% ======================= +%% Ports (Outbound) +%% ======================= +subgraph PORT_ENC["🔌 PORT Encoder"] + enc_port["esp_trace_port_encoder.h + Interface: + - init() + - print_event() + - write() + - flush()"] +end + +subgraph PORT_TR["🔌 PORT Transport"] + tr_port["esp_trace_port_transport.h + Interface: + - init() + - write() + - flush() + - is_host_connected()"] +end + +corec --> enc_port +corec --> tr_port + +%% ======================= +%% Adapters +%% ======================= +subgraph ADAPTERS["🔶 ADAPTERS"] + %% Encoders + enc_sysview["encoder_sysview.c implements sysview vtable"] + enc_ctf["encoder_ctf.c implements ctf vtable"] + enc_percepio["encoder_percepio.c implements percepio vtable"] + + %% Transports + tr_apptrace["transport_apptrace.c implements apptrace vtable"] +end + +enc_port --> enc_sysview +enc_port --> enc_ctf +enc_port --> enc_percepio +tr_port --> tr_apptrace + +%% ======================= +%% Host tools +%% ======================= +subgraph HOST_TOOLS["💻 TOOLS"] + direction LR + view_openocd["OpenOCD"] + view_sysview["SEGGER SystemView"] + view_ctf["Trace Compass"] + view_perfetto["Perfetto"] + view_babeltrace["Babeltrace2"] + view_percepio["TraceAlyzer"] +end + +%% invisible hub to center align +hub(("HOST")) + +%% Adapters feed into the hub (not directly into subgraph) +enc_sysview --> hub +enc_ctf --> hub +tr_apptrace --> hub + +%% hub connects downward to host tools +hub --> view_openocd & view_sysview & view_ctf & view_perfetto & view_babeltrace & view_percepio + +%% Styling +classDef appStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#000 +classDef primaryStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#000 +classDef coreStyle fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000 +classDef portStyle fill:#e1f5fe,stroke:#0277bd,stroke-width:3px,color:#000 +classDef adapterStyle fill:#fff9c4,stroke:#f9a825,stroke-width:2px,color:#000 +classDef hostStyle fill:#e8f5e9,stroke:#388e3c,stroke-width:2px,color:#000 +classDef hubStyle fill:#ffebee,stroke:#c62828,stroke-width:3px,color:#000 + +class APP appStyle +class PRIMARY,api primaryStyle +class CORE,corec,regc coreStyle +class PORT_ENC,PORT_TR,enc_port,tr_port portStyle +class ADAPTERS,enc_sysview,enc_ctf,enc_percepio,tr_apptrace adapterStyle +class HOST_TOOLS,view_openocd,view_sysview,view_ctf,view_perfetto,view_babeltrace,view_percepio hostStyle +class hub hubStyle + +``` + +The architecture follows a layered Port & Adapter pattern where the core manages trace sessions and coordinates adapters through well-defined interfaces (ports). Applications interact with a public API that forwards calls to the core, which then delegates work to encoder adapters (for trace formatting) and transport adapters (for data transmission). The registry enables runtime discovery of adapters that register themselves at link time using `ESP_TRACE_REGISTER_ENCODER()` and `ESP_TRACE_REGISTER_TRANSPORT()` macros. Encoders use transport ports to send formatted trace data, allowing any encoder to work with any transport. This separation means you can, for example, use SystemView with JTAG, other library with UART, or any other combination without modifying the core or adapters themselves. + +## How to Enable + +### Using Menuconfig + +1. Go to `Component config` → `ESP Trace Configuration` +2. Select your desired trace transport under `Trace transport`: + - **ESP-IDF apptrace** - Use built-in apptrace for custom tracing + - **None** - Disable tracing transport +3. Select your trace library under `Trace library`: + - **SEGGER SystemView** - Enable SystemView tracing + - **None** - Use standalone apptrace without a library + +### Using sdkconfig + +For standalone apptrace (without a trace library): + +``` +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_NONE=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +``` + +For SystemView tracing over JTAG: + +``` +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_SYSVIEW=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +CONFIG_APPTRACE_DEST_JTAG=y +``` + +## Component Dependencies + +To use tracing in your application, add `esp_trace` to your component's dependencies in `CMakeLists.txt`: + +```cmake +idf_component_register( + SRCS "main.c" + INCLUDE_DIRS "." + REQUIRES esp_trace +) +``` + +The `esp_trace` component will automatically include necessary sub-components (like `app_trace`) based on your configuration. + +## Adding External Trace Libraries + +The `esp_trace` component supports integration of external trace libraries through two types of adapters: + +- **Transport Adapters**: Handle the physical transport layer (e.g., JTAG, UART) +- **Encoder Adapters**: Handle the trace encoding/formatting (e.g., SystemView, custom formats) + +### Creating a Transport Adapter + +Transport adapters provide the physical communication layer for trace data. + +**Example: Creating a custom transport adapter** + +```c +#include "esp_trace_registry.h" +#include "esp_trace_port_transport.h" + +static esp_err_t my_transport_init(esp_trace_transport_t *tp, const void *cfg) +{ + // Initialize your transport + return ESP_OK; +} + +static esp_err_t my_transport_write(esp_trace_transport_t *tp, const void *data, size_t size, uint32_t tmo) +{ + // Write data to your transport + return ESP_OK; +} + +static esp_err_t my_transport_flush(esp_trace_transport_t *tp, uint32_t tmo) +{ + // Flush transport buffers + return ESP_OK; +} + +// Create the vtable with your functions +static const esp_trace_transport_vtable_t s_my_transport_vt = { + .init = my_transport_init, + .write = my_transport_write, + .flush = my_transport_flush, + // Add other required function pointers as needed +}; + +// Register the transport adapter +ESP_TRACE_REGISTER_TRANSPORT("my_transport", &s_my_transport_vt); +``` + +See `components/esp_trace/adapters/transport/adapter_transport_apptrace.c` for a complete reference implementation. + +### Creating an Encoder Adapter + +Encoder adapters handle trace data formatting and encoding for specific trace libraries. + +**Example: Creating a custom encoder adapter** + +```c +#include "esp_trace_registry.h" +#include "esp_trace_port_encoder.h" + +static esp_err_t my_encoder_init(esp_trace_encoder_t *enc, const void *cfg) +{ + // Initialize your encoder + // Configure transport if needed: + // enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE, &value); + return ESP_OK; +} + +static esp_err_t my_encoder_print_event(esp_trace_encoder_t *enc, + const char *event_name, + const char *formatted_str) +{ + // Format and send trace event + return ESP_OK; +} + +static esp_err_t my_encoder_flush(esp_trace_encoder_t *enc, uint32_t tmo) +{ + // Flush encoder buffers + return ESP_OK; +} + +// Create the vtable with your functions +static const esp_trace_encoder_vtable_t s_my_encoder_vt = { + .init = my_encoder_init, + .print_event = my_encoder_print_event, + .flush = my_encoder_flush, + // Add other required function pointers as needed +}; + +// Register the encoder adapter +ESP_TRACE_REGISTER_ENCODER("my_encoder", &s_my_encoder_vt); +``` + +**Key Points:** +- Use `ESP_TRACE_REGISTER_ENCODER(name, vtable)` to register your encoder +- Use `ESP_TRACE_REGISTER_TRANSPORT(name, vtable)` if you're implementing a custom transport +- Registration happens automatically at link time (no manual initialization needed) + +See `components/esp_trace/adapters/encoder/adapter_encoder_sysview.c` for a complete reference implementation. + +### FreeRTOS Trace Integration + +If your external trace library needs to capture FreeRTOS events, you must provide an `esp_trace_freertos_impl.h` header in your component's include directory. This header should define FreeRTOS trace macros (like `traceTASK_SWITCHED_IN()`, `traceISR_ENTER()`, etc.) that will be called by FreeRTOS. + +The `esp_trace` component includes this header when `CONFIG_ESP_TRACE_LIB_EXTERNAL=y` is set: + +```c +// In esp_trace_freertos.h +#if CONFIG_ESP_TRACE_LIB_EXTERNAL +#include "esp_trace_freertos_impl.h" +#endif +``` + +**Example esp_trace_freertos_impl.h:** +```c +#pragma once + +#include "your_trace_library.h" + +#define traceTASK_SWITCHED_IN() your_lib_task_switched_in(xTaskGetCurrentTaskHandle()) +#define traceISR_ENTER(irq_num) your_lib_isr_enter(irq_num) +#define traceISR_EXIT() your_lib_isr_exit() +// ... define other FreeRTOS trace macros as needed +``` + +### Component CMakeLists.txt Setup + +For external adapters to work properly, your component's CMakeLists.txt needs two important settings: + +**Example CMakeLists.txt:** +```cmake +idf_component_register( + SRCS "src/adapter_encoder_ctf.c" + INCLUDE_DIRS "include" + REQUIRES esp_trace + WHOLE_ARCHIVE TRUE # Important: ensures adapter registration is linked +) + +# Auto-register this component with esp_trace +# This allows esp_trace to find your esp_trace_freertos_impl.h +idf_component_get_property(esp_trace_lib esp_trace COMPONENT_LIB) +target_link_libraries(${esp_trace_lib} INTERFACE $) +``` + +**Important:** +- `WHOLE_ARCHIVE TRUE` ensures your adapter registration code is linked +- The `target_link_libraries` trick makes your headers visible to esp_trace component + +### Using an External Adapter + +1. **Add the component to your project dependencies** in your main component's `CMakeLists.txt`: + ```cmake + idf_component_register( + SRCS "main.c" + INCLUDE_DIRS "." + REQUIRES my_trace_component esp_trace + ) + ``` + +2. **Configure trace settings** in your project's `sdkconfig.defaults`: + ```ini + # Enable esp_trace + CONFIG_ESP_TRACE_ENABLE=y + + # Use external trace library + CONFIG_ESP_TRACE_LIB_EXTERNAL=y + + # Select transport (e.g., apptrace over UART) + CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y + CONFIG_APPTRACE_DEST_UART=y + CONFIG_APPTRACE_DEST_UART_NUM=0 + ``` + +3. **Build and run** - The adapter will be automatically registered and used when the component is linked. + +**Note:** External trace libraries should use `CONFIG_ESP_TRACE_LIB_EXTERNAL=y` instead of defining their own Kconfig option in the esp_trace menu. This keeps the external component independent from the esp_trace component. + +## Documentation + +For detailed usage instructions, see: +- [Application Tracing Guide](../../docs/en/api-guides/app_trace.rst) +- [Migration Guide](../../docs/en/migration-guides/release-6.x/6.0/system.rst) + +## Examples + +Examples demonstrating trace usage can be found in: +- `examples/system/app_trace_basic/` - Basic application tracing +- `examples/system/sysview_tracing/` - SystemView tracing example diff --git a/components/esp_trace/adapters/encoder/adapter_encoder_sysview.c b/components/esp_trace/adapters/encoder/adapter_encoder_sysview.c new file mode 100644 index 0000000000..6061c4110d --- /dev/null +++ b/components/esp_trace/adapters/encoder/adapter_encoder_sysview.c @@ -0,0 +1,148 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +#include "esp_err.h" +#include "esp_heap_caps.h" +#include "esp_trace_types.h" +#include "esp_trace_registry.h" +#include "esp_trace_port_encoder.h" +#include "esp_trace_port_transport.h" +#include "adapters/adapter_encoder_sysview.h" +#include "esp_trace_util.h" +#include "esp_sysview_trace.h" +#include "SEGGER_SYSVIEW.h" +#include "SEGGER_RTT.h" + +/* + * This adapter is used to create a public system-wide APIs for SystemView. + * All encoding and transport operations are done by SystemView component. (SEGGER_RTT_esp.c) + */ + +#define SYSVIEW_FLUSH_TMO_US (1000 * 1000) /* 1second */ +#define SYSVIEW_FLUSH_THRESH 0 + +/** + * @brief Initializes sysview encoder. + * This function is called for each core. + * Adapter implementations do NOT need their own multi-core protection. Core does it for them. + * + * @param enc Pointer to the encoder structure. Must not be NULL. + * @param enc_cfg Pointer to the encoder configuration. Can be NULL for defaults. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t init(esp_trace_encoder_t *enc, const void *enc_cfg) +{ + static bool initialized = false; + + if (!enc) { + return ESP_ERR_INVALID_ARG; + } + + if (initialized) { + return ESP_OK; + } + + const esp_trace_sysview_config_t *cfg = enc_cfg; + int dest_cpu = 0; // Default to CPU0 + + if (cfg) { + dest_cpu = cfg->dest_cpu; + } + + // Allocate and initialize encoder context + sysview_encoder_ctx_t *ctx = heap_caps_calloc(1, sizeof(*ctx), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (!ctx) { + return ESP_ERR_NO_MEM; + } + + /* Segger Sysview needs locking mechanism. */ + esp_trace_lock_init(&ctx->lock); + ctx->dest_cpu = dest_cpu; + enc->ctx = ctx; + + if (SEGGER_RTT_ESP_SetEncoder(enc) != 0) { + heap_caps_free(ctx); + enc->ctx = NULL; + return ESP_ERR_NOT_SUPPORTED; + } + + /* Configure transport for SystemView requirements */ + if (enc->tp->vt->set_config) { + uint32_t flush_tmo = SYSVIEW_FLUSH_TMO_US; + uint32_t flush_thresh = SYSVIEW_FLUSH_THRESH; + uint32_t header_size = 2; /* SystemView uses 2-byte (16-bit) trace headers */ + enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO, &flush_tmo); + enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH, &flush_thresh); + enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE, &header_size); + } + + SEGGER_SYSVIEW_Conf(); + + initialized = true; + + return ESP_OK; +} + +/** + * @brief Panic handler + * + * Called during system panic to finalize encoder state. + * + * @param enc Pointer to the encoder structure. Must not be NULL. + * @param info Panic information + */ +static void panic_handler(esp_trace_encoder_t *enc, const void *info) +{ + (void)enc; + (void)info; + + SEGGER_RTT_ESP_Flush(); +} + +/** + * @brief Takes the lock of sysview encoder. + * + * @param enc Pointer to the encoder structure. Must not be NULL. + * @param tmo Timeout for the operation (in us). + */ +static unsigned int take_lock(esp_trace_encoder_t *enc, uint32_t tmo_us) +{ + sysview_encoder_ctx_t *ctx = enc->ctx; + esp_trace_lock_take(&ctx->lock, tmo_us); + + return ctx->lock.int_state; +} + +/** + * @brief Gives the lock of sysview encoder. + * + * @param enc Pointer to the encoder structure. Must not be NULL. + * @param int_state The interrupt state. + */ +static void give_lock(esp_trace_encoder_t *enc, unsigned int_state) +{ + sysview_encoder_ctx_t *ctx = enc->ctx; + + // Restore interrupt state before releasing lock + ctx->lock.int_state = int_state; + esp_trace_lock_give(&ctx->lock); +} + +/** + * @brief Sysview encoder vtable. + */ +static const esp_trace_encoder_vtable_t s_sysview_vt = { + .init = init, + .panic_handler = panic_handler, + .take_lock = take_lock, + .give_lock = give_lock, +}; + +ESP_TRACE_REGISTER_ENCODER("sysview", &s_sysview_vt); diff --git a/components/esp_trace/adapters/transport/adapter_transport_apptrace.c b/components/esp_trace/adapters/transport/adapter_transport_apptrace.c new file mode 100644 index 0000000000..c7ecda0af7 --- /dev/null +++ b/components/esp_trace/adapters/transport/adapter_transport_apptrace.c @@ -0,0 +1,268 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_err.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "esp_trace_registry.h" +#include "esp_trace_port_transport.h" +#include "esp_trace_types.h" +#include "esp_app_trace.h" + +static const char *TAG = "adapter_transport_apptrace"; + +typedef struct { + uint32_t flush_tmo; + uint32_t flush_thresh; +} apptrace_ctx_t; + +/** + * @brief Initializes apptrace transport. + * This function is called for each core at system init time. + * Allocated context will not be freed and kept alive until the end of the program. + * Adapter implementations do NOT need their own multi-core protection. Core does it for them. + * + * @param tp Pointer to the transport structure. Must not be NULL. + * @param tp_cfg Pointer to the transport configuration. NULL means use default configuration. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t apptrace_init(esp_trace_transport_t *tp, const void *tp_cfg) +{ + if (!tp) { + return ESP_ERR_INVALID_ARG; + } + + /* Create context if not already done */ + if (!tp->ctx) { + apptrace_ctx_t *ctx = heap_caps_calloc(1, sizeof(*ctx), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (!ctx) { + return ESP_ERR_NO_MEM; + } + tp->ctx = ctx; + } + + const esp_apptrace_config_t *cfg = (esp_apptrace_config_t *)tp_cfg; + esp_apptrace_config_t default_cfg = APPTRACE_CONFIG_DEFAULT(); + + if (!cfg) { + cfg = &default_cfg; + } + + /* Initialize context */ + apptrace_ctx_t *ctx = (apptrace_ctx_t *)tp->ctx; + ctx->flush_tmo = cfg->flush_tmo; + ctx->flush_thresh = cfg->flush_thresh; + + // Initialize underlying apptrace + esp_err_t err = esp_apptrace_init(cfg); + if (err != ESP_OK) { + heap_caps_free(ctx); + tp->ctx = NULL; + return err; + } + + return ESP_OK; +} + +/** + * @brief Reads data from apptrace transport. + * + * @param tp Pointer to the transport structure. Ignored. + * @param data Pointer to the data buffer. + * @param size Pointer to the size of the data buffer. + * @param tmo Timeout for the operation (in us). + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t apptrace_read(esp_trace_transport_t *tp, void *data, size_t *size, uint32_t tmo) +{ + (void)tp; + return esp_apptrace_read(data, (uint32_t *)size, tmo); +} + +/** + * @brief Writes data to apptrace transport. + * + * @param tp Pointer to the transport structure. Ignored. + * @param data Pointer to the data buffer. + * @param size Size of the data buffer. + * @param tmo Timeout for the operation (in us). + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t apptrace_write(esp_trace_transport_t *tp, const void *data, size_t size, uint32_t tmo) +{ + (void)tp; + return esp_apptrace_write(data, (uint32_t)size, tmo); +} + +/** + * @brief Configures down buffer for apptrace transport. + * + * @param tp Pointer to the transport structure. Ignored. + * @param buf Pointer to the data buffer. + * @param size Size of the data buffer. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t apptrace_down_buffer_config(esp_trace_transport_t *tp, uint8_t *buf, uint32_t size) +{ + (void)tp; + return esp_apptrace_down_buffer_config(buf, size); +} + +/** + * @brief Flushes data from apptrace transport without locking. + * + * Uses the panic configuration stored during initialization. + * + * @param tp Pointer to the transport structure. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t apptrace_flush_nolock(esp_trace_transport_t *tp) +{ + apptrace_ctx_t *ctx = (apptrace_ctx_t *)tp->ctx; + if (!ctx) { + return ESP_ERR_INVALID_STATE; + } + return esp_apptrace_flush_nolock(ctx->flush_thresh, ctx->flush_tmo); +} + +/** + * @brief Checks if the host is connected to apptrace transport. + * + * @param tp Pointer to the transport structure. Ignored. + * + * @return True if the host is connected, otherwise false. + */ +static bool apptrace_is_host_connected(esp_trace_transport_t *tp) +{ + (void)tp; + return esp_apptrace_host_is_connected(); +} + +/** + * @brief Gets the link type of apptrace transport. + * + * @param tp Pointer to the transport structure. Ignored. + * + * @return The link type of apptrace transport. + */ +static esp_trace_link_types_t apptrace_get_link_type(esp_trace_transport_t *tp) +{ + (void)tp; + + switch (esp_apptrace_get_destination()) { + case ESP_APPTRACE_DEST_JTAG: + return ESP_TRACE_LINK_DEBUG_PROBE; + case ESP_APPTRACE_DEST_UART: + return ESP_TRACE_LINK_UART; + default: + return ESP_TRACE_LINK_UNKNOWN; + } +} + +/** + * @brief Sets configuration for apptrace transport. + * + * @param tp Pointer to the transport structure. Must not be NULL. + * @param key The key of the configuration. + * @param value The value of the configuration. + */ +static esp_err_t apptrace_set_config(esp_trace_transport_t *tp, esp_trace_transport_cfg_key_t key, const void *value) +{ + if (!value) { + return ESP_ERR_INVALID_ARG; + } + + apptrace_ctx_t *ctx = (apptrace_ctx_t *)tp->ctx; + if (!ctx) { + return ESP_ERR_INVALID_STATE; + } + + switch (key) { + case ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE: { + esp_apptrace_header_size_t header_size = *(const esp_apptrace_header_size_t *)value; + return esp_apptrace_set_header_size(header_size); + } + case ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO: + ctx->flush_tmo = *(const uint32_t *)value; + return ESP_OK; + case ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH: + ctx->flush_thresh = *(const uint32_t *)value; + return ESP_OK; + default: + ESP_EARLY_LOGE(TAG, "Key %d is not supported", key); + return ESP_ERR_NOT_SUPPORTED; + } +} + +/** + * @brief Gets configuration from apptrace transport. + * + * @param tp Pointer to the transport structure. Must not be NULL. + * @param key Configuration key. + * @param value Pointer to store the configuration value. + * @return ESP_OK on success, ESP_ERR_INVALID_ARG if parameters are invalid, + * ESP_ERR_NOT_SUPPORTED if key is not supported. + */ +static esp_err_t apptrace_get_config(esp_trace_transport_t *tp, esp_trace_transport_cfg_key_t key, void *value) +{ + apptrace_ctx_t *ctx = (apptrace_ctx_t *)tp->ctx; + + if (!value) { + return ESP_ERR_INVALID_ARG; + } + + switch (key) { + case ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO: + *(uint32_t *)value = ctx->flush_tmo; + return ESP_OK; + case ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH: + *(uint32_t *)value = ctx->flush_thresh; + return ESP_OK; + default: + ESP_EARLY_LOGE(TAG, "Key %d is not supported", key); + return ESP_ERR_NOT_SUPPORTED; + } +} + +void apptrace_panic_handler(esp_trace_transport_t *tp, const void *info) +{ + (void)info; + + apptrace_ctx_t *ctx = (apptrace_ctx_t *)tp->ctx; + if (!ctx) { + return; + } + + esp_apptrace_flush_nolock(ctx->flush_thresh, ctx->flush_tmo); +} + +/** + * @brief Apptrace transport vtable. + */ +static const esp_trace_transport_vtable_t s_apptrace_vt = { + .init = apptrace_init, + .set_config = apptrace_set_config, + .get_config = apptrace_get_config, + .read = apptrace_read, + .write = apptrace_write, + .flush_nolock = apptrace_flush_nolock, + .down_buffer_config = apptrace_down_buffer_config, + .is_host_connected = apptrace_is_host_connected, + .get_link_type = apptrace_get_link_type, + .panic_handler = apptrace_panic_handler, +}; + +ESP_TRACE_REGISTER_TRANSPORT("apptrace", &s_apptrace_vt); diff --git a/components/esp_trace/include/adapters/adapter_encoder_sysview.h b/components/esp_trace/include/adapters/adapter_encoder_sysview.h new file mode 100644 index 0000000000..cd367324cc --- /dev/null +++ b/components/esp_trace/include/adapters/adapter_encoder_sysview.h @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "esp_trace_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief SystemView encoder configuration + */ +typedef struct { + /** + * @brief CPU to trace (0 or 1) + * + * Determines which CPU's events are captured by SystemView. + * Only relevant when using UART apptrace transport. + * + * - 0: Capture events from CPU0 (Pro CPU) + * - 1: Capture events from CPU1 (App CPU) + * + * @note This parameter is ignored for single-core systems + * @note This parameter is ignored when using JTAG transport + */ + int dest_cpu; +} esp_trace_sysview_config_t; + +/** + * @brief SystemView encoder context structure + * + * This structure is shared between the sysview adapter and the SEGGER RTT layer + * to allow proper access to encoder-specific configuration. + */ +typedef struct { + int dest_cpu; ///< CPU to trace (0 or 1) + esp_trace_lock_t lock; ///< Encoder lock +} sysview_encoder_ctx_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace.h b/components/esp_trace/include/esp_trace.h new file mode 100644 index 0000000000..bbc96fa646 --- /dev/null +++ b/components/esp_trace/include/esp_trace.h @@ -0,0 +1,140 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#include "esp_trace_types.h" + +/** + * @brief Trace session handle + * + * Opaque handle representing an active trace session. + */ +typedef struct esp_trace_handle *esp_trace_handle_t; + +/** + * @brief Parameters for opening a trace session + * + * This structure configures all aspects of a trace session, including the core behavior, + * encoder (trace library), and transport (communication channel). + */ +typedef struct { + /** + * @brief Core trace system configuration (optional) + * + * Currently reserved for future use. + */ + const esp_trace_config_t *core_cfg; + + /** + * @brief Encoder name (required) + * + * Must match a registered encoder name. Built-in encoders: + * - "sysview" - SEGGER SystemView protocol for FreeRTOS tracing + * - "raw" - Pass-through for raw binary data + */ + const char *encoder_name; + + /** + * @brief Encoder-specific configuration (optional) + * + * If NULL, encoder uses its default configuration. The structure type + * depends on the encoder being used. See encoder-specific documentation. + */ + const void *encoder_cfg; + + /** + * @brief Transport name (required) + * + * Must match a registered transport name. Built-in transports: + * - "apptrace" - Uses app_trace for JTAG or UART communication + * + */ + const char *transport_name; + + /** + * @brief Transport-specific configuration (optional) + * + * If NULL, transport uses its default configuration. The structure type + * depends on the transport being used: + * - For "apptrace": `esp_apptrace_config_t*` + * + * See transport-specific documentation for details. + */ + const void *transport_cfg; +} esp_trace_open_params_t; + +/** + * @brief Get trace initialization parameters for early system initialization + * + * User applications need to implement this function to provide a custom trace configuration. + * This function is called during system initialization before any other trace functions are called. + * + * @return Configuration + */ +esp_trace_open_params_t esp_trace_get_user_params(void); + +/** + * @brief Get the active trace handle + * + * @return The active trace handle + */ +esp_trace_handle_t esp_trace_get_active_handle(void); + +/** + * @brief Write data to the trace handle + * + * @param handle The trace handle + * @param data The data to write + * @param size The size of the data + * @param tmo The timeout in us + * + * @return ESP_OK on success, otherwise see esp_err_t + */ +esp_err_t esp_trace_write(esp_trace_handle_t handle, const void *data, size_t size, unsigned long tmo); + +/** + * @brief Flush the trace handle + * + * @param handle The trace handle + * @param tmo The timeout in us + * + * @return ESP_OK on success, otherwise see esp_err_t + */ +esp_err_t esp_trace_flush(esp_trace_handle_t handle, unsigned long tmo); + +/** + * @brief Check if the host is connected + * + * @param handle The trace handle + * + * @return true if the host is connected, otherwise false + */ +bool esp_trace_is_host_connected(esp_trace_handle_t handle); + +/** + * @brief Get the link type + * + * @param handle The trace handle + * + * @return The link type @see esp_trace_link_types_t + */ +esp_trace_link_types_t esp_trace_get_link_type(esp_trace_handle_t handle); + +/** + * @brief Panic flush the trace handle. This function is called from panic handler. + * + * @param handle The trace handle + */ +void esp_trace_panic_handler(const void *info); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace_freertos.h b/components/esp_trace/include/esp_trace_freertos.h new file mode 100644 index 0000000000..fc8d75c89d --- /dev/null +++ b/components/esp_trace/include/esp_trace_freertos.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +/** + * @brief FreeRTOS trace macros dispatcher + * + * This header provides a unified interface for FreeRTOS tracing. + * It dispatches to the appropriate implementation based on configuration: + * + * - CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW: Uses SEGGER SystemView + * - CONFIG_ESP_TRACE_LIB_EXTERNAL: Uses external component's implementation + * (external component must provide esp_trace_freertos_impl.h see components/esp_trace/README.md for more details) + */ + +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +#include "SEGGER_SYSVIEW_FreeRTOS.h" +#undef INLINE /* to avoid redefinition */ +#elif CONFIG_ESP_TRACE_LIB_EXTERNAL +#include "esp_trace_freertos_impl.h" +#endif diff --git a/components/esp_trace/include/esp_trace_port_encoder.h b/components/esp_trace/include/esp_trace_port_encoder.h new file mode 100644 index 0000000000..2aa7bd8b9f --- /dev/null +++ b/components/esp_trace/include/esp_trace_port_encoder.h @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "esp_err.h" +#include "esp_trace_types.h" + +/* forward declarations */ +typedef struct esp_trace_encoder esp_trace_encoder_t; +typedef struct esp_trace_transport esp_trace_transport_t; + +/** + * @brief Encoder Virtual Table + * + * Defines the interface for trace encoders (libraries) + */ +typedef struct { + /** + * @brief Initialize encoder + * @param enc Encoder instance + * @param enc_cfg Encoder-specific configuration + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*init)(esp_trace_encoder_t *enc, const void *enc_cfg); + + /** + * @brief Write trace data + * @param enc Encoder instance + * @param data Data buffer to write + * @param size Size of data in bytes + * @param tmo Timeout in microseconds + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*write)(esp_trace_encoder_t *enc, const void *data, size_t size, uint32_t tmo); + + /** + * @brief Panic handler + * @param enc Encoder instance + * @param info Panic information + */ + void (*panic_handler)(esp_trace_encoder_t *enc, const void *info); + + /** + * @brief Take encoder lock + * @param enc Encoder instance + * @param tmo Timeout in microseconds + * @return Lock state (for recursive locking) or 0 on failure + */ + unsigned int (*take_lock)(esp_trace_encoder_t *enc, uint32_t tmo_us); + + /** + * @brief Give encoder lock + * @param enc Encoder instance + * @param int_state The interrupt state + */ + void (*give_lock)(esp_trace_encoder_t *enc, unsigned int_state); + +} esp_trace_encoder_vtable_t; + +/** + * @brief Encoder structure, represents an active trace library instance. + */ +struct esp_trace_encoder { + const esp_trace_encoder_vtable_t *vt; ///< Pointer to encoder vtable + esp_trace_transport_t *tp; ///< Pointer to transport instance + void *ctx; ///< Encoder specific context +}; + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace_port_transport.h b/components/esp_trace/include/esp_trace_port_transport.h new file mode 100644 index 0000000000..39d435e924 --- /dev/null +++ b/components/esp_trace/include/esp_trace_port_transport.h @@ -0,0 +1,137 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "esp_err.h" +#include "esp_trace_types.h" // esp_trace_link_types_t + +/* forward declarations */ +typedef struct esp_trace_transport esp_trace_transport_t; + +/** + * @brief Transport configuration keys + * + * Standard configuration keys that encoders can use to configure transport behavior. + */ +typedef enum { + ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE, ///< (uint32_t*) Trace header size in bytes + ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO, ///< (uint32_t*) Flush timeout in microseconds + ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH, ///< (uint32_t*) Flush threshold in bytes +} esp_trace_transport_cfg_key_t; + +/** + * @brief Transport Virtual Table + * + * Defines the interface for trace transports. + * + */ +typedef struct { + /** + * @brief Initialize transport + * @param tp Transport instance + * @param tp_cfg Transport-specific configuration + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*init)(esp_trace_transport_t *tp, const void *tp_cfg); + + /** + * @brief Set transport configuration + * @param tp Transport instance + * @param key Configuration key + * @param value Configuration value + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*set_config)(esp_trace_transport_t *tp, esp_trace_transport_cfg_key_t key, const void *value); + + /** + * @brief Get transport configuration + * @param tp Transport instance + * @param key Configuration key + * @param value Pointer to store configuration value + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*get_config)(esp_trace_transport_t *tp, esp_trace_transport_cfg_key_t key, void *value); + + /** + * @brief Read trace data + * @param tp Transport instance + * @param data Buffer to read data into + * @param size Pointer to size (in: buffer size, out: bytes read) + * @param tmo Timeout in microseconds + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*read)(esp_trace_transport_t *tp, void *data, size_t *size, uint32_t tmo); + + /** + * @brief Write trace data + * @param tp Transport instance + * @param data Data buffer to write + * @param size Size of data in bytes + * @param tmo Timeout in microseconds + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*write)(esp_trace_transport_t *tp, const void *data, size_t size, uint32_t tmo); + + /** + * @brief Flush without lock + * + * The transport should use its internally stored flush configuration (timeout, threshold) that was + * set during initialization. + * + * @param tp Transport instance + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*flush_nolock)(esp_trace_transport_t *tp); + + /** + * @brief Configure down buffer + * @param tp Transport instance + * @param buf Buffer pointer + * @param size Buffer size in bytes + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*down_buffer_config)(esp_trace_transport_t *tp, uint8_t *buf, uint32_t size); + + /** + * @brief Check if host is connected + * @param tp Transport instance + * @return true if host is connected, false otherwise + */ + bool (*is_host_connected)(esp_trace_transport_t *tp); + + /** + * @brief Get link type @see esp_trace_link_types_t + * @param tp Transport instance + * @return Link type + */ + esp_trace_link_types_t (*get_link_type)(esp_trace_transport_t *tp); + + /** + * @brief Panic handler + * @param tp Transport instance + * @param info Panic information + */ + void (*panic_handler)(esp_trace_transport_t *tp, const void *info); +} esp_trace_transport_vtable_t; + +/** + * @brief Transport structure representing an active transport instance. + */ +struct esp_trace_transport { + const esp_trace_transport_vtable_t *vt; ///< Pointer to transport vtable + void *ctx; ///< Transport-specific context +}; + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace_registry.h b/components/esp_trace/include/esp_trace_registry.h new file mode 100644 index 0000000000..d1ae8fa286 --- /dev/null +++ b/components/esp_trace/include/esp_trace_registry.h @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#include "esp_trace_port_encoder.h" +#include "esp_trace_port_transport.h" + +typedef struct { + const char *name; ///< Encoder name for lookup (e.g., "sysview") + const esp_trace_encoder_vtable_t *vtable; ///< Pointer to function table +} esp_trace_encoder_desc_t; + +typedef struct { + const char *name; ///< Transport name for lookup (e.g., "apptrace") + const esp_trace_transport_vtable_t *vtable; ///< Pointer to function table +} esp_trace_transport_desc_t; + +#define ESP_TRACE_SECTION(name) __attribute__((used, section(name))) + +/** + * @brief Register an encoder at compile time + * + * Place this macro in your encoder implementation file after defining the vtable. + * The encoder will be automatically discovered by the trace system at runtime. + * + * @note This creates a static descriptor in the .esp_trace_encoder_desc section + * @note The linker collects all descriptors and creates esp_trace_encoder_array + * @note Only use once per file (one encoder per implementation file) + * + * @param name_str Encoder name string (e.g., "sysview") + * @param vt_ptr Pointer to the encoder vtable structure + * + */ +#define ESP_TRACE_REGISTER_ENCODER(name_str, vt_ptr) \ + static const esp_trace_encoder_desc_t _esp_trace_encoder_desc \ + ESP_TRACE_SECTION(".esp_trace_encoder_desc") = { (name_str), (vt_ptr) } + +/** + * @brief Register a transport at compile time + * + * Place this macro in your transport implementation file after defining the vtable. + * The transport will be automatically discovered by the trace system at runtime. + * + * @note This creates a static descriptor in the .esp_trace_transport_desc section + * @note The linker collects all descriptors and creates esp_trace_transport_array + * @note Only use once per file (one transport per implementation file) + * + * @param name_str Transport name string (e.g., "apptrace") + * @param vt_ptr Pointer to the transport vtable structure + * + */ +#define ESP_TRACE_REGISTER_TRANSPORT(name_str, vt_ptr) \ + static const esp_trace_transport_desc_t _esp_trace_transport_desc \ + ESP_TRACE_SECTION(".esp_trace_transport_desc") = { (name_str), (vt_ptr) } + +/* Lookup functions */ +const esp_trace_encoder_vtable_t *esp_trace_find_encoder(const char *name); +const esp_trace_transport_vtable_t *esp_trace_find_transport(const char *name); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace_types.h b/components/esp_trace/include/esp_trace_types.h new file mode 100644 index 0000000000..5b1efae25a --- /dev/null +++ b/components/esp_trace/include/esp_trace_types.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct esp_trace_config { + // Reserved for future use + int reserved; +} esp_trace_config_t; + +typedef enum { + ESP_TRACE_LINK_UNKNOWN = 0, + ESP_TRACE_LINK_DEBUG_PROBE, + ESP_TRACE_LINK_UART, +} esp_trace_link_types_t; + +/* Timeout constants for trace operations */ +#define ESP_TRACE_TMO_INFINITE (UINT32_MAX) + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace_util.h b/components/esp_trace/include/esp_trace_util.h new file mode 100644 index 0000000000..a2c158b6c8 --- /dev/null +++ b/components/esp_trace/include/esp_trace_util.h @@ -0,0 +1,123 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "esp_err.h" + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// TIMESTAMP /////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Initialize the trace timestamp source. + * + * This function initializes the trace timestamp source based on the configured + * source. The timestamp source can be the CPU cycle counter, esp_timer, or + * Timer Group, depending on configuration. + * + * @return The timestamp frequency in Hz. + */ +uint32_t esp_trace_timestamp_init(void); + +/** + * @brief Get the current timestamp value from the configured source for ESP trace. + * + * This function returns the current timestamp value, which can be sourced from + * the CPU cycle counter, esp_timer, or Timer Group, depending on configuration. + * + * @return The current timestamp value as a 32-bit unsigned integer. + */ +uint32_t esp_trace_timestamp_get(void); + +/** + * @brief Get the current CPU frequency in Hz. + * + * This function returns the current CPU frequency as reported by esp_clk_cpu_freq(). + * + * @return The CPU frequency in Hz. + */ +uint32_t esp_trace_cpu_freq_get(void); + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// TIMEOUT ///////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Timeout structure for trace operations + * + * This structure holds data necessary for measuring time intervals. + * After initialization via esp_trace_tmo_init(), user needs to call esp_trace_tmo_check() + * periodically to check timeout for expiration. + */ +typedef struct { + int64_t start; ///< Time interval start (in us) + int64_t tmo; ///< Timeout value (in us) + int64_t elapsed; ///< Elapsed time (in us) +} esp_trace_tmo_t; + +/** + * @brief Initialize timeout structure + * + * @param tmo Pointer to timeout structure to be initialized + * @param user_tmo Timeout value (in us). Use ESP_TRACE_TMO_INFINITE to wait indefinitely + */ +void esp_trace_tmo_init(esp_trace_tmo_t *tmo, uint32_t user_tmo); + +/** + * @brief Check timeout for expiration + * + * @param tmo Pointer to timeout structure + * @return ESP_OK if not expired, ESP_ERR_TIMEOUT if expired + */ +esp_err_t esp_trace_tmo_check(esp_trace_tmo_t *tmo); + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// LOCKS /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +#include "spinlock.h" + +/** + * @brief Trace component lock structure + * + * Similar to esp_apptrace_lock_t but for trace component locking. + * This structure provides spinlock-based synchronization for trace components + * (encoders, transports, and other trace components). + */ +typedef struct { + spinlock_t mux; ///< Spinlock for synchronization + unsigned int int_state; ///< Interrupt state for recursive locking +} esp_trace_lock_t; + +/** + * @brief Initialize trace component lock + * @param lock Pointer to lock structure to be initialized + */ +void esp_trace_lock_init(esp_trace_lock_t *lock); + +/** + * @brief Take trace component lock + * @param lock Pointer to lock structure + * @param tmo Timeout in microseconds + * @return ESP_OK on success, ESP_ERR_TIMEOUT on timeout + */ +esp_err_t esp_trace_lock_take(esp_trace_lock_t *lock, uint32_t tmo_us); + +/** + * @brief Give trace component lock + * @param lock Pointer to lock structure + * @return ESP_OK on success + */ +esp_err_t esp_trace_lock_give(esp_trace_lock_t *lock); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/linker.lf b/components/esp_trace/linker.lf new file mode 100644 index 0000000000..ba230f2034 --- /dev/null +++ b/components/esp_trace/linker.lf @@ -0,0 +1,50 @@ +# ESP Trace Component Linker Fragment +[mapping:esp_trace] +archive: libesp_trace.a +entries: + if ESP_TRACE_ENABLE = y: + esp_trace_core (noflash) + esp_trace_registry (noflash) + port_utils (noflash) + if ESP_TRACE_LIB_SEGGER_SYSVIEW: + adapter_encoder_sysview (noflash) + if ESP_TRACE_TRANSPORT_APPTRACE: + adapter_transport_apptrace (noflash) + +[mapping:esp_trace_driver] +archive: libesp_driver_gptimer.a +entries: + if ESP_TRACE_TS_SOURCE_GPTIMER = y: + gptimer: gptimer_get_raw_count (noflash) + else: + * (default) + +# Static registration of encoders and transports at link time + +[sections:esp_trace_encoder_desc] +entries: + .esp_trace_encoder_desc + +[sections:esp_trace_transport_desc] +entries: + .esp_trace_transport_desc + +[scheme:esp_trace_encoder_desc_default] +entries: + esp_trace_encoder_desc -> flash_rodata + +[scheme:esp_trace_transport_desc_default] +entries: + esp_trace_transport_desc -> flash_rodata + +[mapping:esp_trace_encoder_desc] +archive: * +entries: + * (esp_trace_encoder_desc_default); + esp_trace_encoder_desc -> flash_rodata KEEP() SORT(name) SURROUND(esp_trace_encoder_array) + +[mapping:esp_trace_transport_desc] +archive: * +entries: + * (esp_trace_transport_desc_default); + esp_trace_transport_desc -> flash_rodata KEEP() SORT(name) SURROUND(esp_trace_transport_array) diff --git a/components/esp_trace/src/core/esp_trace_core.c b/components/esp_trace/src/core/esp_trace_core.c new file mode 100644 index 0000000000..13fd193e8c --- /dev/null +++ b/components/esp_trace/src/core/esp_trace_core.c @@ -0,0 +1,207 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * ESP Trace Core - Central trace session management + * + * This module manages trace sessions, coordinating encoders (trace libraries like SystemView) + * and transports (communication channels like JTAG, UART). + * + */ + +#include +#include "esp_cpu.h" +#include "esp_log.h" +#include "esp_err.h" +#include "esp_rom_sys.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "esp_trace_registry.h" +#include "esp_trace.h" +#include "esp_trace_port_transport.h" +#include "esp_private/startup_internal.h" + +static const char *TAG = "esp_trace_core"; + +struct esp_trace_handle { + esp_trace_encoder_t encoder; + esp_trace_transport_t transport; +}; + +/** + * Singleton session management + * Only one trace session can be active at a time. + */ +static esp_trace_handle_t s_active_handle = NULL; +static portMUX_TYPE s_init_lock = portMUX_INITIALIZER_UNLOCKED; +static volatile int s_trace_handle_created = 0; + +static esp_err_t esp_trace_create(const esp_trace_open_params_t *params) +{ + if (!params || !params->encoder_name || !params->transport_name) { + return ESP_ERR_INVALID_ARG; + } + + if (s_active_handle) { + ESP_EARLY_LOGE(TAG, "Trace handle already created"); + return ESP_ERR_INVALID_STATE; + } + + const esp_trace_encoder_vtable_t *enc_vt = esp_trace_find_encoder(params->encoder_name); + const esp_trace_transport_vtable_t *tp_vt = esp_trace_find_transport(params->transport_name); + + if (!enc_vt || !tp_vt) { + ESP_EARLY_LOGE(TAG, "Encoder '%s' or transport '%s' not found", params->encoder_name, params->transport_name); + return ESP_ERR_NOT_FOUND; + } + + esp_trace_handle_t h = heap_caps_calloc(1, sizeof(*h), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (!h) { + ESP_EARLY_LOGE(TAG, "Failed to allocate trace handle"); + return ESP_ERR_NO_MEM; + } + + h->encoder.vt = enc_vt; + h->transport.vt = tp_vt; + h->encoder.tp = &h->transport; + + s_active_handle = h; + + return ESP_OK; +} + +/* This function is called during early system initialization (before app_main) on all cores */ +static esp_err_t esp_trace_init(const esp_trace_open_params_t *params) +{ + esp_err_t err = ESP_OK; + esp_trace_handle_t h = NULL; + int core_id = esp_cpu_get_core_id(); + + /* Core 0 creates the handle if it doesn't exist yet */ + if (core_id == 0) { + if (!s_trace_handle_created) { + err = esp_trace_create(params); + if (err != ESP_OK) { + return err; + } + s_trace_handle_created = 1; + } + } else { + // There is NO guarantee that system init functions will execute on core 0 first + // So we need to wait for core 0 to create the handle + while (!s_trace_handle_created) { + esp_rom_delay_us(10); + } + } + + /* Handle is guaranteed to be created by now */ + h = s_active_handle; + + portENTER_CRITICAL(&s_init_lock); + + /* Setup transport first (encoder depends on it) */ + if (h->transport.vt->init) { + err = h->transport.vt->init(&h->transport, params->transport_cfg); + if (err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Transport open failed: %d", err); + goto cleanup; + } + } + + /* Setup encoder */ + if (h->encoder.vt->init) { + err = h->encoder.vt->init(&h->encoder, params->encoder_cfg); + if (err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Encoder init failed: %d", err); + goto cleanup; + } + } + + ESP_EARLY_LOGI(TAG, "Trace initialized on core %d: encoder='%s', transport='%s'", + core_id, params->encoder_name, params->transport_name); + + portEXIT_CRITICAL(&s_init_lock); + return ESP_OK; + +cleanup: + if (s_active_handle) { + /* Will not create a heap trace event. Returning error will cause an abort. */ + heap_caps_free(s_active_handle); + s_active_handle = NULL; + s_trace_handle_created = 0; + } + portEXIT_CRITICAL(&s_init_lock); + return err; +} + +esp_err_t esp_trace_write(esp_trace_handle_t h, const void *data, size_t size, unsigned long tmo) +{ + if (!h || !data || size == 0) { + return ESP_ERR_INVALID_ARG; + } + + if (!h->encoder.vt->write) { + return ESP_ERR_NOT_SUPPORTED; + } + + return h->encoder.vt->write(&h->encoder, data, size, tmo); +} + +bool esp_trace_is_host_connected(esp_trace_handle_t h) +{ + if (!h || !h->transport.vt->is_host_connected) { + return false; + } + + return h->transport.vt->is_host_connected(&h->transport); +} + +esp_trace_link_types_t esp_trace_get_link_type(esp_trace_handle_t h) +{ + if (!h || !h->transport.vt->get_link_type) { + return ESP_TRACE_LINK_UNKNOWN; + } + + return h->transport.vt->get_link_type(&h->transport); +} + +esp_trace_handle_t esp_trace_get_active_handle(void) +{ + return s_active_handle; +} + +void esp_trace_panic_handler(const void *info) +{ + esp_trace_handle_t h = s_active_handle; + if (!h) { + return; + } + if (h->encoder.vt->panic_handler) { + h->encoder.vt->panic_handler(&h->encoder, info); + } + + if (h->transport.vt->panic_handler) { + h->transport.vt->panic_handler(&h->transport, info); + } +} + +esp_trace_open_params_t __attribute__((weak)) esp_trace_get_user_params(void) +{ + esp_trace_open_params_t trace_params = { + .core_cfg = NULL, + .encoder_name = CONFIG_ESP_TRACE_LIB_NAME, + .encoder_cfg = NULL, /* Not used for now */ + .transport_name = CONFIG_ESP_TRACE_TRANSPORT_NAME, + .transport_cfg = NULL, /* Null means configure with the default parameters */ + }; + return trace_params; +} + +ESP_SYSTEM_INIT_FN(esp_trace_early_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 120) +{ + esp_trace_open_params_t trace_params = esp_trace_get_user_params(); + return esp_trace_init(&trace_params); +} diff --git a/components/esp_trace/src/core/esp_trace_registry.c b/components/esp_trace/src/core/esp_trace_registry.c new file mode 100644 index 0000000000..c2b259cac9 --- /dev/null +++ b/components/esp_trace/src/core/esp_trace_registry.c @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "esp_log.h" +#include "esp_err.h" +#include "esp_trace_registry.h" + +/** + * @file esp_trace_registry.c + * @brief Linker-time registration implementation + * + * The linker collects all ESP_TRACE_REGISTER_ENCODER() and ESP_TRACE_REGISTER_TRANSPORT() + * registrations into arrays with SURROUND symbols that mark the start and end: + * + * - _esp_trace_encoder_array_start ... _esp_trace_encoder_array_end + * - _esp_trace_transport_array_start ... _esp_trace_transport_array_end + * + * These are populated automatically by the linker script (linker.lf). + */ + +extern esp_trace_encoder_desc_t _esp_trace_encoder_array_start; +extern esp_trace_encoder_desc_t _esp_trace_encoder_array_end; +extern esp_trace_transport_desc_t _esp_trace_transport_array_start; +extern esp_trace_transport_desc_t _esp_trace_transport_array_end; + +const esp_trace_encoder_vtable_t *esp_trace_find_encoder(const char *name) +{ + if (!name) { + return NULL; + } + + for (const esp_trace_encoder_desc_t *it = &_esp_trace_encoder_array_start; + it < &_esp_trace_encoder_array_end; ++it) { + if (it->name && strcmp(it->name, name) == 0) { + return it->vtable; + } + } + + return NULL; +} + +const esp_trace_transport_vtable_t *esp_trace_find_transport(const char *name) +{ + if (!name) { + return NULL; + } + + for (const esp_trace_transport_desc_t *it = &_esp_trace_transport_array_start; + it < &_esp_trace_transport_array_end; ++it) { + if (it->name && strcmp(it->name, name) == 0) { + return it->vtable; + } + } + + return NULL; +} diff --git a/components/esp_trace/src/ports/port_utils.c b/components/esp_trace/src/ports/port_utils.c new file mode 100644 index 0000000000..30cad3d97c --- /dev/null +++ b/components/esp_trace/src/ports/port_utils.c @@ -0,0 +1,154 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "sdkconfig.h" +#include "esp_timer.h" +#include "esp_clk_tree.h" +#include "esp_cpu.h" +#include "esp_private/esp_clk.h" +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +#include "esp_trace_util.h" +#include "esp_trace_types.h" + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// TIMESTAMP /////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +// Determine which timer to use as timestamp source +#if CONFIG_ESP_TRACE_TS_SOURCE_CCOUNT +#define TS_USE_CCOUNT 1 +#elif CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER +#define TS_USE_ESP_TIMER 1 +#else +#define TS_USE_TIMERGROUP 1 +#endif + +#if TS_USE_TIMERGROUP +#include "driver/gptimer.h" + +// Timer group timer divisor +#define ESP_TRACE_TIMER_DIV 2 + +// GPTimer handle +static gptimer_handle_t s_trace_gptimer; + +#endif // TS_USE_TIMERGROUP + +#if TS_USE_ESP_TIMER +// esp_timer provides 1us resolution +#define ESP_TRACE_TIMESTAMP_FREQ (1000000) +#endif // TS_USE_ESP_TIMER + +#if TS_USE_CCOUNT +// CCOUNT is incremented at CPU frequency +#define ESP_TRACE_TIMESTAMP_FREQ (CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 1000000) +#endif // TS_USE_CCOUNT + +// System Frequency. +#define ESP_TRACE_CPU_FREQ (esp_clk_cpu_freq()) + +uint32_t esp_trace_timestamp_init(void) +{ + /* We only need to initialize something if we use Timer Group. + * esp_timer and ccount can be used as is. + */ +#if TS_USE_TIMERGROUP + // get clock source frequency + uint32_t counter_src_hz = 0; + ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)GPTIMER_CLK_SRC_DEFAULT, + ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz)); + gptimer_config_t config = { + .clk_src = GPTIMER_CLK_SRC_DEFAULT, + .direction = GPTIMER_COUNT_UP, + .resolution_hz = counter_src_hz / ESP_TRACE_TIMER_DIV, + }; + // pick any free GPTimer instance + ESP_ERROR_CHECK(gptimer_new_timer(&config, &s_trace_gptimer)); + /* Start counting */ + gptimer_enable(s_trace_gptimer); + gptimer_start(s_trace_gptimer); + return config.resolution_hz; +#else + return ESP_TRACE_TIMESTAMP_FREQ; +#endif // TS_USE_TIMERGROUP +} + +uint32_t esp_trace_timestamp_get(void) +{ +#if TS_USE_TIMERGROUP + uint64_t ts = 0; + gptimer_get_raw_count(s_trace_gptimer, &ts); + return (uint32_t)ts; // return lower part of counter value +#elif TS_USE_CCOUNT + return esp_cpu_get_cycle_count(); +#elif TS_USE_ESP_TIMER + return (uint32_t) esp_timer_get_time(); // return lower part of counter value +#endif +} + +uint32_t esp_trace_cpu_freq_get(void) +{ + return esp_clk_cpu_freq(); +} + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// TIMEOUT ///////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void esp_trace_tmo_init(esp_trace_tmo_t *tmo, uint32_t user_tmo) +{ + tmo->start = esp_timer_get_time(); + tmo->tmo = user_tmo == ESP_TRACE_TMO_INFINITE ? (int64_t) -1 : (int64_t)user_tmo; + tmo->elapsed = 0; +} + +esp_err_t esp_trace_tmo_check(esp_trace_tmo_t *tmo) +{ + if (tmo->tmo != (int64_t) -1) { + tmo->elapsed = esp_timer_get_time() - tmo->start; + if (tmo->elapsed >= tmo->tmo) { + return ESP_ERR_TIMEOUT; + } + } + return ESP_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// LOCKS /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void esp_trace_lock_init(esp_trace_lock_t *lock) +{ + portMUX_INITIALIZE(&lock->mux); + lock->int_state = 0; +} + +esp_err_t esp_trace_lock_take(esp_trace_lock_t *lock, uint32_t tmo_us) +{ + esp_trace_tmo_t tmo; + esp_trace_tmo_init(&tmo, tmo_us); + + while (1) { + // Try to enter critical section (take the spinlock) with 0 timeout + if (portTRY_ENTER_CRITICAL(&lock->mux, 0) == pdTRUE) { + return ESP_OK; + } + + // Failed to enter critical section, check timeout + if (esp_trace_tmo_check(&tmo) != ESP_OK) { + return ESP_ERR_TIMEOUT; + } + } +} + +esp_err_t esp_trace_lock_give(esp_trace_lock_t *lock) +{ + portEXIT_CRITICAL(&lock->mux); + return ESP_OK; +} diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index 9f9db5fdef..1401601f71 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -220,13 +220,8 @@ else() # linker to not drop this symbol. target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_main") - if(CONFIG_APPTRACE_SV_ENABLE) - # FreeRTOS headers have a dependency on app_trace when SystemView tracing is enabled - idf_component_optional_requires(PUBLIC app_trace) - elseif(CONFIG_APPTRACE_ENABLE) - # [refactor-todo]: app_startup.c esp_startup_start_app_other_cores() has a dependency on esp_apptrace_init() - # (called on CPU1). This should be resolved when link-time registration of startup functions is added. - idf_component_optional_requires(PRIVATE app_trace) + if(CONFIG_ESP_TRACE_ENABLE) + idf_component_optional_requires(PUBLIC esp_trace) endif() if(CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h index d66b6df762..b017c5105d 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h @@ -401,7 +401,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW extern volatile BaseType_t xPortSwitchFlag; #define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag) #else diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h index 59ae3548eb..a460e179ca 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h @@ -421,7 +421,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW extern volatile BaseType_t xPortSwitchFlag; #define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag) #else diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h index 2280f54d46..a5b7b1b914 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h @@ -740,7 +740,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW extern volatile UBaseType_t xPortSwitchFlag[portNUM_PROCESSORS]; #define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag[_cpu_]) #else diff --git a/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h index ce0b206419..b820060414 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h @@ -658,7 +658,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW extern volatile uint32_t port_switch_flag[portNUM_PROCESSORS]; #define os_task_switch_is_pended(_cpu_) (port_switch_flag[_cpu_]) #else diff --git a/components/freertos/config/include/freertos/FreeRTOSConfig.h b/components/freertos/config/include/freertos/FreeRTOSConfig.h index 8a505d5bc2..1e3db20e98 100644 --- a/components/freertos/config/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/config/include/freertos/FreeRTOSConfig.h @@ -35,7 +35,7 @@ #endif /* apptrace module increases minimum stack usage */ -#if CONFIG_APPTRACE_ENABLE +#if CONFIG_ESP_TRACE_TRANSPORT_APPTRACE #define STACK_OVERHEAD_APPTRACE 1280 #else #define STACK_OVERHEAD_APPTRACE 0 @@ -232,10 +232,9 @@ * Note: Include trace macros here and not above as trace macros are dependent on some of the FreeRTOS configs */ #ifndef __ASSEMBLER__ - #if CONFIG_SYSVIEW_ENABLE - #include "SEGGER_SYSVIEW_FreeRTOS.h" - #undef INLINE /* to avoid redefinition */ - #endif /* CONFIG_SYSVIEW_ENABLE */ + #if CONFIG_ESP_TRACE_ENABLE + #include "esp_trace_freertos.h" + #endif #if CONFIG_FREERTOS_SMP diff --git a/components/xtensa/xtensa_intr.c b/components/xtensa/xtensa_intr.c index 4d374aad50..a2f9bfc69b 100644 --- a/components/xtensa/xtensa_intr.c +++ b/components/xtensa/xtensa_intr.c @@ -156,7 +156,7 @@ xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg) return ((old == &xt_unhandled_interrupt) ? 0 : old); } -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW void * xt_get_interrupt_handler_arg(int n) { xt_handler_table_entry * entry; diff --git a/docs/en/api-guides/app_trace.rst b/docs/en/api-guides/app_trace.rst index 1733f0952e..dcc88f7410 100644 --- a/docs/en/api-guides/app_trace.rst +++ b/docs/en/api-guides/app_trace.rst @@ -41,7 +41,7 @@ Using of this feature depends on two components: 1. **Host side:** Application tracing is done over JTAG, so it needs OpenOCD to be set up and running on host machine. For instructions on how to set it up, please see :doc:`JTAG Debugging <../api-guides/jtag-debugging/index>` for details. -2. **Target side:** Application tracing functionality can be enabled in menuconfig. **Important:** You must first enable application tracing by going to ``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing`` (:ref:`CONFIG_APPTRACE_ENABLE`). After enabling this option, you can configure the destination for the trace data. For UART interfaces, users have to define port number, baud rate, TX and RX pins numbers, and additional UART-related parameters. When FreeRTOS SystemView Tracing is enabled, selected destination will be used for systemview tracing as well. +2. **Target side:** Application tracing functionality can be enabled in menuconfig. **Important:** You must first enable application tracing by going to ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` and selecting ``ESP-IDF apptrace``. After that, configuration can be done at ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing``. Here you can configure the destination for the trace data. For UART interfaces, users have to define port number, baud rate, TX and RX pins numbers, and additional UART-related parameters. When any trace library is selected (for example SEGGER SystemView), these settings will be used for the library as well. .. note:: @@ -65,7 +65,40 @@ How to Use This Library This library provides APIs for transferring arbitrary data between the host and {IDF_TARGET_NAME}. When enabled in menuconfig, the application tracing module is automatically initialized during system startup using configuration from menuconfig. Users can then call corresponding APIs to send, receive, or flush the data. -Optionally, users can override the default configuration by implementing the weak callback function :cpp:func:`esp_apptrace_get_user_params()`. +Optionally, users can override the default configuration by implementing the weak callback function :cpp:func:`esp_apptrace_get_user_params()`. This callback will be active when there is no selected trace library, meaning the Application Level Tracing library (``app_trace`` component) will be working standalone. Otherwise, :cpp:func:`esp_trace_get_user_params()` will be used for overriding the configuration. + +Quick Start Summary +------------------- + +1. Standalone usage with Application Level Tracing APIs + + In menuconfig, disable the trace library and enable the Application Level Tracing transport: + + - ``Component config`` > ``ESP Trace Configuration`` > ``Trace library``: select ``None`` + - ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport``: select ``ESP-IDF apptrace`` + + Alternatively, set these options in ``sdkconfig.defaults`` to enforce standalone mode: + + .. code-block:: none + + CONFIG_ESP_TRACE_ENABLE=y + CONFIG_ESP_TRACE_LIB_NONE=y + CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y + + Configure the destination in ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing``. + +2. Runtime configuration via ``esp_apptrace_get_user_params()`` + + - If you select ``All (runtime selection)`` in Kconfig (``APPTRACE_DEST_ALL``), the callback can switch between JTAG and UART at runtime and adjust their parameters. + - If you select a single destination (JTAG or UART) in Kconfig, the callback can override that destination's parameters at runtime, but it cannot switch the destination type. + +.. note:: + + Application tracing can also work as a transport adapter to the esp_trace library. In this case, the Application Level Tracing library will not be used directly, but rather through the selected esp_trace library with new APIs. + +.. note:: + + The code examples below are valid when the Application Level Tracing library is used standalone without a trace library. .. _app_trace-application-specific-tracing: @@ -110,7 +143,7 @@ In general, users should decide what type of data should be transferred in every return res; } - ``esp_apptrace_write()`` function uses memcpy to copy user data to the internal buffer. In some cases, it can be more optimal to use ``esp_apptrace_buffer_get()`` and ``esp_apptrace_buffer_put()`` functions. They allow developers to allocate buffer and fill it themselves. The following piece of code shows how to do this. + The :cpp:func:`esp_apptrace_write()` function uses memcpy to copy user data to the internal buffer. In some cases, it can be more optimal to use :cpp:func:`esp_apptrace_buffer_get()` and :cpp:func:`esp_apptrace_buffer_put()` functions. They allow developers to allocate buffer and fill it themselves. The following piece of code shows how to do this. .. code-block:: c @@ -157,7 +190,7 @@ In general, users should decide what type of data should be transferred in every ... } - ``esp_apptrace_read()`` function uses memcpy to copy host data to user buffer. In some casesm it can be more optimal to use ``esp_apptrace_down_buffer_get()`` and ``esp_apptrace_down_buffer_put()`` functions. They allow developers to occupy chunk of read buffer and process it in-place. The following piece of code shows how to do this. + The :cpp:func:`esp_apptrace_read()` function uses memcpy to copy host data to user buffer. In some cases, it can be more optimal to use :cpp:func:`esp_apptrace_down_buffer_get()` and :cpp:func:`esp_apptrace_down_buffer_put()` functions. They allow developers to occupy chunk of read buffer and process it in-place. The following piece of code shows how to do this. .. code-block:: c @@ -197,7 +230,7 @@ In general, users should decide what type of data should be transferred in every 5. Connect to OpenOCD telnet server. It can be done using the following command in terminal ``telnet 4444``. If telnet session is opened on the same machine which runs OpenOCD, you can use ``localhost`` as ```` in the command above. -6. Start trace data collection using special OpenOCD command. This command will transfer tracing data and redirect them to the specified file or socket (currently only files are supported as trace data destination). For description of the corresponding commands, see `OpenOCD Application Level Tracing Commands`_. +6. Start trace data collection using special OpenOCD command. This command will transfer tracing data and redirect them to the specified file or socket. For description of the corresponding commands, see `OpenOCD Application Level Tracing Commands`_. 7. The final step is to process received data. Since the format of data is defined by users, the processing stage is out of the scope of this document. Good starting points for data processor are python scripts in ``$IDF_PATH/tools/esp_app_trace``: ``apptrace_proc.py`` (used for feature tests) and ``logtrace_proc.py`` (see more details in section `Logging to Host`_). @@ -255,7 +288,7 @@ Command usage examples: .. highlight:: none -1. Collect 2048 bytes of tracing data to the file ``trace.log``. The file will be saved in the ``openocd-esp32`` directory. +1. Collect 2048 bytes of tracing data to the file ``trace.log``. The file will be saved in the ``openocd-esp32`` directory. :: @@ -328,7 +361,7 @@ How To Use It In order to use logging via trace module, users need to perform the following steps: -1. Enable application tracing in menuconfig (``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing``). +1. Enable application tracing in menuconfig by going to ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` and selecting ``ESP-IDF apptrace``. After that, configuration can be done at ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing``. 2. On the target side, the special vprintf-like function :cpp:func:`esp_apptrace_vprintf` needs to be installed. It sends log data to the host. An example is ``esp_log_set_vprintf(esp_apptrace_vprintf);``. To send log data to UART again, use ``esp_log_set_vprintf(vprintf);``. 3. Follow instructions in items 4-6 in `Application Specific Tracing`_ (OpenOCD setup and trace collection). 4. To print out collected log records, run the following command in terminal: ``$IDF_PATH/tools/esp_app_trace/logtrace_proc.py /path/to/trace/file /path/to/program/elf/file``. @@ -367,11 +400,11 @@ Another useful ESP-IDF feature built on top of application tracing library is th How To Use It """"""""""""" -Support for this feature is enabled by ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` (:ref:`CONFIG_APPTRACE_SV_ENABLE`) menuconfig option. There are several other options enabled under the same menu: +Support for this feature is enabled by ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView`` menuconfig option. There are several other options enabled under the same menu: -1. {IDF_TARGET_NAME} timer to use as SystemView timestamp source: (:ref:`CONFIG_APPTRACE_SV_TS_SOURCE`) selects the source of timestamps for SystemView events. In the single core mode, timestamps are generated using {IDF_TARGET_NAME} internal cycle counter running at maximum frequency. (:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`) In the dual-core mode, external timer is used to generate timestamps. It's frequency is 1/2 of the CPU frequency. +1. {IDF_TARGET_NAME} timer to use as SystemView timestamp source: (:ref:`CONFIG_ESP_TRACE_TIMESTAMP_SOURCE`) selects the source of timestamps for SystemView events. In the single core mode, timestamps are generated using {IDF_TARGET_NAME} internal cycle counter running at maximum frequency. (:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`) In the dual-core mode, external timer is used to generate timestamps. It's frequency is 1/2 of the CPU frequency. -2. Individually enabled or disabled collection of SystemView events (``CONFIG_APPTRACE_SV_EVT_XXX``): +2. Individually enabled or disabled collection of SystemView events (``CONFIG_SEGGER_SYSVIEW_EVT_XXX``): - Trace Buffer Overflow Event - ISR Enter Event @@ -389,7 +422,7 @@ Support for this feature is enabled by ``Component config`` > ``Application Leve ESP-IDF has all the code required to produce SystemView compatible traces. -3. Select Pro or App CPU in menuconfig options ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` to trace over the UART interface in real-time. +3. To trace over the UART interface in real-time, first select UART as the destination in ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing``. Then select Pro or App CPU in ``Component config`` > ``ESP Trace Configuration`` > ``SEGGER SystemView``. OpenOCD SystemView Tracing Command Options """""""""""""""""""""""""""""""""""""""""" @@ -447,6 +480,22 @@ Command usage examples: OpenOCD telnet command line prompt will not be available until tracing is stopped. To stop tracing, press Ctrl+C in the OpenOCD window. +Multi-Core SystemView Tracing Command +"""""""""""""""""""""""""""""""""""""" + +For SystemView version 3.60 and later, which supports multi-core tracing, use the ``esp sysview_mcore`` command. This command is identical to ``esp sysview`` but uses the official SEGGER SystemView multi-core format. Tracing data from all cores are saved in the same file, which can be opened in SEGGER SystemView v3.60 or later. + +Command usage example: + +.. highlight:: none + +:: + + esp sysview_mcore start file://heap_log_mcore.SVDat + +For detailed command syntax and options, refer to the ``esp sysview`` command above, as ``esp sysview_mcore`` accepts the same parameters. + + Data Visualization """""""""""""""""" @@ -454,9 +503,19 @@ After trace data are collected, users can use a special tool to visualize the re .. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES - Unfortunately, SystemView does not support tracing from multiple cores. So when tracing from {IDF_TARGET_NAME} with JTAG interfaces in the dual-core mode, two files are generated: one for PRO CPU and another for APP CPU. Users can load each file into separate instances of the tool. For tracing over UART, users can select ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` in menuconfig Pro or App to choose which CPU has to be traced. + **Multi-Core Tracing** -It is uneasy and awkward to analyze data for every core in separate instance of the tool. Fortunately, there is an Eclipse plugin called *Impulse* which can load several trace files, thus making it possible to inspect events from both cores in one view. Also, this plugin has no limitation of 1,000,000 events as compared to the free version of SystemView. + SystemView version 3.60 and later supports tracing from multiple cores. For multi-core tracing, use the ``esp sysview_mcore`` command to generate a single file compatible with SystemView multi-core format: + + :: + + esp sysview_mcore start file://heap_log_mcore.SVDat + + This command will create a single trace file that can be loaded directly into SystemView 3.60+ for multi-core visualization. + + **Note:** SystemView versions before 3.60 do not support multi-core tracing. For older versions, when tracing from {IDF_TARGET_NAME} with JTAG interfaces in the dual-core mode, two separate files are generated: one for PRO CPU and another for APP CPU. Users can load each file into separate instances of the tool. For tracing over UART, users can select ``Component config`` > ``ESP Trace Configuration`` > ``SEGGER SystemView`` in menuconfig to choose which CPU (Pro or App) has to be traced. + + For older SystemView versions, analyzing data for every core in separate instances can be awkward. An alternative is to use the Eclipse plugin called *Impulse*, which can load several trace files, making it possible to inspect events from both cores in one view. This plugin also has no limitation of 1,000,000 events as compared to the free version of SystemView. Good instructions on how to install, configure, and visualize data in Impulse from one core can be found `here `_. diff --git a/docs/en/api-reference/system/heap_debug.rst b/docs/en/api-reference/system/heap_debug.rst index 069a7245da..287dda1979 100644 --- a/docs/en/api-reference/system/heap_debug.rst +++ b/docs/en/api-reference/system/heap_debug.rst @@ -571,8 +571,8 @@ Host-Based Mode Once you have identified the code which you think is leaking: - In the project configuration menu, navigate to ``Component config`` > ``Heap Memory Debugging`` > :ref:`CONFIG_HEAP_TRACING_DEST` and select ``Host-Based``. -- In the project configuration menu, navigate to ``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing`` > ``Data Destination`` :ref:`CONFIG_APPTRACE_DESTINATION` and select ``JTAG``. -- In the project configuration menu, navigate to ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` and enable :ref:`CONFIG_APPTRACE_SV_ENABLE`. +- In the project configuration menu, navigate to ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` > ``Data Destination`` :ref:`CONFIG_APPTRACE_DESTINATION` and select ``JTAG``. +- In the project configuration menu, navigate to ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` and select ``SEGGER SystemView``. - Call the function :cpp:func:`heap_trace_init_tohost` early in the program, to initialize the JTAG heap tracing module. - Call the function :cpp:func:`heap_trace_start` to begin recording all memory allocation and free calls in the system. Call this immediately before the piece of code which you suspect is leaking memory. diff --git a/docs/en/migration-guides/release-6.x/6.0/system.rst b/docs/en/migration-guides/release-6.x/6.0/system.rst index bbf3652aac..97337b3d52 100644 --- a/docs/en/migration-guides/release-6.x/6.0/system.rst +++ b/docs/en/migration-guides/release-6.x/6.0/system.rst @@ -73,61 +73,44 @@ App Trace Configuration Changes ^^^^^^^^^^^^^^^^^^^^^ -Previously, application tracing was automatically enabled when a destination was configured. Now you must explicitly enable application tracing through ``CONFIG_APPTRACE_ENABLE``` option before configuring any destination. +The application tracing configuration menu has been moved. Previously located at ``Component config`` > ``Application Level Tracing``, it is now under ``Component config`` > ``ESP Trace Configuration``. -To enable application tracing, go to "Component config" → "Application Level Tracing" → "Enable Application Level Tracing" in menuconfig. +Previously, application tracing was automatically enabled when a destination was configured. Now you must explicitly enable application tracing by selecting the trace transport before configuring any destination. + +To enable application tracing, go to ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` and select ``ESP-IDF apptrace`` in menuconfig. After that, configuration can be done at ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing``. + +If apptrace will be used without a library (for example when SEGGER SystemView is disabled) in standalone mode, the following configurations need to be set in your sdkconfig file: + +.. code-block:: none + + CONFIG_ESP_TRACE_ENABLE=y + CONFIG_ESP_TRACE_LIB_NONE=y + CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y + +These can also be configured through menuconfig as described above. Removed extra data buffering option. ``CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX`` is no longer supported. Removed deprecated ``ESP_APPTRACE_DEST_TRAX`` enum value. Use ``ESP_APPTRACE_DEST_JTAG`` instead. +Component Dependency Changes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Applications now require the ``esp_trace`` component instead of ``app_trace``. Update your component's ``CMakeLists.txt`` file to reflect this change. + +The ``app_trace`` component is now a sub-component of ``esp_trace`` and will be included automatically when needed. + Initialization Flow Changes ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If you need to override the default configuration at runtime, you can implement the ``esp_apptrace_get_user_params()`` callback function. A weak default implementation exists that returns menuconfig defaults (``APPTRACE_CONFIG_DEFAULT()``). Your application can override this by providing its own configuration. - - .. code-block:: c - - esp_apptrace_config_t esp_apptrace_get_user_params(void) - { - esp_apptrace_config_t config = APPTRACE_CONFIG_DEFAULT(); - - // Override with custom values (example for UART) - config.dest_cfg.uart.uart_num = UART_NUM_0; - config.dest_cfg.uart.baud_rate = 921600; - config.dest_cfg.uart.tx_pin_num = GPIO_NUM_17; - config.dest_cfg.uart.rx_pin_num = GPIO_NUM_16; - - return config; - } - - **Important:** - - - Do **not** add ``__attribute__((weak))`` to your implementation - - You can also use destination-specific macros: ``APPTRACE_JTAG_CONFIG_DEFAULT()`` or ``APPTRACE_UART_CONFIG_DEFAULT()`` +For runtime configuration override, a new callback system is available. See the :doc:`Application Tracing documentation <../../../api-guides/app_trace>` for details on ``esp_apptrace_get_user_params()`` and ``esp_trace_get_user_params()``. API Changes ^^^^^^^^^^^ The destination parameter has been removed from all apptrace APIs. -Old Version: - -.. code-block:: c - - esp_apptrace_write(ESP_APPTRACE_DEST_JTAG, data, size, timeout); - esp_apptrace_read(ESP_APPTRACE_DEST_UART, buffer, &size, timeout); - esp_apptrace_flush(ESP_APPTRACE_DEST_JTAG, min_sz, timeout); - -Update to: - -.. code-block:: c - - esp_apptrace_write(data, size, timeout); - esp_apptrace_read(buffer, &size, timeout); - esp_apptrace_flush(min_sz, timeout); - -The destination is now configured in menuconfig under "Application Level Tracing" → "Data Destination". +Default destination is now configured in menuconfig under ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` and can be altered at runtime by providing callback with custom tracing configuration. The UART destination configuration has been simplified: @@ -151,12 +134,12 @@ New configuration: CONFIG_APPTRACE_DEST_UART=y CONFIG_APPTRACE_DEST_UART_NUM=0 # or 1, 2 depending on target -SystemView Destination -^^^^^^^^^^^^^^^^^^^^^^ +SystemView Configuration +^^^^^^^^^^^^^^^^^^^^^^^^ -The SystemView destination is now controlled by the same configuration as the application trace destination. When SystemView is enabled, it will use the destination configured under "Application Level Tracing" → "Data Destination". +The SystemView configuration has been moved to a new location in the menuconfig: ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView``. -This means that if you have both application tracing and SystemView enabled, they will share the same destination (JTAG or UART) as configured in the menuconfig. SystemView will not have its own destination configuration. +The SystemView no longer has its own separate destination configuration. It shares the configuration with the application tracing transport (JTAG or UART). FreeRTOS -------- @@ -249,7 +232,7 @@ OTA Updates The partial download functionality in ESP HTTPS OTA has been moved under a configuration option in order to reduce the memory footprint if partial download is not used. -To use partial download features in your OTA applications, you need to enable the component-level configuration :ref:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` in menuconfig (``Component config`` → ``ESP HTTPS OTA`` → ``Enable partial HTTP download for OTA``). +To use partial download features in your OTA applications, you need to enable the component-level configuration :ref:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` in menuconfig (``Component config`` > ``ESP HTTPS OTA`` > ``Enable partial HTTP download for OTA``). Removed Deprecated APIs ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/zh_CN/api-guides/app_trace.rst b/docs/zh_CN/api-guides/app_trace.rst index 48b763d0d7..8ea25142c0 100644 --- a/docs/zh_CN/api-guides/app_trace.rst +++ b/docs/zh_CN/api-guides/app_trace.rst @@ -41,7 +41,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 1. **主机端:** 应用程序跟踪通过 JTAG 来完成,因此需要在主机上安装并运行 OpenOCD。详细信息请参阅 :doc:`JTAG 调试 <../api-guides/jtag-debugging/index>`。 -2. **目标端:** 在 menuconfig 中开启应用程序跟踪功能。**重要提示:** 您必须首先通过 ``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing`` (:ref:`CONFIG_APPTRACE_ENABLE`) 启用应用程序跟踪。启用此选项后,您可以配置跟踪数据的传输目标。对于 UART 接口,用户需要定义端口号、波特率、TX 和 RX 管脚及其他相关参数。当启用 FreeRTOS SystemView 跟踪功能时,所选目标也将被用于 SystemView 跟踪。 +2. **目标端:** 在 menuconfig 中开启应用程序跟踪功能。**重要提示:** 须首先通过 ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` 并选择 ``ESP-IDF apptrace`` 启用应用程序跟踪。之后,可以在 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 中进行详细配置,例如配置跟踪数据的传输目标。对于 UART 接口,需定义端口号、波特率、TX 和 RX 管脚及其他相关参数。当选择任何跟踪库(例如 SEGGER SystemView)时,这些配置也将同步用于该库。 .. note:: @@ -53,7 +53,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 2. *Timeout for flushing last trace data to host on panic* (:ref:`CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO`)。该选项仅在流模式下才可发挥作用,它可用于控制跟踪模块在发生 Panic 时等待主机读取最新数据的最长时间。 -3. *Internal Sync Lock* (:ref:`CONFIG_APPTRACE_LOCK_ENABLE`)。启用此选项可使用锁保护跟踪缓冲区写入操作,防止多个任务并发生成跟踪数据时发生数据损坏。 +3. *Internal Sync Lock* (:ref:`CONFIG_APPTRACE_LOCK_ENABLE`)。启用此选项可使用锁保护跟踪缓冲区的写入操作,防止多个任务并发生成跟踪数据时发生数据损坏。 4. *UART RX/TX ring buffer size* (:ref:`CONFIG_APPTRACE_UART_TX_BUFF_SIZE`)。缓冲区的大小取决于通过 UART 传输的数据量。 @@ -63,9 +63,42 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 如何使用此库 -------------- -该库提供了用于在主机和 {IDF_TARGET_NAME} 之间传输任意数据的 API。在 menuconfig 中启用该库后,应用程序跟踪模块会在系统启动期间使用 menuconfig 配置自动初始化。然后用户可以调用相应的 API 来发送、接收或者刷新数据。 +该库提供了用于在主机和 {IDF_TARGET_NAME} 之间传输任意数据的 API。在 menuconfig 中启用该库后,应用程序跟踪模块会在系统启动期间使用 menuconfig 配置自动初始化。随后用户可以调用相应的 API 来发送、接收或者刷新数据。 -用户可以通过实现弱回调函数 :cpp:func:`esp_apptrace_get_user_params()` 来覆盖默认配置(可选)。 +用户可选择通过实现弱回调函数 :cpp:func:`esp_apptrace_get_user_params()` 来覆盖默认配置。该函数仅在未选择任何跟踪库时生效,此时,仅应用层跟踪库(``app_trace`` 组件)独立运行。否则,系统将调用 :cpp:func:`esp_trace_get_user_params()` 来覆盖默认配置。 + +快速入门 +--------- + +1. 独立使用应用层跟踪 API + + 在 menuconfig 中禁用跟踪库并启用应用层跟踪传输: + + - ``Component config`` > ``ESP Trace Configuration`` > ``Trace library``:选择 ``None`` + - ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport``:选择 ``ESP-IDF apptrace`` + + 也可在 ``sdkconfig.defaults`` 中设置以下选项以强制启用独立模式: + + .. code-block:: none + + CONFIG_ESP_TRACE_ENABLE=y + CONFIG_ESP_TRACE_LIB_NONE=y + CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y + + 通过上述任一方式启用独立应用层跟踪传输后,即可在 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 中配置目标传输。 + +2. 通过 ``esp_apptrace_get_user_params()`` 进行运行时配置 + + - 如果在 Kconfig 中选择 ``All (runtime selection)`` (即 ``APPTRACE_DEST_ALL``),可通过回调函数在运行时切换 JTAG 和 UART 并调整其参数。 + - 如果在 Kconfig 中选定单一目标(JTAG 或 UART),回调函数可在运行时覆盖该目标的参数,但无法切换目标类型。 + +.. note:: + + 应用程序跟踪也可作为 esp_trace 库的传输适配器。在这种情况下,应用层跟踪库不会被直接使用,而是通过已选择的 esp_trace 库及其 API 间接使用。 + +.. note:: + + 以下代码示例适用于应用层跟踪库独立运行(未绑定任何跟踪库)的场景。 .. _app_trace-application-specific-tracing: @@ -85,8 +118,8 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 { esp_apptrace_config_t config = APPTRACE_CONFIG_DEFAULT(); - // Customize configuration if needed - // For example, to use different UART pins: + // 根据需要自定义配置 + // 例如,使用不同的 UART 引脚: config.dest_cfg.uart.tx_pin_num = GPIO_NUM_17; config.dest_cfg.uart.rx_pin_num = GPIO_NUM_16; @@ -110,7 +143,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 return res; } - ``esp_apptrace_write()`` 函数使用 memcpy 把用户数据复制到内部缓存中。在某些情况下,使用 ``esp_apptrace_buffer_get()`` 和 ``esp_apptrace_buffer_put()`` 函数会更加理想,它们允许开发人员自行分配缓冲区并填充。下面的代码片段展示了如何执行此操作。 + 函数 :cpp:func:`esp_apptrace_write()` 通过 memcpy 将用户数据复制到内部缓冲区。在某些情况下,使用 :cpp:func:`esp_apptrace_buffer_get()` 和 :cpp:func:`esp_apptrace_buffer_put()` 函数可能是更优的选择。这两个函数允许开发者自行分配缓冲区并填充数据。以下代码片段展示了具体实现方法。 .. code-block:: c @@ -157,7 +190,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 ... } - ``esp_apptrace_read()`` 函数使用 memcpy 把主机端的数据复制到用户缓存区。在某些情况下,使用 ``esp_apptrace_down_buffer_get()`` 和 ``esp_apptrace_down_buffer_put()`` 函数可能更为理想。它们允许开发人员占用一块读缓冲区并就地进行有关处理操作。下面的代码片段展示了如何执行此操作。 + 函数 :cpp:func:`esp_apptrace_read()` 通过 memcpy 将主机数据复制到用户缓冲区。在某些情况下,使用 :cpp:func:`esp_apptrace_down_buffer_get()` 和 :cpp:func:`esp_apptrace_down_buffer_put()` 函数可能是更优的选择。这两个函数允许开发者直接占用读取缓冲区的数据块并进行原地处理。以下代码片段展示了具体实现方法。 .. code-block:: c @@ -197,7 +230,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 5. 连接到 OpenOCD 的 telnet 服务器。用户可在终端执行命令 ``telnet 4444``。如果用户是在运行 OpenOCD 的同一台机器上打开 telnet 会话,可以使用 ``localhost`` 替换上面命令中的 ````。 -6. 使用特殊的 OpenOCD 命令开始收集待跟踪的命令。此命令将传输跟踪数据并将其重定向到指定的文件或套接字(当前仅支持文件作为跟踪数据目标)。相关命令的说明,请参阅 :ref:`jtag-debugging-launching-debugger`。 +6. 使用特殊的 OpenOCD 命令开始收集待跟踪的命令。此命令将传输跟踪数据并将其重定向到指定的文件或套接字。相关命令的说明,请参阅 `OpenOCD 应用程序跟踪命令`_。 7. 最后,处理接收到的数据。由于数据格式由用户自己定义,本文档中省略数据处理的具体流程。数据处理的范例可以参考位于 ``$IDF_PATH/tools/esp_app_trace`` 下的 Python 脚本 ``apptrace_proc.py`` (用于功能测试)和 ``logtrace_proc.py`` (请参阅 :ref:`app_trace-logging-to-host` 章节中的详细信息)。 @@ -232,7 +265,7 @@ OpenOCD 应用程序跟踪命令 Start 子命令的语法: - ``start [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]`` + ``start [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]`` ``outfile`` 用于保存来自两个 CPU 的数据文件的路径,该参数需要具有以下格式: ``file://path/to/file``。 @@ -261,11 +294,11 @@ Start 子命令的语法: esp apptrace start file://trace.log 1 2048 5 0 0 - 跟踪数据会被检索并以非阻塞的模式保存到文件中,如果收集满 2048 字节的数据或者在 5 秒内都没有新的数据,那么该过程就会停止。 + 跟踪数据会被检索并以非阻塞的模式保存到文件中,如果收集满 2048 字节的数据或者在 5 秒内都没有新的数据,那么该过程就会停止。 - .. note:: + .. note:: - 在将数据提供给 OpenOCD 之前,会对其进行缓冲。如果看到 “Data timeout!” 的消息,则表示目标可能在超时之前没有向 OpenOCD 发送足够的数据以清空缓冲区。要解决这个问题,可以增加超时时间或者使用函数 ``esp_apptrace_flush()`` 以特定间隔刷新数据。 + 在将数据提供给 OpenOCD 之前,会对其进行缓冲。如果看到 “Data timeout!” 的消息,则表示目标可能在超时之前没有向 OpenOCD 发送足够的数据以清空缓冲区。要解决这个问题,可以增加超时时间或者使用函数 ``esp_apptrace_flush()`` 以特定间隔刷新数据。 2. 在非阻塞模式下无限地检索跟踪数据。 @@ -273,7 +306,7 @@ Start 子命令的语法: esp apptrace start file://trace.log 1 -1 -1 0 0 - 对收集数据的大小没有限制,也不设置超时时间。要停止此过程,可以在 OpenOCD 的 telnet 会话窗口中发送 ``esp apptrace stop`` 命令,或者在 OpenOCD 窗口中使用快捷键 Ctrl+C。 + 对收集数据的大小没有限制,也不设置超时时间。要停止此过程,可以在 OpenOCD 的 telnet 会话窗口中发送 ``esp apptrace stop`` 命令,或者在 OpenOCD 窗口中使用快捷键 Ctrl+C。 3. 检索跟踪数据并无限期保存。 @@ -281,7 +314,7 @@ Start 子命令的语法: esp apptrace start file://trace.log 0 -1 -1 0 0 - 在跟踪停止之前,OpenOCD 的 telnet 会话窗口将不可用。要停止跟踪,请在 OpenOCD 的窗口中使用快捷键 Ctrl+C。 + 在跟踪停止之前,OpenOCD 的 telnet 会话窗口将不可用。要停止跟踪,请在 OpenOCD 的窗口中使用快捷键 Ctrl+C。 4. 等待目标停止,然后恢复目标的操作并开始检索数据。当收集满 2048 字节的数据后就停止: @@ -289,7 +322,7 @@ Start 子命令的语法: esp apptrace start file://trace.log 0 2048 -1 1 0 - 想要复位后立即开始跟踪,请使用 OpenOCD 的 ``reset halt`` 命令。 + 想要复位后立即开始跟踪,请使用 OpenOCD 的 ``reset halt`` 命令。 .. _app_trace-logging-to-host: @@ -328,9 +361,9 @@ ESP-IDF 的日志库会默认使用类 vprintf 的函数将格式化的字符串 为了使用跟踪模块来记录日志,用户需要执行以下步骤: -1. 在 menuconfig 中启用应用程序跟踪功能(路径为 ``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing``)。 +1. 在 menuconfig 中开启应用程序跟踪功能。须首先通过 ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` 并选择 ``ESP-IDF apptrace`` 启用应用程序跟踪。之后,可以在 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 中进行详细配置。 2. 在目标端,需要安装特殊的类 vprintf 函数 :cpp:func:`esp_apptrace_vprintf`,该函数负责将日志数据发送给主机,使用方法为 ``esp_log_set_vprintf(esp_apptrace_vprintf);``。如需将日志数据再次重定向给 UART,请使用 ``esp_log_set_vprintf(vprintf);``。 -3. 按照 :ref:`app_trace-application-specific-tracing` 章节中的第 1-5 步进行操作。 +3. 按照 :ref:`app_trace-application-specific-tracing` 章节中的第 4-6 步进行操作(OpenOCD 设置和跟踪数据收集)。 4. 打印接收到的日志记录,请在终端运行以下命令:``$IDF_PATH/tools/esp_app_trace/logtrace_proc.py /path/to/trace/file /path/to/program/elf/file``。 @@ -367,11 +400,11 @@ ESP-IDF 中另一个基于应用层跟踪库的实用功能是系统级跟踪, 如何使用 """""""" -若需使用这个功能,需要在 menuconfig 中开启 :ref:`CONFIG_APPTRACE_SV_ENABLE` 选项,具体路径为 ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing``。同一菜单栏下还开启了其它几个选项: +若需使用这个功能,需要在 menuconfig 中通过 ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView`` 选项启用此功能。同一菜单栏下还有其它几个选项: -1. {IDF_TARGET_NAME} 用作 SystemView 时间戳源的定时器选择:(:ref:`CONFIG_APPTRACE_SV_TS_SOURCE`)用于选择 SystemView 事件的时间戳源。在单核模式下,时间戳由以最大频率运行的 {IDF_TARGET_NAME} 内部周期计数器生成。(:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`)在双核模式下,使用外部定时器生成时间戳,其频率为 CPU 频率的 1/2。 +1. {IDF_TARGET_NAME} 用作 SystemView 时间戳源的定时器选择:(:ref:`CONFIG_ESP_TRACE_TIMESTAMP_SOURCE`)用于选择 SystemView 事件的时间戳源。在单核模式下,时间戳由以最大频率运行的 {IDF_TARGET_NAME} 内部周期计数器生成。(:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`)在双核模式下,使用外部定时器生成时间戳,其频率为 CPU 频率的 1/2。 -2. 可以单独启用或禁用的 SystemView 事件集合 (``CONFIG_APPTRACE_SV_EVT_XXX``): +2. 可以单独启用或禁用的 SystemView 事件集合 (``CONFIG_SEGGER_SYSVIEW_EVT_XXX``): - Trace Buffer Overflow Event - ISR Enter Event @@ -389,7 +422,7 @@ ESP-IDF 中另一个基于应用层跟踪库的实用功能是系统级跟踪, ESP-IDF 中已经包含了所有用于生成兼容 SystemView 跟踪信息的代码。 -3. 想要通过 UART 接口进行实时跟踪,请在菜单配置选项 ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` 中选择 Pro 或 App CPU。 +3. 想要通过 UART 接口进行实时跟踪,请首先在 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 中选择 UART 作为目标传输方式。然后在 ``Component config`` > ``ESP Trace Configuration`` > ``SEGGER SystemView`` 中选择 Pro 或 App CPU。 OpenOCD SystemView 跟踪命令选项 """"""""""""""""""""""""""""""" @@ -447,6 +480,22 @@ Start 子命令语法: OpenOCD 的 telnet 命令行在跟踪停止前会无法使用,要停止跟踪,请在 OpenOCD 窗口使用 Ctrl+C 快捷键。 +多核 SystemView 跟踪命令 +"""""""""""""""""""""""""" + +对于支持多核跟踪的 SystemView 3.60 及更高版本,请使用 ``esp sysview_mcore`` 命令。此命令与 ``esp sysview`` 相同,但使用官方 SEGGER SystemView 多核格式。所有核心的跟踪数据都保存在同一文件中,可在 SEGGER SystemView v3.60 或更高版本中打开。 + +命令使用示例: + +.. highlight:: none + +:: + + esp sysview_mcore start file://heap_log_mcore.SVDat + +有关详细的命令语法和选项,请参考前文所述的 ``esp sysview`` 命令,因为 ``esp sysview_mcore`` 支持相同的参数。 + + 数据可视化 """""""""" @@ -454,9 +503,19 @@ Start 子命令语法: .. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES - 遗憾的是,SystemView 不支持从多个核心进行跟踪。所以当使用 JTAG 跟踪双核模式下的 {IDF_TARGET_NAME} 时会生成两个文件:一个用于 PRO CPU,另一个用于 APP CPU。用户可以将每个文件加载到工具中单独分析。使用 UART 进行跟踪时,用户可以在 menuconfig Pro 或 App 中点击 ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` 并选择要跟踪的 CPU。 + **多核跟踪** -在工具中单独分析每个核的跟踪数据是比较棘手的,但是 Eclipse 提供了 *Impulse* 插件,该插件可以加载多个跟踪文件,并且可以在同一视图中检查来自两个内核的事件。此外,与免费版的 SystemView 相比,此插件没有 1,000,000 个事件的限制。 + SystemView 3.60 及更高版本支持多核心进行跟踪。对于多核跟踪,使用 ``esp sysview_mcore`` 命令可以生成与 SystemView 多核格式兼容的单个文件: + + :: + + esp sysview_mcore start file://heap_log_mcore.SVDat + + 此命令将创建一个单独的跟踪文件,可以直接加载到 SystemView 3.60+ 中进行多核可视化。 + + **注意:** SystemView 3.60 之前的版本不支持多核跟踪。对于旧版本,当使用 JTAG 接口跟踪双核模式下的 {IDF_TARGET_NAME} 时会生成两个文件:一个用于 PRO CPU,另一个用于 APP CPU。用户可将每个文件载入不同的工具实例。使用 UART 进行跟踪时,用户可以在 menuconfig 中选择 ``Component config`` > ``ESP Trace Configuration`` > ``SEGGER SystemView`` 来指定需要跟踪的 CPU(Pro 或 App)。 + + 对于旧版本的 SystemView,在不同的实例中分别分析每个核的数据可能较为不便。另一个选择是使用名为 *Impulse* 的 Eclipse 插件,该插件可同时加载多个跟踪文件,实现在同一视图中检查来自两个核心的事件。与 SystemView 免费版相比,此插件还不受 100 万事件数量的限制。 关于如何安装、配置 Impulse 并使用它来可视化来自单个核心的跟踪数据,请参阅 `官方教程 `_ 。 @@ -485,7 +544,6 @@ Start 子命令语法: 如果你在可视化方面遇到了问题(未显示数据或者缩放操作异常),可以尝试删除当前的信号层次结构,再双击必要的文件或端口。Eclipse 会请求创建新的信号层次结构。 - .. _app_trace-gcov-source-code-coverage: Gcov(源代码覆盖率) diff --git a/docs/zh_CN/api-reference/system/heap_debug.rst b/docs/zh_CN/api-reference/system/heap_debug.rst index c932b8049f..370cc13751 100644 --- a/docs/zh_CN/api-reference/system/heap_debug.rst +++ b/docs/zh_CN/api-reference/system/heap_debug.rst @@ -571,8 +571,8 @@ ESP-IDF 集成了用于请求 :ref:`堆内存信息 `、:ref:` 确定存在泄漏的代码后,请执行以下步骤: - 在项目配置菜单中,前往 ``Component config`` > ``Heap Memory Debugging`` > :ref:`CONFIG_HEAP_TRACING_DEST` 并选择 ``Host-Based``。 -- 在项目配置菜单中,前往 ``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing`` > ``Data Destination`` :ref:`CONFIG_APPTRACE_DESTINATION` 并选择 ``JTAG``。 -- 在项目配置菜单中,前往 ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` 并启用 :ref:`CONFIG_APPTRACE_SV_ENABLE`。 +- 在项目配置菜单中,前往 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` > ``Data Destination`` :ref:`CONFIG_APPTRACE_DESTINATION` 并选择 ``JTAG``。 +- 在项目配置菜单中,前往 ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` 并选择 ``SEGGER SystemView``。 - 在程序早期,调用函数 :cpp:func:`heap_trace_init_tohost`,初始化 JTAG 堆内存跟踪模块。 - 在有内存泄漏之嫌的代码块前,调用函数 :cpp:func:`heap_trace_start` 开始记录系统中的内存分配和释放操作。 diff --git a/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst b/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst index 8678610fa1..b9cdd4b055 100644 --- a/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst +++ b/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst @@ -73,61 +73,44 @@ App 追踪 配置更改 ^^^^^^^^^^ -此前,当配置传输目标时,应用程序跟踪会自动启用。现在必须在配置任何目标前,通过 ``CONFIG_APPTRACE_ENABLE`` 选项显式启用应用程序跟踪功能。 +应用程序跟踪配置菜单已移动。之前位于 ``Component config`` > ``Application Level Tracing``,现在位于 ``Component config`` > ``ESP Trace Configuration``。 -如需启用应用程序跟踪,请在 menuconfig 中依次进入 "Component config" → "Application Level Tracing" → "Enable Application Level Tracing" 进行设置。 +此前,应用程序跟踪功能会在配置目标传输方式时自动启用。现在必须在配置任何目标传输方式前,通过选择跟踪传输方式显式启用应用程序跟踪功能。 + +如需启用应用程序跟踪,请在 menuconfig 中依次进入 ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` 并选择 ``ESP-IDF apptrace``。之后,可以在 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 中进行配置。 + +如果要在独立模式下使用 apptrace 而不使用库(例如禁用 SEGGER SystemView 时),需要在 sdkconfig 文件中设置以下配置: + +.. code-block:: none + + CONFIG_ESP_TRACE_ENABLE=y + CONFIG_ESP_TRACE_LIB_NONE=y + CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y + +这些配置也可以按上述说明通过 menuconfig 进行设置。 已移除额外数据缓冲选项。不再支持 ``CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX`` 配置项。 已移除弃用的 ``ESP_APPTRACE_DEST_TRAX`` 枚举值。请改用 ``ESP_APPTRACE_DEST_JTAG``。 +组件依赖更改 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +应用程序现在需要 ``esp_trace`` 组件,而不是 ``app_trace``。请更新组件的 ``CMakeLists.txt`` 文件以反映此更改。 + +``app_trace`` 组件现在是 ``esp_trace`` 的子组件,将在需要时自动包含。 + 初始化流程更改 ^^^^^^^^^^^^^^^^^^^ -如需在运行时覆盖默认配置,可以实现 ``esp_apptrace_get_user_params()`` 回调函数。系统提供了一个弱默认实现,返回 menuconfig 的默认配置(``APPTRACE_CONFIG_DEFAULT()``)。您的应用程序可以通过提供自己的配置来覆盖此默认实现。 - - .. code-block:: c - - esp_apptrace_config_t esp_apptrace_get_user_params(void) - { - esp_apptrace_config_t config = APPTRACE_CONFIG_DEFAULT(); - - // 使用自定义值覆盖(UART 示例) - config.dest_cfg.uart.uart_num = UART_NUM_0; - config.dest_cfg.uart.baud_rate = 921600; - config.dest_cfg.uart.tx_pin_num = GPIO_NUM_17; - config.dest_cfg.uart.rx_pin_num = GPIO_NUM_16; - - return config; - } - - **重要提示:** - - - 请 **勿** 在您的实现中添加 ``__attribute__((weak))`` - - 您也可以使用特定目标的宏:``APPTRACE_JTAG_CONFIG_DEFAULT()`` 或 ``APPTRACE_UART_CONFIG_DEFAULT()`` +对于运行时配置覆盖,提供了新的回调系统。详细信息请参见 :doc:`应用程序跟踪文档 <../../../api-guides/app_trace>` 中关于 ``esp_apptrace_get_user_params()`` 和 ``esp_trace_get_user_params()`` 的说明。 API 更改 ^^^^^^^^^^^ 所有 apptrace API 中的目标参数已被移除。 -旧版本: - -.. code-block:: c - - esp_apptrace_write(ESP_APPTRACE_DEST_JTAG, data, size, timeout); - esp_apptrace_read(ESP_APPTRACE_DEST_UART, buffer, &size, timeout); - esp_apptrace_flush(ESP_APPTRACE_DEST_JTAG, min_sz, timeout); - -更新为: - -.. code-block:: c - - esp_apptrace_write(data, size, timeout); - esp_apptrace_read(buffer, &size, timeout); - esp_apptrace_flush(min_sz, timeout); - -目标现在在 menuconfig 中的 "Application Level Tracing" → "Data Destination" 下全局配置。 +默认目标现在在 menuconfig 中的 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 下配置,并且可以在运行时通过提供带有自定义跟踪配置的回调来更改。 UART 目标配置已简化: @@ -151,12 +134,12 @@ UART 目标配置已简化: CONFIG_APPTRACE_DEST_UART=y CONFIG_APPTRACE_DEST_UART_NUM=0 # 或 1、2,具体取决于目标芯片 -SystemView 的传输目标 -^^^^^^^^^^^^^^^^^^^^^^^ +SystemView 配置 +^^^^^^^^^^^^^^^^^^^^^^^^ -SystemView 的传输目标现在由与应用程序跟踪目标相同的配置控制。启用 SystemView 后,它将使用在 "Application Level Tracing" → "Data Destination" 下配置的目标传输方式。 +SystemView 配置已移至 menuconfig 中的新位置:``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView``。 -这意味着如果同时启用了应用程序跟踪和 SystemView,它们将共享在 menuconfig 中配置的相同目标传输方式(JTAG 或 UART)。SystemView 将不再拥有独立的传输目标配置。 +SystemView 不再拥有独立的传输目标配置。它与应用程序跟踪传输方式(JTAG 或 UART)共享配置。 FreeRTOS -------- @@ -249,7 +232,7 @@ OTA 更新 ESP HTTPS OTA 的分段下载功能已移至配置选项下,以便在未使用分段下载时减少内存占用。 -如果要在 OTA 应用中使用分段下载功能,需要在 menuconfig 中启用组件级配置 :ref:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` (``Component config`` → ``ESP HTTPS OTA`` → ``Enable partial HTTP download for OTA``)。 +如果要在 OTA 应用中使用分段下载功能,需要在 menuconfig 中启用组件级配置 :ref:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` (``Component config`` > ``ESP HTTPS OTA`` > ``Enable partial HTTP download for OTA``)。 已移除的废弃 API ^^^^^^^^^^^^^^^^^^^^ diff --git a/examples/system/app_trace_basic/main/CMakeLists.txt b/examples/system/app_trace_basic/main/CMakeLists.txt index 0558d62cba..0664fdf7a4 100644 --- a/examples/system/app_trace_basic/main/CMakeLists.txt +++ b/examples/system/app_trace_basic/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "app_trace_basic_example_main.c" - PRIV_REQUIRES app_trace + PRIV_REQUIRES esp_trace INCLUDE_DIRS ".") diff --git a/examples/system/app_trace_basic/main/app_trace_basic_example_main.c b/examples/system/app_trace_basic/main/app_trace_basic_example_main.c index de89536b58..cdd5812c08 100644 --- a/examples/system/app_trace_basic/main/app_trace_basic_example_main.c +++ b/examples/system/app_trace_basic/main/app_trace_basic_example_main.c @@ -16,14 +16,14 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_app_trace.h" #include "soc/uart_pins.h" #include "esp_log.h" +#include "esp_app_trace.h" static const char *TAG = "example"; #if !CONFIG_APPTRACE_DEST_JTAG -/* Override default config to use console pins as a uart channel */ +/* Override default uart config to use console pins as a uart channel */ esp_apptrace_config_t esp_apptrace_get_user_params(void) { esp_apptrace_config_t config = APPTRACE_UART_CONFIG_DEFAULT(); @@ -56,7 +56,7 @@ void app_main(void) if (res != ESP_OK) { ESP_LOGE(TAG, "Failed to write data to host [0x%x] (%s)", res, esp_err_to_name(res)); } - esp_apptrace_flush(1000); + esp_apptrace_flush( 1000); vTaskDelay(50 / portTICK_PERIOD_MS); } diff --git a/examples/system/app_trace_basic/sdkconfig.ci.apptrace_uart b/examples/system/app_trace_basic/sdkconfig.ci.apptrace_uart index e2a7c255a3..d96128e892 100644 --- a/examples/system/app_trace_basic/sdkconfig.ci.apptrace_uart +++ b/examples/system/app_trace_basic/sdkconfig.ci.apptrace_uart @@ -1,3 +1,3 @@ CONFIG_ESP_CONSOLE_NONE=y -# Destination selection on runtime -CONFIG_APPTRACE_DEST_NONE=y +# Destination can be selectable on runtime +CONFIG_APPTRACE_DEST_ALL=y diff --git a/examples/system/app_trace_basic/sdkconfig.defaults b/examples/system/app_trace_basic/sdkconfig.defaults index 376f789f61..0bf0d89da2 100644 --- a/examples/system/app_trace_basic/sdkconfig.defaults +++ b/examples/system/app_trace_basic/sdkconfig.defaults @@ -1,2 +1,4 @@ # Enable application tracing by default -CONFIG_APPTRACE_ENABLE=y +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_NONE=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y diff --git a/examples/system/app_trace_to_plot/main/CMakeLists.txt b/examples/system/app_trace_to_plot/main/CMakeLists.txt index d96666ff74..ce5523dc83 100644 --- a/examples/system/app_trace_to_plot/main/CMakeLists.txt +++ b/examples/system/app_trace_to_plot/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "app_trace_to_plot.c" - PRIV_REQUIRES app_trace + PRIV_REQUIRES esp_trace INCLUDE_DIRS ".") diff --git a/examples/system/app_trace_to_plot/main/app_trace_to_plot.c b/examples/system/app_trace_to_plot/main/app_trace_to_plot.c index db686a1085..ce872916ab 100644 --- a/examples/system/app_trace_to_plot/main/app_trace_to_plot.c +++ b/examples/system/app_trace_to_plot/main/app_trace_to_plot.c @@ -17,6 +17,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_app_trace.h" +#include "esp_trace.h" #include "esp_log.h" #include #include diff --git a/examples/system/app_trace_to_plot/sdkconfig.defaults b/examples/system/app_trace_to_plot/sdkconfig.defaults index bcec5bd2f0..fbbd10861b 100644 --- a/examples/system/app_trace_to_plot/sdkconfig.defaults +++ b/examples/system/app_trace_to_plot/sdkconfig.defaults @@ -1,3 +1,5 @@ # Enable application tracing by default -CONFIG_APPTRACE_ENABLE=y +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_NONE=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y CONFIG_APPTRACE_DEST_JTAG=y diff --git a/examples/system/gcov/sdkconfig.defaults b/examples/system/gcov/sdkconfig.defaults index 4d64a37900..bd9ffe56ca 100644 --- a/examples/system/gcov/sdkconfig.defaults +++ b/examples/system/gcov/sdkconfig.defaults @@ -1,5 +1,7 @@ +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_NONE=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y CONFIG_APPTRACE_DEST_JTAG=y -CONFIG_APPTRACE_ENABLE=y CONFIG_APPTRACE_LOCK_ENABLE=y CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO=-1 CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH=0 diff --git a/examples/system/sysview_tracing/main/CMakeLists.txt b/examples/system/sysview_tracing/main/CMakeLists.txt index 55b846e1da..ff0df4c7b7 100644 --- a/examples/system/sysview_tracing/main/CMakeLists.txt +++ b/examples/system/sysview_tracing/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "sysview_tracing.c" - PRIV_REQUIRES esp_driver_gptimer app_trace + PRIV_REQUIRES esp_driver_gptimer esp_trace INCLUDE_DIRS ".") diff --git a/examples/system/sysview_tracing/main/sysview_tracing.c b/examples/system/sysview_tracing/main/sysview_tracing.c index 0d62a12217..498e29fb14 100644 --- a/examples/system/sysview_tracing/main/sysview_tracing.c +++ b/examples/system/sysview_tracing/main/sysview_tracing.c @@ -9,6 +9,7 @@ #include "esp_err.h" #include "sdkconfig.h" +#include #include #include #include @@ -18,10 +19,11 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gptimer.h" +#include "esp_trace.h" static const char *TAG = "example"; -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW #if !CONFIG_USE_CUSTOM_EVENT_ID #define SYSVIEW_EXAMPLE_SEND_EVENT_ID 0 @@ -76,7 +78,7 @@ static void example_sysview_event_send(uint32_t id, uint32_t val) #define SYSVIEW_EXAMPLE_WAIT_EVENT_START() #define SYSVIEW_EXAMPLE_WAIT_EVENT_END(_val_) -#endif // CONFIG_APPTRACE_SV_ENABLE +#endif // CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW typedef struct { gptimer_handle_t gptimer; @@ -140,7 +142,7 @@ void app_main(void) static example_event_data_t event_data[CONFIG_FREERTOS_NUMBER_OF_CORES]; -#if CONFIG_APPTRACE_SV_ENABLE && CONFIG_USE_CUSTOM_EVENT_ID +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW && CONFIG_USE_CUSTOM_EVENT_ID // Currently OpenOCD does not support requesting module info from target. So do the following... // Wait until SystemView module receives START command from host, // after that data can be sent to the host using onboard API, diff --git a/examples/system/sysview_tracing/sdkconfig.defaults b/examples/system/sysview_tracing/sdkconfig.defaults index 0593357a28..a555ba9727 100644 --- a/examples/system/sysview_tracing/sdkconfig.defaults +++ b/examples/system/sysview_tracing/sdkconfig.defaults @@ -1,19 +1,20 @@ # 1ms tick period CONFIG_FREERTOS_HZ=1000 # Enable FreeRTOS SystemView Tracing by default -CONFIG_APPTRACE_ENABLE=y -CONFIG_APPTRACE_SV_ENABLE=y -CONFIG_APPTRACE_SV_TS_SOURCE_ESP_TIMER=y -CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE=y +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER=y +CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_IDLE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE=y diff --git a/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt b/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt index 2573075098..f4f7b0740d 100644 --- a/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt +++ b/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "sysview_heap_log.c" - PRIV_REQUIRES app_trace + PRIV_REQUIRES esp_trace INCLUDE_DIRS ".") diff --git a/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c b/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c index 455d013ad2..339083a4b7 100644 --- a/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c +++ b/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c @@ -17,7 +17,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" - +#include "esp_trace.h" static const char *TAG = "example"; diff --git a/examples/system/sysview_tracing_heap_log/sdkconfig.defaults b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults index 97521d048e..a709f86cba 100644 --- a/examples/system/sysview_tracing_heap_log/sdkconfig.defaults +++ b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults @@ -1,24 +1,25 @@ # 1ms tick period CONFIG_FREERTOS_HZ=1000 # Enable application tracing by default +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +CONFIG_ESP_TRACE_TS_SOURCE_GPTIMER=y CONFIG_APPTRACE_DEST_JTAG=y -CONFIG_APPTRACE_ENABLE=y # Enable FreeRTOS SystemView Tracing by default -CONFIG_APPTRACE_SV_ENABLE=y -CONFIG_APPTRACE_SV_TS_SOURCE_GPTIMER=y -CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_IDLE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE=y # Disable color output in logs CONFIG_LOG_COLORS=n # Enable heap tracing to host diff --git a/tools/ci/check_copyright_config.yaml b/tools/ci/check_copyright_config.yaml index 8248680622..1df236acf8 100644 --- a/tools/ci/check_copyright_config.yaml +++ b/tools/ci/check_copyright_config.yaml @@ -223,6 +223,19 @@ zigbee: - Apache-2.0 - LicenseRef-Included +esp_trace: + include: + - components/esp_trace/include/ + - components/esp_trace/adapters/transport/ + - components/esp_trace/adapters/encoder/ + - components/esp_trace/src/core/ + - components/esp_trace/src/ports/ + allowed_licenses: + - Apache-2.0 + - MIT + - CC0-1.0 + + # files matching this section do not perform the check # file patterns starting with ! are negated, meaning files matching them won't match the section. ignore: