diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index e2d5b08cd300..13db509922c2 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -45,6 +45,7 @@ watchdog0 = &wdt010; mcuboot-button0 = &button0; mcuboot-led0 = &led0; + rtt-custom-section = &cpuapp_tcm_region; }; buttons { @@ -345,40 +346,38 @@ zephyr_udc0: &usbhs { status = "okay"; }; -/* Trim this RAM block for power management related features. */ &cpuapp_ram0 { - reg = <0x22000000 (DT_SIZE_K(32) - 256)>; - ranges = <0x0 0x22000000 (0x8000 - 0x100)>; -}; + cpuapp_tcm_region: cpuapp_ram0@0 { + compatible = "zephyr,memory-region"; + reg = <0x00000000 (DT_SIZE_K(32) - 256)>; + zephyr,memory-region = "APP_RAM0"; + }; -/ { - soc { - /* cache control functions - must be executed from local SRAM */ - pm_ramfunc: cpuapp_s2ram@22007f00 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x22007f00 192>; - zephyr,memory-region = "PMLocalRamfunc"; - }; + /* cache control functions - must be executed from local SRAM */ + pm_ramfunc: cpuapp_s2ram@7f00 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x00007f00 192>; + zephyr,memory-region = "PMLocalRamfunc"; + }; - /* temporary stack for S2RAM resume logic */ - pm_s2ram_stack: cpuapp_s2ram_stack@22007fc8 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x22007fc8 16>; - zephyr,memory-region = "pm_s2ram_stack"; - }; + /* temporary stack for S2RAM resume logic */ + pm_s2ram_stack: cpuapp_s2ram_stack@7fc8 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x00007fc8 16>; + zephyr,memory-region = "pm_s2ram_stack"; + }; - /* run-time common mcuboot S2RAM support section */ - mcuboot_s2ram: cpuapp_s2ram@22007fd8 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x22007fd8 8>; - zephyr,memory-region = "mcuboot_s2ram_context"; - }; + /* run-time common mcuboot S2RAM support section */ + mcuboot_s2ram: cpuapp_s2ram@7fd8 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x00007fd8 8>; + zephyr,memory-region = "mcuboot_s2ram_context"; + }; - /* run-time common S2RAM cpu context RAM */ - pm_s2ram: cpuapp_s2ram@22007fe0 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x22007fe0 32>; - zephyr,memory-region = "pm_s2ram_context"; - }; + /* run-time common S2RAM cpu context RAM */ + pm_s2ram: cpuapp_s2ram@7fe0 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x00007fe0 32>; + zephyr,memory-region = "pm_s2ram_context"; }; }; diff --git a/drivers/debug/Kconfig.nrf b/drivers/debug/Kconfig.nrf index 030e9885a06d..138a303e7fc3 100644 --- a/drivers/debug/Kconfig.nrf +++ b/drivers/debug/Kconfig.nrf @@ -16,6 +16,53 @@ config DEBUG_NRF_ETR if DEBUG_NRF_ETR +DT_CHOSEN_ZEPHYR_CONSOLE := zephyr,console + +config DEBUG_NRF_ETR_BACKEND_UART + default y if $(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_CONSOLE)) + bool "UART backend" + +config DEBUG_NRF_ETR_BACKEND_RTT + bool "RTT backend" + select USE_SEGGER_RTT + select SEGGER_RTT_CUSTOM_LOCKING + +if DEBUG_NRF_ETR_BACKEND_RTT + +config DEBUG_NRF_ETR_BACKEND_RTT_BUFFER + int "Buffer number used for logger output." + range 0 SEGGER_RTT_MAX_NUM_UP_BUFFERS + default 0 + help + Select index of up-buffer used for logger output, by default it uses + terminal up-buffer and its settings. + +config DEBUG_NRF_ETR_BACKEND_RTT_BUFFER_SIZE + int "Size of reserved up-buffer for logger output." + default 1024 + depends on DEBUG_NRF_ETR_BACKEND_RTT_BUFFER > 0 + help + Specify reserved size of up-buffer used for logger output. + +config DEBUG_NRF_ETR_BACKEND_RTT_RETRY_CNT + int "Number of retries" + default 4 + help + Number of TX retries before dropping the data and assuming that + RTT session is inactive. + +config DEBUG_NRF_ETR_BACKEND_RTT_RETRY_DELAY_MS + int "Delay between TX retries in milliseconds" + default 5 + help + Sleep period between TX retry attempts. During RTT session, host pulls + data periodically. Period starts from 1-2 milliseconds and can be + increased if traffic on RTT increases (also from host to device). In + case of heavy traffic data can be lost and it may be necessary to + increase delay or number of retries. + +endif + config DEBUG_NRF_ETR_DECODE bool "Decode ETR content" default y if LOG_FRONTEND_STMESP_FSC @@ -80,6 +127,7 @@ config DEBUG_NRF_ETR_SHELL select UART_ASYNC_RX_HELPER select SHELL_LOG_BACKEND_CUSTOM depends on DEBUG_NRF_ETR_DECODE + depends on DEBUG_NRF_ETR_BACKEND_UART default y if SHELL help Enable shell with Coresight STM logging support. diff --git a/drivers/debug/debug_nrf_etr.c b/drivers/debug/debug_nrf_etr.c index d536cd4a9f40..9f56fefc0770 100644 --- a/drivers/debug/debug_nrf_etr.c +++ b/drivers/debug/debug_nrf_etr.c @@ -22,6 +22,11 @@ #include #include #include + +#ifdef CONFIG_DEBUG_NRF_ETR_BACKEND_RTT +#include +#endif + LOG_MODULE_REGISTER(cs_etr_tbm); #define UART_NODE DT_CHOSEN(zephyr_console) @@ -79,7 +84,7 @@ static uint32_t etr_rd_idx; /* Counts number of new messages completed in the current formatter frame decoding. */ static uint32_t new_msg_cnt; -static bool volatile use_async_uart; +static bool volatile use_blocking; static struct k_sem uart_sem; static const struct device *uart_dev = DEVICE_DT_GET(UART_NODE); @@ -149,27 +154,101 @@ static shell_transport_handler_t shell_handler; static void *shell_context; #endif +#ifdef CONFIG_DEBUG_NRF_ETR_BACKEND_RTT + +#define RTT_LOCK() \ + COND_CODE_0(CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_BUFFER, (SEGGER_RTT_LOCK()), ()) + +#define RTT_UNLOCK() \ + COND_CODE_0(CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_BUFFER, (SEGGER_RTT_UNLOCK()), ()) + +static uint8_t rtt_buf[COND_CODE_0(CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_BUFFER, (1), + (CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_BUFFER_SIZE))]; + +static volatile bool rtt_host_present; + +static void rtt_on_failed_write(int retry_cnt, bool in_panic) +{ + if (retry_cnt == 0) { + rtt_host_present = false; + } else if (in_panic) { + k_busy_wait(USEC_PER_MSEC * CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_RETRY_DELAY_MS); + } else { + k_msleep(CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_RETRY_DELAY_MS); + } +} + +static void rtt_on_write(int retry_cnt, bool in_panic) +{ + rtt_host_present = true; + if (use_blocking) { + /* In panic mode block on each write until host reads it. This + * way it is ensured that if system resets all messages are read + * by the host. While pending on data being read by the host we + * must also detect situation where host is disconnected. + */ + while (SEGGER_RTT_HasDataUp(CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_BUFFER)) { + rtt_on_failed_write(retry_cnt--, in_panic); + } + } + +} + +static void rtt_write(uint8_t *data, size_t length, bool in_panic) +{ + int ret = 0; + int retry_cnt = CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_RETRY_CNT; + + do { + if (!in_panic) { + RTT_LOCK(); + ret = SEGGER_RTT_WriteSkipNoLock(CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_BUFFER, + data, length); + RTT_UNLOCK(); + } else { + ret = SEGGER_RTT_WriteSkipNoLock(CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_BUFFER, + data, length); + } + + if (ret) { + rtt_on_write(retry_cnt, in_panic); + } else if (rtt_host_present) { + retry_cnt--; + rtt_on_failed_write(retry_cnt, in_panic); + } else { + } + } while ((ret == 0) && rtt_host_present); +} +#endif /* CONFIG_DEBUG_NRF_ETR_BACKEND_RTT */ + static int log_output_func(uint8_t *buf, size_t size, void *ctx) { - if (use_async_uart) { - int err; - static uint8_t *tx_buf = (uint8_t *)frame_buf0; + ARG_UNUSED(ctx); - err = k_sem_take(&uart_sem, K_FOREVER); - __ASSERT_NO_MSG(err >= 0); + if (IS_ENABLED(CONFIG_DEBUG_NRF_ETR_BACKEND_UART)) { + if (use_blocking) { + for (int i = 0; i < size; i++) { + uart_poll_out(uart_dev, buf[i]); + } + } else { + int err; + static uint8_t *tx_buf = (uint8_t *)frame_buf0; - memcpy(tx_buf, buf, size); + err = k_sem_take(&uart_sem, K_FOREVER); + __ASSERT_NO_MSG(err >= 0); - err = uart_tx(uart_dev, tx_buf, size, SYS_FOREVER_US); - __ASSERT_NO_MSG(err >= 0); + memcpy(tx_buf, buf, size); - tx_buf = (tx_buf == (uint8_t *)frame_buf0) ? - (uint8_t *)frame_buf1 : (uint8_t *)frame_buf0; - } else { - for (int i = 0; i < size; i++) { - uart_poll_out(uart_dev, buf[i]); + err = uart_tx(uart_dev, tx_buf, size, SYS_FOREVER_US); + __ASSERT_NO_MSG(err >= 0); + + tx_buf = (tx_buf == (uint8_t *)frame_buf0) ? + (uint8_t *)frame_buf1 : (uint8_t *)frame_buf0; } } +#ifdef CONFIG_DEBUG_NRF_ETR_BACKEND_RTT + rtt_write(buf, size, use_blocking); +#endif return size; } @@ -528,16 +607,16 @@ static void dump_frame(uint8_t *buf) { int err; - if (use_async_uart) { + if (use_blocking) { + for (int i = 0; i < CORESIGHT_TRACE_FRAME_SIZE; i++) { + uart_poll_out(uart_dev, buf[i]); + } + } else { err = k_sem_take(&uart_sem, K_FOREVER); __ASSERT_NO_MSG(err >= 0); err = uart_tx(uart_dev, buf, CORESIGHT_TRACE_FRAME_SIZE, SYS_FOREVER_US); __ASSERT_NO_MSG(err >= 0); - } else { - for (int i = 0; i < CORESIGHT_TRACE_FRAME_SIZE; i++) { - uart_poll_out(uart_dev, buf[i]); - } } } @@ -593,7 +672,7 @@ static void process(void) } } else { dump_frame((uint8_t *)frame_buf); - frame_buf = (use_async_uart && (frame_buf == frame_buf0)) ? + frame_buf = (!use_blocking && (frame_buf == frame_buf0)) ? frame_buf1 : frame_buf0; } } @@ -649,7 +728,7 @@ void debug_nrf_etr_flush(void) /* Set flag which forces uart to use blocking polling out instead of * asynchronous API. */ - use_async_uart = false; + use_blocking = true; uint32_t k = irq_lock(); /* Repeat arbitrary number of times to ensure that all that is flushed. */ @@ -754,17 +833,23 @@ static void tbm_event_handler(nrf_tbm_event_t event) int etr_process_init(void) { +#ifdef CONFIG_DEBUG_NRF_ETR_BACKEND_RTT + if (CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_BUFFER > 0) { + SEGGER_RTT_ConfigUpBuffer(CONFIG_DEBUG_NRF_ETR_BACKEND_RTT_BUFFER, "stm_logger", + rtt_buf, sizeof(rtt_buf), + SEGGER_RTT_MODE_NO_BLOCK_SKIP); + } +#endif int err; - k_sem_init(&uart_sem, 1, 1); - - err = uart_callback_set(uart_dev, uart_event_handler, NULL); - use_async_uart = (err == 0); - + if (IS_ENABLED(CONFIG_DEBUG_NRF_ETR_BACKEND_UART)) { + err = uart_callback_set(uart_dev, uart_event_handler, NULL); + use_blocking = (err != 0); + k_sem_init(&uart_sem, 1, 1); + } static const nrfx_tbm_config_t config = {.size = wsize_mask}; nrfx_tbm_init(&config, tbm_event_handler); - IRQ_CONNECT(DT_IRQN(DT_NODELABEL(tbm)), DT_IRQ(DT_NODELABEL(tbm), priority), nrfx_isr, nrfx_tbm_irq_handler, 0); irq_enable(DT_IRQN(DT_NODELABEL(tbm))); diff --git a/modules/segger/Kconfig b/modules/segger/Kconfig index ca2d27d4bcf1..0e592fe860d3 100644 --- a/modules/segger/Kconfig +++ b/modules/segger/Kconfig @@ -97,6 +97,8 @@ config SEGGER_RTT_SECTION_CUSTOM config SEGGER_RTT_SECTION_CUSTOM_DTS_REGION bool "Place RTT data in custom linker section defined by a memory region in DTS" + help + The DTS memory section needs to have the "rtt_custom_section" alias. endif diff --git a/samples/boards/nordic/coresight_stm/sample.yaml b/samples/boards/nordic/coresight_stm/sample.yaml index 9ff835d8ffad..10f1d153855a 100644 --- a/samples/boards/nordic/coresight_stm/sample.yaml +++ b/samples/boards/nordic/coresight_stm/sample.yaml @@ -41,6 +41,17 @@ tests: - SB_CONFIG_APP_CPUPPR_RUN=y - SB_CONFIG_APP_CPUFLPR_RUN=y + sample.boards.nrf.coresight_stm.rtt: + required_snippets: + - nordic-log-stm + extra_configs: + - CONFIG_DEBUG_NRF_ETR_BACKEND_RTT=y + - CONFIG_DEBUG_NRF_ETR_BACKEND_UART=n + - CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=8192 + extra_args: + - SB_CONFIG_APP_CPUPPR_RUN=y + - SB_CONFIG_APP_CPUFLPR_RUN=y + sample.boards.nrf.coresight_stm.local_uart: harness: console harness_config: diff --git a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp index 86149e5bd0e0..9566d253b98e 100644 --- a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp +++ b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp @@ -17,4 +17,8 @@ config POWER_DOMAIN config CODE_DATA_RELOCATION default y if (PM || POWEROFF) && !MCUBOOT +choice SEGGER_RTT_SECTION + default SEGGER_RTT_SECTION_CUSTOM_DTS_REGION +endchoice + endif # SOC_NRF54H20_CPUAPP diff --git a/tests/arch/arm/arm_interrupt/testcase.yaml b/tests/arch/arm/arm_interrupt/testcase.yaml index df47b02fccd9..5836a20b9565 100644 --- a/tests/arch/arm/arm_interrupt/testcase.yaml +++ b/tests/arch/arm/arm_interrupt/testcase.yaml @@ -17,6 +17,7 @@ tests: - CONFIG_IDLE_STACK_SIZE=512 - CONFIG_MAIN_STACK_SIZE=2048 - CONFIG_ZTEST_STACK_SIZE=1280 + - CONFIG_KOBJECT_TEXT_AREA=32768 arch.arm.interrupt.extra_exception_info: filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE extra_configs: diff --git a/tests/arch/arm/arm_thread_swap/testcase.yaml b/tests/arch/arm/arm_thread_swap/testcase.yaml index e26d88429050..b60ad6f705d8 100644 --- a/tests/arch/arm/arm_thread_swap/testcase.yaml +++ b/tests/arch/arm/arm_thread_swap/testcase.yaml @@ -14,6 +14,7 @@ tests: - CONFIG_ZTEST_WARN_NO_OPTIMIZATIONS=n - CONFIG_IDLE_STACK_SIZE=512 - CONFIG_MAIN_STACK_SIZE=2048 + - CONFIG_KOBJECT_TEXT_AREA=32768 min_flash: 192 arch.arm.swap.common.fpu_sharing: filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE and CONFIG_ARMV7_M_ARMV8_M_FP @@ -29,4 +30,5 @@ tests: - CONFIG_ZTEST_WARN_NO_OPTIMIZATIONS=n - CONFIG_IDLE_STACK_SIZE=512 - CONFIG_MAIN_STACK_SIZE=2048 + - CONFIG_KOBJECT_TEXT_AREA=32768 min_flash: 192 diff --git a/west.yml b/west.yml index 26335c8499e0..31082f0ff552 100644 --- a/west.yml +++ b/west.yml @@ -354,7 +354,7 @@ manifest: path: modules/lib/picolibc revision: 560946f26db075c296beea5b39d99e6de43c9010 - name: segger - revision: cf56b1d9c80f81a26e2ac5727c9cf177116a4692 + revision: 7c843ea24b9b4f100c226bce0b4eb807e50a42ac path: modules/debug/segger groups: - debug