From 5ef3a64c0071588f407e0ea3e33ce6f3e83e87e6 Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Wed, 12 Dec 2018 20:35:17 +0300 Subject: [PATCH] sys_view: Adds heap tracing API --- components/app_trace/CMakeLists.txt | 10 +- components/app_trace/Kconfig | 8 ++ components/app_trace/component.mk | 3 +- components/app_trace/heap_trace_tohost.c | 114 ++++++++++++++++++ .../app_trace/include/esp_sysview_trace.h | 80 ++++++++++++ components/app_trace/linker.lf | 7 +- .../app_trace/sys_view/SEGGER/SEGGER_RTT.h | 1 + .../sys_view/SEGGER/SEGGER_SYSVIEW.c | 6 +- .../sys_view/SEGGER/SEGGER_SYSVIEW.h | 2 + .../sys_view/esp32/SEGGER_RTT_esp32.c | 37 +++++- .../sys_view/ext/heap_trace_module.c | 100 +++++++++++++++ components/app_trace/sys_view/ext/logging.c | 34 ++++++ .../sysview_tracing/main/sysview_tracing.c | 9 +- 13 files changed, 399 insertions(+), 12 deletions(-) create mode 100644 components/app_trace/heap_trace_tohost.c create mode 100644 components/app_trace/include/esp_sysview_trace.h create mode 100644 components/app_trace/sys_view/ext/heap_trace_module.c create mode 100644 components/app_trace/sys_view/ext/logging.c diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt index c1b3537ca..46ab5930d 100644 --- a/components/app_trace/CMakeLists.txt +++ b/components/app_trace/CMakeLists.txt @@ -13,11 +13,17 @@ if(CONFIG_SYSVIEW_ENABLE) list(APPEND COMPONENT_SRCS "sys_view/SEGGER/SEGGER_SYSVIEW.c" "sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c" "sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c" - "sys_view/esp32/SEGGER_RTT_esp32.c") + "sys_view/esp32/SEGGER_RTT_esp32.c" + "sys_view/ext/heap_trace_module.c" + "sys_view/ext/logging.c") +endif() + +if(CONFIG_HEAP_TRACING_TOHOST) + list(APPEND COMPONENT_SRCS "heap_trace_tohost.c") endif() set(COMPONENT_REQUIRES) -set(COMPONENT_PRIV_REQUIRES) +set(COMPONENT_PRIV_REQUIRES heap) set(COMPONENT_ADD_LDFRAGMENTS linker.lf) register_component() diff --git a/components/app_trace/Kconfig b/components/app_trace/Kconfig index 064f9cf7c..67387c661 100644 --- a/components/app_trace/Kconfig +++ b/components/app_trace/Kconfig @@ -107,6 +107,14 @@ menu "Application Level Tracing" help Configures maximum supported tasks in sysview debug + config SYSVIEW_BUF_WAIT_TMO + int "Trace buffer wait timeout" + depends on SYSVIEW_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 SYSVIEW_EVT_OVERFLOW_ENABLE bool "Trace Buffer Overflow Event" depends on SYSVIEW_ENABLE diff --git a/components/app_trace/component.mk b/components/app_trace/component.mk index 384a04a76..a17fa814f 100644 --- a/components/app_trace/component.mk +++ b/components/app_trace/component.mk @@ -23,7 +23,8 @@ COMPONENT_SRCDIRS += \ sys_view/SEGGER \ sys_view/Sample/OS \ sys_view/Sample/Config \ - sys_view/esp32 + sys_view/esp32 \ + sys_view/ext else COMPONENT_SRCDIRS += gcov endif diff --git a/components/app_trace/heap_trace_tohost.c b/components/app_trace/heap_trace_tohost.c new file mode 100644 index 000000000..764022aba --- /dev/null +++ b/components/app_trace/heap_trace_tohost.c @@ -0,0 +1,114 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */ +#include "esp_heap_trace.h" +#undef HEAP_TRACE_SRCFILE + +#if CONFIG_SYSVIEW_ENABLE +#include "esp_app_trace.h" +#include "esp_sysview_trace.h" +#endif + +#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH + +#ifdef CONFIG_HEAP_TRACING_TOHOST + +#if !CONFIG_SYSVIEW_ENABLE +#error None of the heap tracing backends is enabled! You must enable SystemView compatible tracing to use this feature. +#endif + +static bool s_tracing; + +esp_err_t heap_trace_init_tohost() +{ + if (s_tracing) { + return ESP_ERR_INVALID_STATE; + } + return ESP_OK; +} + +esp_err_t heap_trace_start(heap_trace_mode_t mode_param) +{ +#if CONFIG_SYSVIEW_ENABLE + esp_err_t ret = esp_sysview_heap_trace_start((uint32_t)-1); + if (ret != ESP_OK) { + return ret; + } +#endif + s_tracing = true; + return ESP_OK; +} + +esp_err_t heap_trace_stop(void) +{ + esp_err_t ret = ESP_ERR_NOT_SUPPORTED; +#if CONFIG_SYSVIEW_ENABLE + ret = esp_sysview_heap_trace_stop(); +#endif + s_tracing = false; + return ret; +} + +esp_err_t heap_trace_resume(void) +{ + return heap_trace_start(HEAP_TRACE_ALL); +} + +size_t heap_trace_get_count(void) +{ + return 0; +} + +esp_err_t heap_trace_get(size_t index, heap_trace_record_t *record) +{ + return ESP_ERR_NOT_SUPPORTED; +} + +void heap_trace_dump(void) +{ + return; +} + +/* Add a new allocation to the heap trace records */ +static IRAM_ATTR void record_allocation(const heap_trace_record_t *record) +{ + if (!s_tracing) { + return; + } +#if CONFIG_SYSVIEW_ENABLE + esp_sysview_heap_trace_alloc(record->address, record->size, record->alloced_by); +#endif +} + +/* record a free event in the heap trace log + + For HEAP_TRACE_ALL, this means filling in the freed_by pointer. + For HEAP_TRACE_LEAKS, this means removing the record from the log. +*/ +static IRAM_ATTR void record_free(void *p, void **callers) +{ + if (!s_tracing) { + return; + } +#if CONFIG_SYSVIEW_ENABLE + esp_sysview_heap_trace_free(p, callers); +#endif +} + +#include "heap_trace.inc" + +#endif /*CONFIG_HEAP_TRACING_TOHOST*/ + diff --git a/components/app_trace/include/esp_sysview_trace.h b/components/app_trace/include/esp_sysview_trace.h new file mode 100644 index 000000000..3cf04f1d2 --- /dev/null +++ b/components/app_trace/include/esp_sysview_trace.h @@ -0,0 +1,80 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef ESP_SYSVIEW_TRACE_H_ +#define ESP_SYSVIEW_TRACE_H_ + +#include +#include "esp_err.h" +#include "SEGGER_RTT.h" // SEGGER_RTT_ESP32_Flush +#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE + +/** + * @brief Flushes remaining data in SystemView trace buffer to host. + * + * @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly. + * + * @return ESP_OK. + */ +static inline esp_err_t esp_sysview_flush(uint32_t tmo) +{ + SEGGER_RTT_ESP32_Flush(0, tmo); + return ESP_OK; +} + +/** + * @brief vprintf-like function to sent log messages to the host. + * + * @param format Address of format string. + * @param args List of arguments. + * + * @return Number of bytes written. + */ +int esp_sysview_vprintf(const char * format, va_list args); + +/** + * @brief Starts SystemView heap tracing. + * + * @param tmo Timeout (in us) to wait for the host to be connected. Use -1 to wait forever. + * + * @return ESP_OK on success, ESP_ERR_TIMEOUT if operation has been timed out. + */ +esp_err_t esp_sysview_heap_trace_start(uint32_t tmo); + +/** + * @brief Stops SystemView heap tracing. + * + * @return ESP_OK. + */ +esp_err_t esp_sysview_heap_trace_stop(void); + +/** + * @brief Sends heap allocation event to the host. + * + * @param addr Address of allocated block. + * @param size Size of allocated block. + * @param callers Pointer to array with callstack addresses. + * Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH. + */ +void esp_sysview_heap_trace_alloc(void *addr, uint32_t size, const void *callers); + +/** + * @brief Sends heap de-allocation event to the host. + * + * @param addr Address of de-allocated block. + * @param callers Pointer to array with callstack addresses. + * Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH. + */ +void esp_sysview_heap_trace_free(void *addr, const void *callers); + +#endif //ESP_SYSVIEW_TRACE_H_ diff --git a/components/app_trace/linker.lf b/components/app_trace/linker.lf index 5494afc00..a10982995 100644 --- a/components/app_trace/linker.lf +++ b/components/app_trace/linker.lf @@ -1,7 +1,12 @@ [mapping] archive: libapp_trace.a entries: - * (noflash) + app_trace (noflash) + app_trace_util (noflash) + SEGGER_SYSVIEW (noflash) + SEGGER_RTT_esp32 (noflash) + SEGGER_SYSVIEW_Config_FreeRTOS (noflash) + SEGGER_SYSVIEW_FreeRTOS (noflash) [mapping] archive: libdriver.a diff --git a/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h b/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h index a4673f5aa..877d6ee33 100644 --- a/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h +++ b/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h @@ -160,6 +160,7 @@ unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const voi unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); void SEGGER_RTT_ESP32_FlushNoLock (unsigned long min_sz, unsigned long tmo); +void SEGGER_RTT_ESP32_Flush (unsigned long min_sz, unsigned long tmo); // // Function macro for performance optimization // diff --git a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.c b/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.c index e0d48aca2..bc21811cc 100644 --- a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.c +++ b/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.c @@ -1689,6 +1689,10 @@ void SEGGER_SYSVIEW_Stop(void) { RECORD_END(); } +U8 SEGGER_SYSVIEW_Started(void) { + return _SYSVIEW_Globals.EnableState; +} + /********************************************************************* * * SEGGER_SYSVIEW_GetSysDesc() @@ -2678,7 +2682,7 @@ void SEGGER_SYSVIEW_ErrorfTarget(const char* s, ...) { void SEGGER_SYSVIEW_Print(const char* s) { U8* pPayload; U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN); + RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN + 3/*1 or 3 bytes for string length*/); // pPayload = _EncodeStr(pPayloadStart, s, SEGGER_SYSVIEW_MAX_STRING_LEN); ENCODE_U32(pPayload, SEGGER_SYSVIEW_LOG); diff --git a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.h b/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.h index 91cc0c6f4..b5b5519d0 100644 --- a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.h +++ b/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.h @@ -230,6 +230,8 @@ void SEGGER_SYSVIEW_GetSysDesc (void); void SEGGER_SYSVIEW_SendTaskList (void); void SEGGER_SYSVIEW_SendTaskInfo (const SEGGER_SYSVIEW_TASKINFO* pInfo); void SEGGER_SYSVIEW_SendSysDesc (const char* sSysDesc); +// Checks whether tracing has been started +U8 SEGGER_SYSVIEW_Started(void); /********************************************************************* * diff --git a/components/app_trace/sys_view/esp32/SEGGER_RTT_esp32.c b/components/app_trace/sys_view/esp32/SEGGER_RTT_esp32.c index 410f303a3..2ee0a4950 100644 --- a/components/app_trace/sys_view/esp32/SEGGER_RTT_esp32.c +++ b/components/app_trace/sys_view/esp32/SEGGER_RTT_esp32.c @@ -16,6 +16,7 @@ #include "freertos/FreeRTOS.h" #include "SEGGER_RTT.h" #include "SEGGER_SYSVIEW.h" +#include "SEGGER_SYSVIEW_Conf.h" #include "esp32/rom/ets_sys.h" #include "esp_app_trace.h" @@ -27,8 +28,12 @@ const static char *TAG = "segger_rtt"; // size of down channel data buf #define SYSVIEW_DOWN_BUF_SIZE 32 -#define SEGGER_HOST_WAIT_TMO 500 //us #define SEGGER_STOP_WAIT_TMO 1000000 //us +#if CONFIG_SYSVIEW_BUF_WAIT_TMO == -1 +#define SEGGER_HOST_WAIT_TMO ESP_APPTRACE_TMO_INFINITE +#else +#define SEGGER_HOST_WAIT_TMO CONFIG_SYSVIEW_BUF_WAIT_TMO +#endif static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ]; static uint16_t s_events_buf_filled; @@ -57,9 +62,12 @@ static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE]; */ void SEGGER_RTT_ESP32_FlushNoLock(unsigned long min_sz, unsigned long tmo) { - esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, tmo); - if (res != ESP_OK) { - ESP_LOGE(TAG, "Failed to flush buffered events (%d)!\n", res); + esp_err_t res; + if (s_events_buf_filled > 0) { + res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, tmo); + if (res != ESP_OK) { + ESP_LOGE(TAG, "Failed to flush buffered events (%d)!\n", res); + } } // flush even if we failed to write buffered events, because no new events will be sent after STOP res = esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, min_sz, tmo); @@ -69,6 +77,27 @@ void SEGGER_RTT_ESP32_FlushNoLock(unsigned long min_sz, unsigned long tmo) s_events_buf_filled = 0; } +/********************************************************************* +* +* SEGGER_RTT_ESP32_Flush() +* +* Function description +* Flushes buffered events. +* +* Parameters +* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only. +* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly. +* +* Return value +* None. +*/ +void SEGGER_RTT_ESP32_Flush(unsigned long min_sz, unsigned long tmo) +{ + SEGGER_SYSVIEW_LOCK(); + SEGGER_RTT_ESP32_FlushNoLock(min_sz, tmo); + SEGGER_SYSVIEW_UNLOCK(); +} + /********************************************************************* * * SEGGER_RTT_ReadNoLock() diff --git a/components/app_trace/sys_view/ext/heap_trace_module.c b/components/app_trace/sys_view/ext/heap_trace_module.c new file mode 100644 index 000000000..3d86f2e64 --- /dev/null +++ b/components/app_trace/sys_view/ext/heap_trace_module.c @@ -0,0 +1,100 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include "SEGGER_SYSVIEW.h" +#include "SEGGER_RTT.h" +#include "esp_app_trace.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "esp_log.h" +const static char *TAG = "sysview_heap_trace"; + +#ifdef CONFIG_HEAP_TRACING_STACK_DEPTH +#define CALLSTACK_SIZE CONFIG_HEAP_TRACING_STACK_DEPTH +#else +#define CALLSTACK_SIZE 0 +#endif + +static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = { + .sModule = "ESP32 SystemView Heap Tracing Module", + .NumEvents = 2, +}; + +static bool s_mod_registered; + + +esp_err_t esp_sysview_heap_trace_start(uint32_t tmo) +{ + uint32_t tmo_ticks = tmo/(1000*portTICK_PERIOD_MS); + + ESP_EARLY_LOGV(TAG, "%s", __func__); + do { + if (tmo != (uint32_t)-1) { + // Currently timeout implementation is simple and has granularity of 1 OS tick, + // so just count down the number of times to call vTaskDelay + if (tmo_ticks-- == 0) { + return ESP_ERR_TIMEOUT; + } + } + vTaskDelay(1); + } while(!SEGGER_SYSVIEW_Started()); + + SEGGER_SYSVIEW_RegisterModule(&s_esp_sysview_heap_module); + s_mod_registered = true; + return ESP_OK; +} + +esp_err_t esp_sysview_heap_trace_stop(void) +{ + ESP_EARLY_LOGV(TAG, "%s", __func__); + SEGGER_RTT_ESP32_Flush(0, ESP_APPTRACE_TMO_INFINITE); + return ESP_OK; +} + +void esp_sysview_heap_trace_alloc(const void *addr, uint32_t size, const void *callers) +{ + U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (2+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32]; + U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket); + U32 *calls = (U32 *)callers; + + if (!s_mod_registered) { + return; + } + ESP_EARLY_LOGV(TAG, "%s %p %lu", __func__, addr, size); + pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr); + pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, size); + for (int i = 0; i < CALLSTACK_SIZE; i++) { + pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]); + } + SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 0); +} + +void esp_sysview_heap_trace_free(const void *addr, const void *callers) +{ + U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (1+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32]; + U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket); + U32 *calls = (U32 *)callers; + + if (!s_mod_registered) { + return; + } + ESP_EARLY_LOGV(TAG, "%s %p", __func__, addr); + pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr); + for (int i = 0; i < CALLSTACK_SIZE; i++) { + pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]); + } + SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 1); +} diff --git a/components/app_trace/sys_view/ext/logging.c b/components/app_trace/sys_view/ext/logging.c new file mode 100644 index 000000000..b7aa5ff10 --- /dev/null +++ b/components/app_trace/sys_view/ext/logging.c @@ -0,0 +1,34 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include "SEGGER_SYSVIEW_Int.h" +#include "freertos/FreeRTOS.h" + +static portMUX_TYPE s_log_mutex = portMUX_INITIALIZER_UNLOCKED; + +int esp_sysview_vprintf(const char * format, va_list args) +{ + static char log_buffer[SEGGER_SYSVIEW_MAX_STRING_LEN]; + + portENTER_CRITICAL(&s_log_mutex); + size_t len = vsnprintf(log_buffer, sizeof(log_buffer), format, args); + if (len > sizeof(log_buffer) - 1) { + log_buffer[sizeof(log_buffer - 1)] = 0; + } + SEGGER_SYSVIEW_Print(log_buffer); + portEXIT_CRITICAL(&s_log_mutex); + return len; +} diff --git a/examples/system/sysview_tracing/main/sysview_tracing.c b/examples/system/sysview_tracing/main/sysview_tracing.c index 3ac03d8da..c422d9e46 100644 --- a/examples/system/sysview_tracing/main/sysview_tracing.c +++ b/examples/system/sysview_tracing/main/sysview_tracing.c @@ -198,9 +198,12 @@ void app_main() #if CONFIG_SYSVIEW_ENABLE && CONFIG_USE_CUSTOM_EVENT_ID // Currently OpenOCD does not support requesting module info from target. So do the following... - // Give SystemView tracing module some time to handle START command from host, - // after that data can be sent to the host using onboard API, so user module description does not need to be requested by OpenOCD itself. - vTaskDelay(1); + // Wait untill SystemView module receives START command from host, + // after that data can be sent to the host using onboard API, + // so user module description does not need to be requested by OpenOCD itself. + while(!SEGGER_SYSVIEW_Started()) { + vTaskDelay(1); + } SEGGER_SYSVIEW_RegisterModule(&s_example_sysview_module); #endif