From 372cc6e5ae2b053e2edaa4ded680d032ce7f0390 Mon Sep 17 00:00:00 2001 From: Karsten Koenig Date: Thu, 15 May 2025 12:29:32 +0200 Subject: [PATCH 1/3] soc: nordic: ironside: Add TDD Added support for the IronSide TDD service which allows configuring and powering the trace and debug domain of the nrf54h20. Also provide option to start the trace and debug domain in the soc start sequence. Signed-off-by: Karsten Koenig --- soc/nordic/ironside/CMakeLists.txt | 1 + soc/nordic/ironside/Kconfig | 6 +++ .../ironside/include/nrf_ironside/tdd.h | 38 +++++++++++++++++++ soc/nordic/ironside/tdd.c | 28 ++++++++++++++ soc/nordic/nrf54h/Kconfig | 13 ++++++- soc/nordic/nrf54h/soc.c | 22 +++++++++-- 6 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 soc/nordic/ironside/include/nrf_ironside/tdd.h create mode 100644 soc/nordic/ironside/tdd.c diff --git a/soc/nordic/ironside/CMakeLists.txt b/soc/nordic/ironside/CMakeLists.txt index cf68e8a13529e..98e721541d7f3 100644 --- a/soc/nordic/ironside/CMakeLists.txt +++ b/soc/nordic/ironside/CMakeLists.txt @@ -6,5 +6,6 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CALL call.c) zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_BOOT_REPORT boot_report.c) zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CPUCONF_SERVICE cpuconf.c) +zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_TDD_SERVICE tdd.c) zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_UPDATE_SERVICE update.c) zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_DVFS_SERVICE dvfs.c) diff --git a/soc/nordic/ironside/Kconfig b/soc/nordic/ironside/Kconfig index 59f63f4c022bb..6eeacf0677180 100644 --- a/soc/nordic/ironside/Kconfig +++ b/soc/nordic/ironside/Kconfig @@ -37,6 +37,12 @@ config NRF_IRONSIDE_CPUCONF_SERVICE help Service used to boot local domain cores. +config NRF_IRONSIDE_TDD_SERVICE + bool "IronSide TDD service" + select NRF_IRONSIDE_CALL + help + Service used to control the trace and debug domain. + config NRF_IRONSIDE_UPDATE_SERVICE bool "IronSide update service" select NRF_IRONSIDE_CALL diff --git a/soc/nordic/ironside/include/nrf_ironside/tdd.h b/soc/nordic/ironside/include/nrf_ironside/tdd.h new file mode 100644 index 0000000000000..d065b1619a685 --- /dev/null +++ b/soc/nordic/ironside/include/nrf_ironside/tdd.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_TDD_H_ +#define ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_TDD_H_ + +#include + +#include + +#define IRONSIDE_SE_TDD_SERVICE_ERROR_INVALID_CONFIG (1) + +#define IRONSIDE_SE_CALL_ID_TDD_V0 4 + +#define IRONSIDE_SE_TDD_SERVICE_REQ_CONFIG_IDX 0 +#define IRONSIDE_SE_TDD_SERVICE_RSP_RETCODE_IDX 0 + +enum ironside_se_tdd_config { + RESERVED0 = 0, /* Reserved */ + /** Turn off the TDD */ + IRONSIDE_SE_TDD_CONFIG_OFF = 1, + /** Turn on the TDD with default configuration */ + IRONSIDE_SE_TDD_CONFIG_ON_DEFAULT = 2, +}; + +/** + * @brief Control the Trace and Debug Domain (TDD). + * + * @param config The configuration to be applied. + * + * @retval 0 on success. + * @retval -IRONSIDE_SE_TDD_ERROR_EINVAL on invalid argument. + */ +int ironside_se_tdd_configure(const enum ironside_se_tdd_config config); + +#endif /* ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_TDD_H_ */ diff --git a/soc/nordic/ironside/tdd.c b/soc/nordic/ironside/tdd.c new file mode 100644 index 0000000000000..eee5691cf362b --- /dev/null +++ b/soc/nordic/ironside/tdd.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +int ironside_se_tdd_configure(const enum ironside_se_tdd_config config) +{ + int err; + struct ironside_call_buf *const buf = ironside_call_alloc(); + + buf->id = IRONSIDE_SE_CALL_ID_TDD_V0; + buf->args[IRONSIDE_SE_TDD_SERVICE_REQ_CONFIG_IDX] = (uint32_t)config; + + ironside_call_dispatch(buf); + + if (buf->status == IRONSIDE_CALL_STATUS_RSP_SUCCESS) { + err = buf->args[IRONSIDE_SE_TDD_SERVICE_RSP_RETCODE_IDX]; + } else { + err = buf->status; + } + + ironside_call_release(buf); + + return err; +} diff --git a/soc/nordic/nrf54h/Kconfig b/soc/nordic/nrf54h/Kconfig index 7889287b4a4b4..56b64f293baf4 100644 --- a/soc/nordic/nrf54h/Kconfig +++ b/soc/nordic/nrf54h/Kconfig @@ -8,7 +8,6 @@ config SOC_SERIES_NRF54HX select HAS_NRFX select HAS_NORDIC_DRIVERS select SOC_EARLY_INIT_HOOK if ARM - select SOC_LATE_INIT_HOOK if SOC_NRF54H20_CPURAD_ENABLE select NRF_PLATFORM_HALTIUM select EXPERIMENTAL if MCUBOOT @@ -68,11 +67,23 @@ config SOC_NRF54H20_CPURAD_COMMON select HAS_PM select HAS_POWEROFF +config SOC_NRF54H20_TDD_ENABLE + bool "Power and configure the trace and debug domain (TDD)" + depends on SOC_NRF54H20_CPUAPP + select NRF_IRONSIDE_TDD_SERVICE + select SOC_LATE_INIT_HOOK + help + This will at application boot time request that the trace and + debug domain (TDD) is powered up and configured. + This allows configuring the coresight peripherals from + the application domain. + config SOC_NRF54H20_CPURAD_ENABLE bool "Boot the nRF54H20 Radio core" default y if NRF_802154_SER_HOST || BT_HCI_HOST depends on SOC_NRF54H20_CPUAPP select NRF_IRONSIDE_CPUCONF_SERVICE + select SOC_LATE_INIT_HOOK help This will at application boot time enable clock to the Radiocore, and also power will be requested to the Radiocore diff --git a/soc/nordic/nrf54h/soc.c b/soc/nordic/nrf54h/soc.c index 5f52a091fa845..d51ade98911ab 100644 --- a/soc/nordic/nrf54h/soc.c +++ b/soc/nordic/nrf54h/soc.c @@ -26,6 +26,9 @@ #if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE) #include #endif +#if defined(CONFIG_SOC_NRF54H20_TDD_ENABLE) +#include +#endif LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); @@ -171,10 +174,19 @@ void soc_early_init_hook(void) } } -#if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE) +#if defined(CONFIG_SOC_LATE_INIT_HOOK) + void soc_late_init_hook(void) { - int err; +#if defined(CONFIG_SOC_NRF54H20_TDD_ENABLE) + int err_tdd; + + err_tdd = ironside_se_tdd_configure(IRONSIDE_SE_TDD_CONFIG_ON_DEFAULT); + __ASSERT(err_tdd == 0, "err_tdd was %d", err_tdd); +#endif + +#if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE) + int err_cpuconf; /* The msg will be used for communication prior to IPC * communication being set up. But at this moment no such @@ -213,8 +225,10 @@ void soc_late_init_hook(void) /* Don't wait as this is not yet supported. */ bool cpu_wait = false; - err = ironside_cpuconf(NRF_PROCESSOR_RADIOCORE, radiocore_address, cpu_wait, msg, msg_size); - __ASSERT(err == 0, "err was %d", err); + err_cpuconf = ironside_cpuconf(NRF_PROCESSOR_RADIOCORE, radiocore_address, cpu_wait, msg, + msg_size); + __ASSERT(err_cpuconf == 0, "err_cpuconf was %d", err_cpuconf); +#endif } #endif From d51bc756ee52a0fe4f202ed4803e6e1a509bf30f Mon Sep 17 00:00:00 2001 From: Karsten Koenig Date: Sat, 28 Jun 2025 12:35:19 +0200 Subject: [PATCH 2/3] soc: nrf54h: Configure CTRLSEL and pin for TRACE Configure the CTRLSEL value and the clock pin so that the TRACE pins work when the TDD gets used. Signed-off-by: Karsten Koenig --- soc/nordic/nrf54h/soc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/soc/nordic/nrf54h/soc.c b/soc/nordic/nrf54h/soc.c index d51ade98911ab..a20815b2227ed 100644 --- a/soc/nordic/nrf54h/soc.c +++ b/soc/nordic/nrf54h/soc.c @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE) #include @@ -183,6 +184,13 @@ void soc_late_init_hook(void) err_tdd = ironside_se_tdd_configure(IRONSIDE_SE_TDD_CONFIG_ON_DEFAULT); __ASSERT(err_tdd == 0, "err_tdd was %d", err_tdd); + + UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 3, GPIO_PIN_CNF_CTRLSEL_TND); + UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 4, GPIO_PIN_CNF_CTRLSEL_TND); + UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 5, GPIO_PIN_CNF_CTRLSEL_TND); + UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 6, GPIO_PIN_CNF_CTRLSEL_TND); + UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 7, GPIO_PIN_CNF_CTRLSEL_TND); + #endif #if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE) From f9b516d61490c2ba07f3c18cf3e5b4caa0e27d9b Mon Sep 17 00:00:00 2001 From: Karsten Koenig Date: Mon, 30 Jun 2025 11:56:31 +0200 Subject: [PATCH 3/3] boards: nordic: nrf54h20dk: Add ETM to JLinkScript Added support for ETM tracing via TPIU to the JLinkScript. Signed-off-by: Karsten Koenig --- .../support/nrf54h20_cpuapp.JLinkScript | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript b/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript index b1b968573991f..9738ec77f4372 100644 --- a/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript +++ b/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript @@ -1,6 +1,175 @@ __constant U32 _CPUCONF_ADDR = 0x52011000; __constant U32 _CPUCONF_CPUWAIT_OFFSET = 0x50C; +// ATBFUNNEL +__constant U32 _ATBFUNNEL211_ADDR = 0xBF04D000; +__constant U32 _ATBFUNNEL212_ADDR = 0xBF04E000; +__constant U32 _ATBFUNNEL_CTRLREG_OFFSET = 0x0; +__constant U32 _HOLDTIME_4 = 0x300; +__constant U32 _ENS0 = 0x1; +__constant U32 _ENS1 = 0x2; +__constant U32 _ENS2 = 0x4; + +// ATBREPLICATOR +__constant U32 _ATBREPLICATOR212_ADDR = 0xBF04A000; +__constant U32 _ATBREPLICATOR213_ADDR = 0xBF04B000; +__constant U32 _ATBREPLICATOR_IDFILTER0_OFFSET = 0x0; +__constant U32 _ATBREPLICATOR_IDFILTER1_OFFSET = 0x4; +__constant U32 _ID_NONE = 0xFFFFFFFF; +__constant U32 _ID1x = 0xFFFFFFFD; + +// TSGEN +__constant U32 _TSGEN_ADDR = 0xBF041000; +__constant U32 _TSGEN_CNTCR_OFFSET = 0x0; +__constant U32 _TSGEN_CNTFID0_OFFSET = 0x20; +// Clock rate = TDD Freq. / 8 +__constant U32 _TS_CLOCKRATE = 40000000; + +// CTI +__constant U32 _CTI210_ADDR = 0xBF046000; +__constant U32 _CTICONTROL_OFFSET = 0x0; +__constant U32 _CTIOUTEN_OFFSET = 0xA0; +__constant U32 _CTIGATE_OFFSET = 0x140; +__constant U32 _TPIU_FLUSH_TRIG = 0x2; + +// TPIU +__constant U32 _TPIU_ADDR = 0xBF043000; +__constant U32 _CURRENTPORTSIZE_OFFSET = 0x4; +__constant U32 _FFCR_OFFSET = 0x304; +__constant U32 _FSCR_OFFSET = 0x308; +__constant U32 _ENFCONT = 0x02; +__constant U32 _FONFLIN = 0x10; +__constant U32 _ENFTC = 0x1; +__constant U32 _TPIU_SYNC_FRAME_COUNT = 0x8; +__constant U32 _CURRENTPORTSIZE_4 = 0x8; + +// TDDCONF +__constant U32 _TDDCONF_ADDR = 0xBF001000; +__constant U32 _TRACEPORTSPEED_OFFSET = 0x408; +__constant U32 _SPEED80MHZ = 0x0; + +// CoreSight general +__constant U32 _CORESIGHT_CLAIMSET_OFFSET = 0xFA0; +__constant U32 _CORESIGHT_CLAIMCLR_OFFSET = 0xFA4; +__constant U32 _CORESIGHT_LAR_OFFSET = 0xFB0; +__constant U32 _CORESIGHT_UNLOCK_KEY = 0xC5ACCE55; + +// GPIO P7 +__constant U32 _P7_ADDR = 0x5F938E00; +__constant U32 _PIN_CNF3_OFFSET = 0x8C; +__constant U32 _PIN_CNF4_OFFSET = 0x90; +__constant U32 _PIN_CNF5_OFFSET = 0x94; +__constant U32 _PIN_CNF6_OFFSET = 0x98; +__constant U32 _PIN_CNF7_OFFSET = 0x9C; +__constant U32 _PIN_CNF_TPIU_CLOCK_VALUE = 0x80000503; +__constant U32 _PIN_CNF_TPIU_DATA_VALUE = 0x00000503; + +// Settings +__constant U32 _DEBUGGER_CLAIM_MASK = 0x2; + +// Used to check if we have already set up tracing +int _needCoresightSetup = 1; + +// Unlock a CoreSight peripheral +void _CSUnlock(U32 addr) +{ + JLINK_MEM_WriteU32(addr + _CORESIGHT_LAR_OFFSET, _CORESIGHT_UNLOCK_KEY); +} + +// Lock a CoreSight peripheral +void _CSLock(U32 addr) +{ + JLINK_MEM_WriteU32(addr + _CORESIGHT_LAR_OFFSET, 0); +} + +// Set claim bits in the CoreSight peripheral to indicate to the firmware that it +// has been configured by the host debugger +void _CSClaim(U32 addr) +{ + JLINK_MEM_WriteU32(addr + _CORESIGHT_CLAIMSET_OFFSET, _DEBUGGER_CLAIM_MASK); +} + +// Set up CoreSight and other necessary configuration so to enable ETM -> TPIU tracing. +int _SetupETMTPIUTrace(void) +{ + // Set up ATB funnels/replicators to route ApplicationDomain ETM to TPIU + _CSUnlock(_ATBFUNNEL212_ADDR); + JLINK_MEM_WriteU32(_ATBFUNNEL212_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, _HOLDTIME_4 | _ENS0); + _CSClaim(_ATBFUNNEL212_ADDR); + _CSLock(_ATBFUNNEL212_ADDR); + + _CSUnlock(_ATBREPLICATOR212_ADDR); + JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, _ID_NONE); + JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, _ID1x); + _CSLock(_ATBREPLICATOR212_ADDR); + _CSClaim(_ATBREPLICATOR212_ADDR); + _CSLock(_ATBREPLICATOR212_ADDR); + + _CSUnlock(_ATBFUNNEL211_ADDR); + JLINK_MEM_WriteU32(_ATBFUNNEL211_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, _HOLDTIME_4 | _ENS0); + _CSClaim(_ATBFUNNEL211_ADDR); + _CSLock(_ATBFUNNEL211_ADDR); + + _CSUnlock(_ATBREPLICATOR213_ADDR); + JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, _ID1x); + JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, _ID_NONE); + _CSClaim(_ATBREPLICATOR213_ADDR); + _CSLock(_ATBREPLICATOR213_ADDR); + + // Configure timestamp generator for the correct clock rate + JLINK_MEM_WriteU32(_TSGEN_ADDR + _TSGEN_CNTFID0_OFFSET, _TS_CLOCKRATE); + JLINK_MEM_WriteU32(_TSGEN_ADDR + _TSGEN_CNTCR_OFFSET, 1); + _CSClaim(_TSGEN_ADDR); + + // Configure CTI1 for TPIU formatter flushing + _CSUnlock(_CTI210_ADDR); + JLINK_MEM_WriteU32(_CTI210_ADDR + _CTIOUTEN_OFFSET, _TPIU_FLUSH_TRIG); + JLINK_MEM_WriteU32(_CTI210_ADDR + _CTIGATE_OFFSET, _TPIU_FLUSH_TRIG); + JLINK_MEM_WriteU32(_CTI210_ADDR + _CTICONTROL_OFFSET, 1); + _CSClaim(_CTI210_ADDR); + _CSLock(_CTI210_ADDR); + + // Configure TPIU for port size 4, continuous formatting + _CSUnlock(_TPIU_ADDR); + JLINK_MEM_WriteU32(_TPIU_ADDR + _CURRENTPORTSIZE_OFFSET, _CURRENTPORTSIZE_4); + JLINK_MEM_WriteU32(_TPIU_ADDR + _FFCR_OFFSET, _ENFCONT | _FONFLIN | _ENFTC); + JLINK_MEM_WriteU32(_TPIU_ADDR + _FSCR_OFFSET, _TPIU_SYNC_FRAME_COUNT); + _CSClaim(_TPIU_ADDR); + _CSLock(_TPIU_ADDR); + + // Configure the trace pins + JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF3_OFFSET, _PIN_CNF_TPIU_CLOCK_VALUE); + JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF4_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); + JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF5_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); + JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF6_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); + JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF7_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); + + return 0; +} + +int ConfigTargetSettings(void) +{ + JLINK_ExecCommand("CORESIGHT_AddAP = Index=0 Type=AHB-AP"); + CORESIGHT_IndexAHBAPToUse = 0; + + // Adjust trace sample delay to compensate for timing when using 320MHz + JLINK_ExecCommand("TraceSampleAdjust TD = 1000"); + + return 0; +} + +int OnTraceStart(void) +{ + // Set up CoreSight if not already configured + if (_needCoresightSetup) { + _SetupETMTPIUTrace(); + _needCoresightSetup = 0; + } + + return 0; +} + + int SetupTarget(void) { JLINK_TARGET_Halt();