From f23b49f190e6ebc630932361ee2f6dcdbbf8803a Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Sat, 29 Nov 2025 09:46:35 +0100 Subject: [PATCH 001/155] tests: lib: location: Fix cmock generation Exclude Wi-Fi function, that caused cmock generation failure. The function caused issues as it contains argument which type is conditionally hidden behind Kconfig. Signed-off-by: Robert Lubos --- tests/lib/location/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/lib/location/CMakeLists.txt b/tests/lib/location/CMakeLists.txt index 0aa8ff5b6ca7..6faec8e9dc0e 100644 --- a/tests/lib/location/CMakeLists.txt +++ b/tests/lib/location/CMakeLists.txt @@ -56,6 +56,8 @@ cmock_handle(${ZEPHYR_BASE}/include/zephyr/net/wifi_mgmt.h FUNC_EXCLUDE "NET_MGMT_DEFINE_REQUEST_HANDLER" FUNC_EXCLUDE "BUILD_ASSERT" FUNC_EXCLUDE "offsetof" + FUNC_EXCLUDE ".*wifi_mgmt_raise_p2p_device_found_event" + WORD_EXCLUDE ".*wifi_mgmt_raise_p2p_device_found_event.*" ) cmock_handle(${ZEPHYR_BASE}/include/zephyr/device.h FUNC_EXCLUDE ".*DEVICE_DT_NAME_GET" From 2da9a08d512135bbd79ded7e9379a6df49bc1590 Mon Sep 17 00:00:00 2001 From: Bartosz Miller Date: Fri, 28 Nov 2025 14:25:01 +0100 Subject: [PATCH 002/155] tests: drivers: spi: Bring back updated (NRFX 4.0) MLTPAN-55 test This PAN test has been updated to comply with NRFX 4.0 Signed-off-by: Bartosz Miller --- .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 12 ++- .../boards/nrf54l15dk_nrf54l15_cpuapp.overlay | 10 ++- .../nrf54lm20dk_nrf54lm20a_cpuapp.overlay | 10 ++- .../nrf54ls05dk_nrf54ls05b_cpuapp.overlay | 10 ++- .../nrf54lv10dk_nrf54lv10a_cpuapp.overlay | 10 ++- tests/drivers/spi/spim_pan/prj.conf | 3 + tests/drivers/spi/spim_pan/src/main.c | 86 +++++++++++++++++-- 7 files changed, 130 insertions(+), 11 deletions(-) diff --git a/tests/drivers/spi/spim_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/spi/spim_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 4f000ae90a99..16abf5199ac6 100644 --- a/tests/drivers/spi/spim_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/spi/spim_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -41,10 +41,20 @@ dut_spi: &spi130 { dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; - spi-max-frequency = ; + spi-max-frequency = ; }; }; &exmif { status = "disabled"; }; + +tst_timer: &timer131 { + status = "okay"; +}; + +&dppic133 { + owned-channels = <1>; + sink-channels = <1>; + status = "okay"; + }; diff --git a/tests/drivers/spi/spim_pan/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/spi/spim_pan/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index 4d44f1b97039..b3b8b57096a8 100644 --- a/tests/drivers/spi/spim_pan/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/spi/spim_pan/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -40,10 +40,18 @@ dut_spi: &spi21 { dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; - spi-max-frequency = ; + spi-max-frequency = ; }; }; &gpio1 { status = "okay"; }; + +tst_timer: &timer20 { + status = "okay"; +}; + +&dppic20 { + status = "okay"; +}; diff --git a/tests/drivers/spi/spim_pan/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/spi/spim_pan/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index f53d97531b47..e8996c45b817 100644 --- a/tests/drivers/spi/spim_pan/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay +++ b/tests/drivers/spi/spim_pan/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -40,10 +40,18 @@ dut_spi: &spi21 { dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; - spi-max-frequency = ; + spi-max-frequency = ; }; }; &gpio1 { status = "okay"; }; + +tst_timer: &timer20 { + status = "okay"; +}; + +&dppic20 { + status = "okay"; +}; diff --git a/tests/drivers/spi/spim_pan/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay b/tests/drivers/spi/spim_pan/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay index 93ce94a4d86e..04f3533fc633 100644 --- a/tests/drivers/spi/spim_pan/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay +++ b/tests/drivers/spi/spim_pan/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay @@ -40,10 +40,18 @@ dut_spi: &spi21 { dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; - spi-max-frequency = ; + spi-max-frequency = ; }; }; &gpio1 { status = "okay"; }; + +tst_timer: &timer20 { + status = "okay"; +}; + +&dppic20 { + status = "okay"; +}; diff --git a/tests/drivers/spi/spim_pan/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay b/tests/drivers/spi/spim_pan/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay index 93ce94a4d86e..04f3533fc633 100644 --- a/tests/drivers/spi/spim_pan/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay +++ b/tests/drivers/spi/spim_pan/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay @@ -40,10 +40,18 @@ dut_spi: &spi21 { dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; - spi-max-frequency = ; + spi-max-frequency = ; }; }; &gpio1 { status = "okay"; }; + +tst_timer: &timer20 { + status = "okay"; +}; + +&dppic20 { + status = "okay"; +}; diff --git a/tests/drivers/spi/spim_pan/prj.conf b/tests/drivers/spi/spim_pan/prj.conf index 2358254598b3..5e49c0fe6f2b 100644 --- a/tests/drivers/spi/spim_pan/prj.conf +++ b/tests/drivers/spi/spim_pan/prj.conf @@ -1,3 +1,6 @@ CONFIG_SPI=y CONFIG_ZTEST=y + +CONFIG_NRFX_TIMER=y +CONFIG_NRFX_GPPI=y diff --git a/tests/drivers/spi/spim_pan/src/main.c b/tests/drivers/spi/spim_pan/src/main.c index 68689e228d63..5b042c2a093b 100644 --- a/tests/drivers/spi/spim_pan/src/main.c +++ b/tests/drivers/spi/spim_pan/src/main.c @@ -8,15 +8,21 @@ #include #include #include +#include #include -#define SPI_MODE (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB) +#include +#include -#define TEST_BUFFER_SIZE 8 +/* SPI MODE 0 */ +#define SPI_MODE (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB) +#define TEST_BUFFER_SIZE 64 static struct spi_dt_spec spim_spec = SPI_DT_SPEC_GET(DT_NODELABEL(dut_spi_dt), SPI_MODE, 0); NRF_SPIM_Type *spim_reg = (NRF_SPIM_Type *)DT_REG_ADDR(DT_NODELABEL(dut_spi)); +static nrfx_timer_t test_timer = NRFX_TIMER_INSTANCE(DT_REG_ADDR(DT_NODELABEL(tst_timer))); + #define MEMORY_SECTION(node) \ COND_CODE_1(DT_NODE_HAS_PROP(node, memory_regions), \ (__attribute__((__section__( \ @@ -39,15 +45,31 @@ static void set_buffers(void) memset(rx_buffer, 0xFF, TEST_BUFFER_SIZE); } +static uint32_t configure_test_timer(nrfx_timer_t *timer) +{ + uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer->p_reg); + nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency); + + timer_config.bit_width = NRF_TIMER_BIT_WIDTH_16; + timer_config.mode = NRF_TIMER_MODE_COUNTER; + + TC_PRINT("Timer base frequency: %d Hz\n", base_frequency); + + zassert_ok(nrfx_timer_init(timer, &timer_config, NULL), "Timer init failed\n"); + nrfx_timer_enable(timer); + + return nrfx_timer_task_address_get(timer, NRF_TIMER_TASK_COUNT); +} + /* * Reference: MLTPAN-8 * Requirements to trigger the PAN workaround * CPHA = 0 (configured in SPI_MODE) - * PRESCALER > 2 (16 for 1MHz) + * PRESCALER > 2 (4 for 4MHz) * First transmitted bit is 1 (0x8B, MSB) */ -ZTEST(spim_pan, test_spim_pan_workaround) +ZTEST(spim_pan, test_spim_mltpan_8_workaround) { int err; @@ -59,13 +81,65 @@ ZTEST(spim_pan, test_spim_pan_workaround) set_buffers(); + err = spi_transceive_dt(&spim_spec, &tx_spi_buf_set, &rx_spi_buf_set); TC_PRINT("SPIM prescaler: %u\n", spim_reg->PRESCALER); zassert_true(spim_reg->PRESCALER > 2, "SPIM prescaler is not greater than 2\n"); - - err = spi_transceive_dt(&spim_spec, &tx_spi_buf_set, &rx_spi_buf_set); zassert_ok(err, "SPI transceive failed: %d\n", err); zassert_mem_equal(tx_buffer, rx_buffer, TEST_BUFFER_SIZE, "TX buffer != RX buffer\n"); } +/* + * Reference: MLTPAN-55 + * Requirements to trigger the PAN workaround + * MODE 0 or MODE 2 (CPHA = 0) + * PRESCALER = 4 (4 MHz) for SPIM2x and SPIM3x + * RX.MAXCNT lower than TX.MAXCNT + */ + +ZTEST(spim_pan, test_spim_mltpan_55_workaround) +{ + int err; + + uint8_t ppi_channel; + + uint32_t domain_id; + nrfx_gppi_handle_t gppi_handle; + + uint32_t timer_cc_before, timer_cc_after; + + uint32_t timer_task; + uint32_t spim_event; + + struct spi_buf tx_spi_buf = {.buf = tx_buffer, .len = TEST_BUFFER_SIZE}; + struct spi_buf_set tx_spi_buf_set = {.buffers = &tx_spi_buf, .count = 1}; + + struct spi_buf rx_spi_buf = {.buf = rx_buffer, .len = TEST_BUFFER_SIZE - 1}; + struct spi_buf_set rx_spi_buf_set = {.buffers = &rx_spi_buf, .count = 1}; + + set_buffers(); + + domain_id = nrfx_gppi_domain_id_get((uint32_t)test_timer.p_reg); + ppi_channel = nrfx_gppi_channel_alloc(domain_id); + zassert_true(ppi_channel > 0, "Failed to allocate GPPI channel"); + + timer_task = configure_test_timer(&test_timer); + spim_event = nrf_spim_event_address_get(spim_reg, NRF_SPIM_EVENT_END); + + zassert_ok(nrfx_gppi_conn_alloc(spim_event, timer_task, &gppi_handle), + "Failed to allocate DPPI connection\n"); + nrfx_gppi_conn_enable(gppi_handle); + + timer_cc_before = nrfx_timer_capture(&test_timer, NRF_TIMER_CC_CHANNEL0); + err = spi_transceive_dt(&spim_spec, &tx_spi_buf_set, &rx_spi_buf_set); + timer_cc_after = nrfx_timer_capture(&test_timer, NRF_TIMER_CC_CHANNEL0); + + TC_PRINT("Timer count before: %u, timer count after: %u\n", timer_cc_before, + timer_cc_after); + + zassert_true((timer_cc_after - timer_cc_before) > 0, + "NRF_SPIM_EVENT_END did not trigger\n"); + zassert_mem_equal(tx_buffer, rx_buffer, TEST_BUFFER_SIZE - 1, "TX buffer != RX buffer\n"); +} + ZTEST_SUITE(spim_pan, NULL, test_setup, NULL, NULL, NULL); From e810cd4201fcb9b787caa67e67f92fa70b0317c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Mon, 24 Nov 2025 10:02:42 +0100 Subject: [PATCH 003/155] tests: drivers: can: Add test for CAN stats init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CAN stats shall be initialized during driver initialization. Add test which confirms that CAN stats are zeroed before any start/stop operation. Signed-off-by: Sebastian Głąb --- CODEOWNERS | 1 + scripts/ci/tags.yaml | 4 ++ .../drivers/can/can_stats_init/CMakeLists.txt | 13 +++++ tests/drivers/can/can_stats_init/prj.conf | 4 ++ .../can/can_stats_init/src/can_stats_init.c | 51 +++++++++++++++++++ .../drivers/can/can_stats_init/testcase.yaml | 12 +++++ 6 files changed, 85 insertions(+) create mode 100644 tests/drivers/can/can_stats_init/CMakeLists.txt create mode 100644 tests/drivers/can/can_stats_init/prj.conf create mode 100644 tests/drivers/can/can_stats_init/src/can_stats_init.c create mode 100644 tests/drivers/can/can_stats_init/testcase.yaml diff --git a/CODEOWNERS b/CODEOWNERS index bca837f5838f..4f1e37063b63 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -855,6 +855,7 @@ /tests/bluetooth/tester/ @carlescufi @nrfconnect/ncs-paladin /tests/crypto/ @magnev /tests/drivers/audio/ @nrfconnect/ncs-low-level-test +/tests/drivers/can/ @nrfconnect/ncs-low-level-test /tests/drivers/flash/flash_rpc/ @nrfconnect/ncs-eris /tests/drivers/flash_patch/ @nrfconnect/ncs-eris /tests/drivers/fprotect/ @nrfconnect/ncs-eris diff --git a/scripts/ci/tags.yaml b/scripts/ci/tags.yaml index bbf70d8ee3da..dc3ec8918831 100644 --- a/scripts/ci/tags.yaml +++ b/scripts/ci/tags.yaml @@ -1865,3 +1865,7 @@ ci_tests_subsys_rtt: ci_tests_subsys_swo: files: - nrf/tests/subsys/swo/ + +ci_tests_drivers_can: + files: + - zephyr/drivers/can/ diff --git a/tests/drivers/can/can_stats_init/CMakeLists.txt b/tests/drivers/can/can_stats_init/CMakeLists.txt new file mode 100644 index 000000000000..b5119664448b --- /dev/null +++ b/tests/drivers/can/can_stats_init/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(can_stats_init) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/can/can_stats_init/prj.conf b/tests/drivers/can/can_stats_init/prj.conf new file mode 100644 index 000000000000..dc6615086d49 --- /dev/null +++ b/tests/drivers/can/can_stats_init/prj.conf @@ -0,0 +1,4 @@ +CONFIG_CAN=y +CONFIG_STATS=y +CONFIG_CAN_STATS=y +CONFIG_ZTEST=y diff --git a/tests/drivers/can/can_stats_init/src/can_stats_init.c b/tests/drivers/can/can_stats_init/src/can_stats_init.c new file mode 100644 index 000000000000..f21761ed3c63 --- /dev/null +++ b/tests/drivers/can/can_stats_init/src/can_stats_init.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +#include + +#define EXPECTED 0 + +static const struct device *const can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)); + +/* Test that CAN statistics are cleared during driver initialization. + * + * Since CAN start/stop will clear CAN stats, it's crucial this test + * is executed immediately after CAN driver initialization. + */ +ZTEST_USER(can_stats_init, test_can_stats_cleared_during_driver_init) +{ + uint32_t val; + + val = can_stats_get_bit_errors(can_dev); + zassert_true(val == EXPECTED, "CAN bit errors are too high (%u)", val); + val = can_stats_get_bit0_errors(can_dev); + zassert_true(val == EXPECTED, "CAN bit0 errors are too high (%u)", val); + val = can_stats_get_bit1_errors(can_dev); + zassert_true(val == EXPECTED, "CAN bit1 errors are too high (%u)", val); + val = can_stats_get_stuff_errors(can_dev); + zassert_true(val == EXPECTED, "CAN stuff errors are too high (%u)", val); + val = can_stats_get_crc_errors(can_dev); + zassert_true(val == EXPECTED, "CAN crc errors are too high (%u)", val); + val = can_stats_get_form_errors(can_dev); + zassert_true(val == EXPECTED, "CAN form errors are too high (%u)", val); + val = can_stats_get_ack_errors(can_dev); + zassert_true(val == EXPECTED, "CAN ack errors are too high (%u)", val); + val = can_stats_get_rx_overruns(can_dev); + zassert_true(val == EXPECTED, "CAN rx overruns are too high (%u)", val); +} + +void *suite_setup(void) +{ + zassert_true(device_is_ready(can_dev), "CAN device not ready"); + + return NULL; +} + +ZTEST_SUITE(can_stats_init, NULL, suite_setup, NULL, NULL, NULL); diff --git a/tests/drivers/can/can_stats_init/testcase.yaml b/tests/drivers/can/can_stats_init/testcase.yaml new file mode 100644 index 000000000000..98bdf5764222 --- /dev/null +++ b/tests/drivers/can/can_stats_init/testcase.yaml @@ -0,0 +1,12 @@ +common: + tags: + - drivers + - can + - ci_tests_drivers_can + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + +tests: + drivers.can.can_stats_init: {} From fbd2c221ff94dfb71c6b68221e059eeb45a6f726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katarzyna=20Gi=C4=85d=C5=82a?= Date: Fri, 28 Nov 2025 14:39:57 +0100 Subject: [PATCH 004/155] quarantine: Clear quarantine for applications.machine_learning.* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issues are fixed therefore test configurations could be removed from quarantine. NCSDK-35672, NCSDK-35522 Signed-off-by: Katarzyna Giądła --- scripts/quarantine.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/scripts/quarantine.yaml b/scripts/quarantine.yaml index 0b35732b495d..8842e51b6370 100644 --- a/scripts/quarantine.yaml +++ b/scripts/quarantine.yaml @@ -42,14 +42,6 @@ - thingy53/nrf5340/cpuapp comment: "https://nordicsemi.atlassian.net/browse/NCSDK-35521" -- scenarios: - - applications.machine_learning.zrelease - - applications.machine_learning.zdebug - - applications.machine_learning.zdebug_rtt - platforms: - - thingy53/nrf5340/cpuapp - comment: "https://nordicsemi.atlassian.net/browse/NCSDK-35522,NCSDK-35672" - - scenarios: - benchmarks.multicore.idle_twim.nrf54h20dk_cpuapp_cpurad.s2ram platforms: From 408a35fc93a51f2ad183086703e1e392eac805a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Mon, 1 Dec 2025 08:18:47 +0100 Subject: [PATCH 005/155] tests: drivers: can: Fix code formatting in can_stats_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix code formatting - remove double SPACE character. Signed-off-by: Sebastian Głąb --- tests/drivers/can/can_stats_init/src/can_stats_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/drivers/can/can_stats_init/src/can_stats_init.c b/tests/drivers/can/can_stats_init/src/can_stats_init.c index f21761ed3c63..7a045fb09614 100644 --- a/tests/drivers/can/can_stats_init/src/can_stats_init.c +++ b/tests/drivers/can/can_stats_init/src/can_stats_init.c @@ -10,7 +10,7 @@ #include -#define EXPECTED 0 +#define EXPECTED 0 static const struct device *const can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)); From 192d7a33ff7d1861bc5de2e48ea805e4a2d67bf2 Mon Sep 17 00:00:00 2001 From: Jorgen Kvalvaag Date: Fri, 28 Nov 2025 14:21:54 +0100 Subject: [PATCH 006/155] samples: https_client: Fix pdn kconfigs Sample is using link_controller and needs to use LTE_LC_PDN_* kconfigs. Signed-off-by: Jorgen Kvalvaag --- samples/net/https_client/overlay-pdn-nrf91-ipv4.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/net/https_client/overlay-pdn-nrf91-ipv4.conf b/samples/net/https_client/overlay-pdn-nrf91-ipv4.conf index 2506124827c2..45e1dffe8016 100644 --- a/samples/net/https_client/overlay-pdn-nrf91-ipv4.conf +++ b/samples/net/https_client/overlay-pdn-nrf91-ipv4.conf @@ -4,5 +4,5 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -CONFIG_PDN_DEFAULTS_OVERRIDE=y -CONFIG_PDN_DEFAULT_FAM_IPV4=y +CONFIG_LTE_LC_PDN_DEFAULTS_OVERRIDE=y +CONFIG_LTE_LC_PDN_DEFAULT_FAM_IPV4=y From 59c91cbffd5cee5e087c50158a9728513939cde7 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Fri, 28 Nov 2025 12:28:00 +0100 Subject: [PATCH 007/155] samples: peripheral: 802154_phy_test: fix nrfx_timer assert Now this assertion must explicitly check for `0` value as nrfx 4.0 functions returns errno codes. Signed-off-by: Nikodem Kastelik --- samples/peripheral/802154_phy_test/src/periph_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/peripheral/802154_phy_test/src/periph_proc.c b/samples/peripheral/802154_phy_test/src/periph_proc.c index 6a4854d9aee4..47acb685baab 100644 --- a/samples/peripheral/802154_phy_test/src/periph_proc.c +++ b/samples/peripheral/802154_phy_test/src/periph_proc.c @@ -99,7 +99,7 @@ void periph_init(void) nrfx_timer_config_t clk_timer_cfg = NRFX_TIMER_DEFAULT_CONFIG(base_frequency); err_code = nrfx_timer_init(&clk_timer, &clk_timer_cfg, clk_timer_handler); - NRFX_ASSERT(err_code); + __ASSERT_NO_MSG(err_code == 0); for (int i = 0; i < GPIO_COUNT; ++i) { nrfx_gpiote_t *gpiote = NRF_GPIOTE_FOR_GPIO(i); From 04993f284e3ed3a38f20f5e87014a099a2151680 Mon Sep 17 00:00:00 2001 From: Jan Tore Guggedal Date: Fri, 28 Nov 2025 10:05:25 +0100 Subject: [PATCH 008/155] samples: cellular: pdn: Enable default context events The sample needs to enable default context events in order to receive event when the default context is detached. Signed-off-by: Jan Tore Guggedal --- samples/cellular/pdn/src/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/samples/cellular/pdn/src/main.c b/samples/cellular/pdn/src/main.c index f59ed6462c14..5de60141d4cc 100644 --- a/samples/cellular/pdn/src/main.c +++ b/samples/cellular/pdn/src/main.c @@ -146,6 +146,12 @@ int main(void) */ lte_lc_register_handler(lte_lc_evt_handler); + err = lte_lc_pdn_default_ctx_events_enable(); + if (err) { + printk("lte_lc_pdn_default_ctx_events_enable() failed, err %d\n", err); + return 0; + } + err = lte_lc_connect(); if (err) { return 0; From a79b3a62e350386666dae8f46d1e265e3c9abae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 26 Nov 2025 15:19:24 +0100 Subject: [PATCH 009/155] samples: ironside_se: protectedmem_periphconf: Fix sample.yaml regex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix sample.yaml regex to match expected uart output. Signed-off-by: Sebastian Bøe --- samples/ironside_se/protectedmem_periphconf/sample.yaml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/samples/ironside_se/protectedmem_periphconf/sample.yaml b/samples/ironside_se/protectedmem_periphconf/sample.yaml index 757bdc77aaab..48497c6f9153 100644 --- a/samples/ironside_se/protectedmem_periphconf/sample.yaml +++ b/samples/ironside_se/protectedmem_periphconf/sample.yaml @@ -15,13 +15,10 @@ common: type: multi_line ordered: true regex: - - "=== Protected Memory Demo ===" - - "Attempting to write test pattern" - - "Write successful \\(in current boot\\)\\." - - "Rebooting\\.\\.\\." + - "Writing test pattern to protected memory\\.\\.\\." + - "Rebooting\\. Secondary firmware should boot if protection is working\\." # When PROTECTEDMEM integrity check fails, secondary firmware boots - - "=== Secondary Firmware Booted ===" - - "PROTECTEDMEM integrity check FAILED" + - "PROTECTEDMEM integrity check failed - secondary firmware booted" tests: samples.protectedmem_periphconf.nrf54h20dk: From 497a8b194cebd65d00b51e7ff858b26ed1c6a235 Mon Sep 17 00:00:00 2001 From: Anton Zyma Date: Mon, 20 Oct 2025 14:59:34 +0300 Subject: [PATCH 010/155] nrf_security: CRACEN: Decrease number of typecasts The number of const casts decreased. Ref: NCSDK-32018 Signed-off-by: Anton Zyma --- .../cracenpsa/include/cracen_psa_primitives.h | 6 + .../include/cracen_psa_rsa_encryption.h | 8 +- .../cracen_psa_rsa_signature_pkcs1v15.h | 4 +- .../include/cracen_psa_rsa_signature_pss.h | 5 +- .../drivers/cracen/cracenpsa/src/asymmetric.c | 2 +- .../src/drivers/cracen/cracenpsa/src/common.c | 36 ++--- .../src/drivers/cracen/cracenpsa/src/common.h | 7 +- .../src/drivers/cracen/cracenpsa/src/ecdsa.c | 7 +- .../src/drivers/cracen/cracenpsa/src/jpake.c | 48 ++++--- .../cracen/cracenpsa/src/key_derivation.c | 21 +-- .../cracen/cracenpsa/src/key_management.c | 23 ++-- .../src/drivers/cracen/cracenpsa/src/kmu.c | 4 +- .../drivers/cracen/cracenpsa/src/rsa_keygen.c | 18 +-- .../drivers/cracen/cracenpsa/src/rsaes_oaep.c | 8 +- .../src/drivers/cracen/cracenpsa/src/rsapss.c | 5 +- .../cracen/cracenpsa/src/rsassa_pkcs1v15.c | 6 +- .../src/drivers/cracen/cracenpsa/src/sign.c | 5 +- .../drivers/cracen/cracenpsa/src/spake2p.c | 79 ++++++----- .../src/drivers/cracen/cracenpsa/src/srp.c | 88 ++++++++----- .../silexpk/include/silexpk/sxbuf/sxbufop.h | 54 +++++++- .../silexpk/include/silexpk/sxops/adapter.h | 13 +- .../silexpk/include/silexpk/sxops/dsa.h | 27 ++-- .../include/silexpk/sxops/eccweierstrass.h | 123 ++++++++++-------- .../silexpk/include/silexpk/sxops/ecjpake.h | 66 +++++----- .../silexpk/include/silexpk/sxops/rsa.h | 91 +++++++------ .../silexpk/include/silexpk/sxops/sm9.h | 54 ++++---- .../silexpk/include/silexpk/sxops/srp.h | 26 ++-- .../cracen/silexpk/interface/sxbuf/sxbufops.c | 19 ++- .../cracen/silexpk/target/hw/ik/ikhardware.c | 2 +- 29 files changed, 501 insertions(+), 354 deletions(-) diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_primitives.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_primitives.h index 400f7ad05c17..dd00caae0664 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_primitives.h +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_primitives.h @@ -410,6 +410,12 @@ struct cracen_signature { uint8_t *s; /** Signature element "s". */ }; +struct cracen_const_signature { + size_t sz; /** Total signature size, in bytes. */ + const uint8_t *r; /** Signature element "r". */ + const uint8_t *s; /** Signature element "s". */ +}; + struct cracen_ecc_priv_key { const struct sx_pk_ecurve *curve; const uint8_t *d; /** Private key value d */ diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_encryption.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_encryption.h index 5fdd7ca97149..10adb6cb02ad 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_encryption.h +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_encryption.h @@ -10,12 +10,12 @@ #include "cracen_psa_primitives.h" int cracen_rsa_oaep_encrypt(const struct sxhashalg *hashalg, struct cracen_rsa_key *rsa_key, - struct cracen_crypt_text *text, struct sx_buf *label, uint8_t *output, - size_t *output_length); + struct cracen_crypt_text *text, struct sx_const_buf *label, + uint8_t *output, size_t *output_length); int cracen_rsa_oaep_decrypt(const struct sxhashalg *hashalg, struct cracen_rsa_key *rsa_key, - struct cracen_crypt_text *text, struct sx_buf *label, uint8_t *output, - size_t *output_length); + struct cracen_crypt_text *text, struct sx_const_buf *label, + uint8_t *output, size_t *output_length); int cracen_rsa_pkcs1v15_decrypt(struct cracen_rsa_key *rsa_key, struct cracen_crypt_text *text, uint8_t *output, size_t *output_length); diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_signature_pkcs1v15.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_signature_pkcs1v15.h index 927af56dd90d..17bff4ae2e2e 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_signature_pkcs1v15.h +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_signature_pkcs1v15.h @@ -20,12 +20,12 @@ int cracen_rsa_pkcs1v15_sign_digest(struct cracen_rsa_key *rsa_key, size_t digest_length); int cracen_rsa_pkcs1v15_verify_message(struct cracen_rsa_key *rsa_key, - struct cracen_signature *signature, + struct cracen_const_signature *signature, const struct sxhashalg *hashalg, const uint8_t *message, size_t message_length); int cracen_rsa_pkcs1v15_verify_digest(struct cracen_rsa_key *rsa_key, - struct cracen_signature *signature, + struct cracen_const_signature *signature, const struct sxhashalg *hashalg, const uint8_t *digest, size_t digest_length); diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_signature_pss.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_signature_pss.h index 1dde2ee03700..0e38ded19d0b 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_signature_pss.h +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_rsa_signature_pss.h @@ -18,11 +18,12 @@ int cracen_rsa_pss_sign_digest(struct cracen_rsa_key *rsa_key, struct cracen_sig size_t input_length, size_t saltsz); int cracen_rsa_pss_verify_message(struct cracen_rsa_key *rsa_key, - struct cracen_signature *signature, + struct cracen_const_signature *signature, const struct sxhashalg *hashalg, const uint8_t *message, size_t message_length, size_t saltsz); -int cracen_rsa_pss_verify_digest(struct cracen_rsa_key *rsa_key, struct cracen_signature *signature, +int cracen_rsa_pss_verify_digest(struct cracen_rsa_key *rsa_key, + struct cracen_const_signature *signature, const struct sxhashalg *hashalg, const uint8_t *digest, size_t digest_length, size_t saltsz); diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/asymmetric.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/asymmetric.c index 8b57c6c07bf1..bdbdeb1620d5 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/asymmetric.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/asymmetric.c @@ -66,7 +66,7 @@ cracen_asymmetric_crypt_internal(const psa_key_attributes_t *attributes, const u return status; } - struct sx_buf label = {salt_length, (uint8_t *)salt}; + struct sx_const_buf label = {salt_length, salt}; if (dir == CRACEN_ENCRYPT) { sx_status = cracen_rsa_oaep_encrypt(hashalg, &pubkey, &text, &label, diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.c index 9d50cbbd642f..58ef97378433 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.c @@ -320,8 +320,8 @@ psa_status_t cracen_ecc_reduce_p256(const uint8_t *input, size_t input_size, uin { const uint8_t *order = sx_pk_curve_order(&sx_curve_nistp256); - sx_op modulo = {.sz = CRACEN_P256_KEY_SIZE, .bytes = (uint8_t *)order}; - sx_op operand = {.sz = input_size, .bytes = (uint8_t *)input}; + sx_const_op modulo = {.sz = CRACEN_P256_KEY_SIZE, .bytes = order}; + sx_const_op operand = {.sz = input_size, .bytes = input}; sx_op result = {.sz = output_size, .bytes = output}; /* The nistp256 curve order (n) is prime so we use the ODD variant of the reduce command. */ @@ -332,15 +332,15 @@ psa_status_t cracen_ecc_reduce_p256(const uint8_t *input, size_t input_size, uin } psa_status_t cracen_ecc_check_public_key(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *in_pnt) + const sx_pk_const_affine_point *in_pnt) { int sx_status; uint8_t char_x[CRACEN_MAC_ECC_PRIVKEY_BYTES]; uint8_t char_y[CRACEN_MAC_ECC_PRIVKEY_BYTES]; /* Get the order of the curve from the parameters */ - struct sx_buf n = {.sz = sx_pk_curve_opsize(curve), - .bytes = (uint8_t *)sx_pk_curve_order(curve)}; + struct sx_const_buf n = {.sz = sx_pk_curve_opsize(curve), + .bytes = sx_pk_curve_order(curve)}; sx_pk_affine_point scratch_pnt = {.x = {.sz = n.sz, .bytes = char_x}, .y = {.sz = n.sz, .bytes = char_y}}; @@ -413,7 +413,7 @@ void cracen_xorbytes(uint8_t *a, const uint8_t *b, size_t sz) } } -static int cracen_asn1_get_len(uint8_t **p, const uint8_t *end, size_t *len) +static int cracen_asn1_get_len(const uint8_t **p, const uint8_t *end, size_t *len) { if ((end - *p) < 1) { return SX_ERR_INVALID_PARAM; @@ -445,7 +445,7 @@ static int cracen_asn1_get_len(uint8_t **p, const uint8_t *end, size_t *len) return 0; } -static int cracen_asn1_get_tag(uint8_t **p, const uint8_t *end, size_t *len, int tag) +static int cracen_asn1_get_tag(const uint8_t **p, const uint8_t *end, size_t *len, int tag) { if ((end - *p) < 1) { return SX_ERR_INVALID_PARAM; @@ -460,7 +460,7 @@ static int cracen_asn1_get_tag(uint8_t **p, const uint8_t *end, size_t *len, int return cracen_asn1_get_len(p, end, len); } -static int cracen_asn1_get_int(uint8_t **p, const uint8_t *end, int *val) +static int cracen_asn1_get_int(const uint8_t **p, const uint8_t *end, int *val) { int ret = SX_ERR_INVALID_PARAM; size_t len; @@ -503,7 +503,7 @@ static int cracen_asn1_get_int(uint8_t **p, const uint8_t *end, int *val) return 0; } -int cracen_signature_asn1_get_operand(uint8_t **p, const uint8_t *end, +int cracen_signature_asn1_get_operand(const uint8_t **p, const uint8_t *end, struct sx_buf *op) { int ret; @@ -539,10 +539,10 @@ int cracen_signature_get_rsa_key(struct cracen_rsa_key *rsa, bool extract_pubkey { int ret, version; size_t len; - uint8_t *parser_ptr; - uint8_t *end; + const uint8_t *parser_ptr; + const uint8_t *end; - parser_ptr = (uint8_t *)key; + parser_ptr = key; end = parser_ptr + keylen; if (!extract_pubkey && !is_key_pair) { @@ -591,7 +591,7 @@ int cracen_signature_get_rsa_key(struct cracen_rsa_key *rsa, bool extract_pubkey } } else { /* Skip algorithm identifier prefix. */ - uint8_t *id_seq = parser_ptr; + const uint8_t *id_seq = parser_ptr; ret = cracen_asn1_get_tag(&id_seq, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); if (ret == 0) { @@ -717,7 +717,7 @@ static psa_status_t cracen_load_ikg_keyref(const psa_key_attributes_t *attribute }; k->owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(psa_get_key_id(attributes)); - k->user_data = (uint8_t *)&k->owner_id; + k->user_data = (const uint8_t *)&k->owner_id; return PSA_SUCCESS; } @@ -745,7 +745,7 @@ psa_status_t cracen_load_keyref(const psa_key_attributes_t *attributes, const ui return PSA_SUCCESS; case CRACEN_KMU_KEY_USAGE_SCHEME_PROTECTED: k->sz = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)); - k->key = (uint8_t *)CRACEN_PROTECTED_RAM_AES_KEY0; + k->key = (const uint8_t *)CRACEN_PROTECTED_RAM_AES_KEY0; return PSA_SUCCESS; @@ -767,14 +767,14 @@ psa_status_t cracen_load_keyref(const psa_key_attributes_t *attributes, const ui } k->owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(psa_get_key_id(attributes)); - k->user_data = (uint8_t *)&k->owner_id; + k->user_data = (const uint8_t *)&k->owner_id; k->prepare_key = NULL; k->clean_key = NULL; switch (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(attributes))) { case CRACEN_PROTECTED_RAM_AES_KEY0_ID: k->sz = 32; - k->key = (uint8_t *)CRACEN_PROTECTED_RAM_AES_KEY0; + k->key = (const uint8_t *)CRACEN_PROTECTED_RAM_AES_KEY0; break; default: if (key_buffer_size == 0) { @@ -930,7 +930,7 @@ int cracen_hash_input_with_context(struct sxhash *hashopctx, const uint8_t *inpu } int cracen_rsa_modexp(struct sx_pk_acq_req *pkreq, struct sx_pk_slot *inputs, - struct cracen_rsa_key *rsa_key, uint8_t *base, size_t basez, int *sizes) + struct cracen_rsa_key *rsa_key, const uint8_t *base, size_t basez, int *sizes) { *pkreq = sx_pk_acquire_req(rsa_key->cmd); if (pkreq->status != SX_OK) { diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.h index d9a579487158..a589e72cf652 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.h +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.h @@ -117,7 +117,7 @@ static inline size_t cracen_ecc_wstr_expected_pub_key_bytes(size_t priv_key_size * */ psa_status_t cracen_ecc_check_public_key(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *in_pnt); + const sx_pk_const_affine_point *in_pnt); /** * \brief Tries to extract an RSA key from ASN.1. @@ -148,7 +148,7 @@ int cracen_signature_get_rsa_key(struct cracen_rsa_key *rsa, bool extract_pubkey * \retval SX_OK on success. * \retval SX_ERR_INVALID_PARAM if the ASN.1 integer cannot be extracted. */ -int cracen_signature_asn1_get_operand(uint8_t **p, const uint8_t *end, struct sx_buf *op); +int cracen_signature_asn1_get_operand(const uint8_t **p, const uint8_t *end, struct sx_buf *op); /** * @brief Use cracen_get_random up to generate a random number in the range [1, upperlimit). @@ -314,7 +314,8 @@ psa_status_t cracen_ecc_reduce_p256(const uint8_t *input, size_t input_size, uin * status code. */ int cracen_rsa_modexp(struct sx_pk_acq_req *pkreq, struct sx_pk_slot *inputs, - struct cracen_rsa_key *rsa_key, uint8_t *base, size_t basez, int *sizes); + struct cracen_rsa_key *rsa_key, const uint8_t *base, size_t basez, + int *sizes); #define CRACEN_KEY_INIT_RSA(mod, expon) \ (struct cracen_rsa_key) \ diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ecdsa.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ecdsa.c index f6df919bce07..1cc716144a26 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ecdsa.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ecdsa.c @@ -148,7 +148,7 @@ static void ecdsa_write_pk(const uint8_t *pubkey, uint8_t *x, uint8_t *y, size_t sx_wrpkmem(y, pubkey + opsz, opsz); } -static void ecdsa_write_sig(const struct cracen_signature *sig, uint8_t *r, uint8_t *s, +static void ecdsa_write_sig(const struct cracen_const_signature *sig, uint8_t *r, uint8_t *s, size_t opsz) { sx_wrpkmem(r, sig->r, opsz); @@ -524,10 +524,7 @@ int cracen_ecdsa_verify_digest(const uint8_t *pubkey, const uint8_t *digest, con struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecdsa_verify inputs; - struct cracen_signature internal_signature = {0}; - - internal_signature.r = (uint8_t *)signature; - internal_signature.s = (uint8_t *)signature + opsz; + struct cracen_const_signature internal_signature = {.r = signature, .s = signature + opsz}; pkreq = sx_pk_acquire_req(SX_PK_CMD_ECDSA_VER); if (pkreq.status) { diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/jpake.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/jpake.c index 09e17882903b..a28fcd943204 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/jpake.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/jpake.c @@ -23,10 +23,6 @@ #include #include -#define MAKE_SX_POINT(name, ptr, point_size) \ - sx_pk_affine_point name = {{.bytes = (ptr), .sz = (point_size) / 2}, \ - {.bytes = (ptr) + (point_size) / 2, .sz = (point_size) / 2}}; - /* * This driver supports uncompressed points only. Uncompressed types * are prefixed with the byte 0x04. See 2.3.3.3.3 from "SEC 1: @@ -72,8 +68,8 @@ psa_status_t cracen_jpake_set_password_key(cracen_jpake_operation_t *operation, */ const uint8_t *order = sx_pk_curve_order(operation->curve); - sx_op modulo = {.sz = CRACEN_P256_KEY_SIZE, .bytes = (uint8_t *)order}; - sx_op b = {.sz = password_length, .bytes = (uint8_t *)password}; + sx_const_op modulo = {.sz = CRACEN_P256_KEY_SIZE, .bytes = order}; + sx_const_op b = {.sz = password_length, .bytes = password}; sx_op result = {.sz = sizeof(operation->secret), .bytes = operation->secret}; /* The nistp256 curve order (n) is prime so we use the ODD variant of the reduce command. */ @@ -322,14 +318,14 @@ static psa_status_t cracen_write_key_share(cracen_jpake_operation_t *operation, memcpy(generator, curve_pt, CRACEN_P256_POINT_SIZE); } else if (idx == 2) { /* Second round of J-PAKE: Compute G_a, x2s and A. */ - MAKE_SX_POINT(G4, operation->P[0], CRACEN_P256_POINT_SIZE); - MAKE_SX_POINT(G3, operation->P[1], CRACEN_P256_POINT_SIZE); - MAKE_SX_POINT(G1, operation->X[0], CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(G4, operation->P[0], CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(G3, operation->P[1], CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(G1, operation->X[0], CRACEN_P256_POINT_SIZE); MAKE_SX_POINT(ga, generator, CRACEN_P256_POINT_SIZE); MAKE_SX_POINT(a, operation->X[2], CRACEN_P256_POINT_SIZE); - sx_ecop x2s = {.bytes = operation->x[1], .sz = CRACEN_P256_KEY_SIZE}; - sx_ecop s = {.bytes = operation->secret, .sz = CRACEN_P256_KEY_SIZE}; + sx_const_ecop x2s = {.bytes = operation->x[1], .sz = CRACEN_P256_KEY_SIZE}; + sx_const_ecop s = {.bytes = operation->secret, .sz = CRACEN_P256_KEY_SIZE}; sx_ecop rx2s = {.bytes = operation->x[2], .sz = CRACEN_P256_KEY_SIZE}; sx_status = sx_ecjpake_gen_step_2(operation->curve, &G4, &G3, &G1, &x2s, &s, &a, @@ -362,9 +358,9 @@ static psa_status_t cracen_write_key_share(cracen_jpake_operation_t *operation, return status; } - sx_ecop sx_v = {.bytes = v, .sz = sizeof(v)}; - sx_ecop sx_x = {.bytes = operation->x[idx], .sz = sizeof(operation->x[idx])}; - sx_ecop sx_h = {.bytes = h, .sz = PSA_HASH_LENGTH(PSA_ALG_SHA_256)}; + sx_const_ecop sx_v = {.bytes = v, .sz = sizeof(v)}; + sx_const_ecop sx_x = {.bytes = operation->x[idx], .sz = sizeof(operation->x[idx])}; + sx_const_ecop sx_h = {.bytes = h, .sz = PSA_HASH_LENGTH(PSA_ALG_SHA_256)}; sx_ecop sx_r = {.bytes = operation->r, .sz = sizeof(operation->r)}; sx_status = sx_ecjpake_generate_zkp(operation->curve, &sx_v, &sx_x, &sx_h, &sx_r); @@ -491,9 +487,9 @@ static psa_status_t cracen_read_zk_proof(cracen_jpake_operation_t *operation, co } else if (idx == 2) { /* Second round of J-PAKE: Compute G_B. */ - MAKE_SX_POINT(G1, operation->X[0], CRACEN_P256_POINT_SIZE); - MAKE_SX_POINT(G2, operation->X[1], CRACEN_P256_POINT_SIZE); - MAKE_SX_POINT(G3, operation->P[0], CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(G1, operation->X[0], CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(G2, operation->X[1], CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(G3, operation->P[0], CRACEN_P256_POINT_SIZE); MAKE_SX_POINT(g, generator, CRACEN_P256_POINT_SIZE); int sx_status = sx_ecjpake_3pt_add(operation->curve, &G1, &G2, &G3, &g); @@ -513,12 +509,12 @@ static psa_status_t cracen_read_zk_proof(cracen_jpake_operation_t *operation, co return status; } - MAKE_SX_POINT(sx_v, operation->V, CRACEN_P256_POINT_SIZE); - MAKE_SX_POINT(sx_x, operation->P[idx], CRACEN_P256_POINT_SIZE); - MAKE_SX_POINT(sx_g, generator, CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(sx_v, operation->V, CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(sx_x, operation->P[idx], CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(sx_g, generator, CRACEN_P256_POINT_SIZE); - sx_ecop sx_r = {.bytes = operation->r, .sz = sizeof(operation->r)}; - sx_ecop sx_h = {.bytes = h, .sz = h_len}; + sx_const_ecop sx_r = {.bytes = operation->r, .sz = sizeof(operation->r)}; + sx_const_ecop sx_h = {.bytes = h, .sz = h_len}; int sx_status = sx_ecjpake_verify_zkp(operation->curve, &sx_v, &sx_x, &sx_r, &sx_h, idx == 2 ? &sx_g : SX_PT_CURVE_GENERATOR); @@ -559,10 +555,10 @@ psa_status_t cracen_jpake_get_shared_key(cracen_jpake_operation_t *operation, output[0] = CRACEN_ECC_PUBKEY_UNCOMPRESSED; /* get PMSK */ - MAKE_SX_POINT(x4, operation->P[1], CRACEN_P256_POINT_SIZE); - MAKE_SX_POINT(b, operation->P[2], CRACEN_P256_POINT_SIZE); - sx_ecop x2 = {.bytes = operation->x[1], .sz = CRACEN_P256_KEY_SIZE}; - sx_ecop x2s = {.bytes = operation->x[2], .sz = CRACEN_P256_KEY_SIZE}; + MAKE_SX_CONST_POINT(x4, operation->P[1], CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(b, operation->P[2], CRACEN_P256_POINT_SIZE); + sx_const_ecop x2 = {.bytes = operation->x[1], .sz = CRACEN_P256_KEY_SIZE}; + sx_const_ecop x2s = {.bytes = operation->x[2], .sz = CRACEN_P256_KEY_SIZE}; MAKE_SX_POINT(t, output + 1, CRACEN_P256_POINT_SIZE); sx_status = sx_ecjpake_gen_sess_key(operation->curve, &x4, &b, &x2, &x2s, &t); diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_derivation.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_derivation.c index 379da5597cb9..ef7fa73d9d4c 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_derivation.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_derivation.c @@ -56,11 +56,11 @@ static psa_status_t cracen_ecdh_wrstr_calc_secret(const struct sx_pk_ecurve *cur uint8_t scratch_char_x[CRACEN_MAC_ECC_PRIVKEY_BYTES]; uint8_t scratch_char_y[CRACEN_MAC_ECC_PRIVKEY_BYTES]; - struct sx_buf priv_key_buff = {.sz = priv_key_size, .bytes = (uint8_t *)priv_key}; + sx_const_ecop priv_key_buff = {.sz = priv_key_size, .bytes = priv_key}; sx_pk_affine_point scratch_pnt = {{.bytes = scratch_char_x, .sz = priv_key_size}, {.bytes = scratch_char_y, .sz = priv_key_size}}; - sx_pk_affine_point publ_key_pnt = {}; + sx_pk_const_affine_point publ_key_pnt = {}; if (publ_key_size != cracen_ecc_wstr_expected_pub_key_bytes(priv_key_size)) { return PSA_ERROR_INVALID_ARGUMENT; @@ -77,10 +77,10 @@ static psa_status_t cracen_ecdh_wrstr_calc_secret(const struct sx_pk_ecurve *cur return PSA_ERROR_BUFFER_TOO_SMALL; } - publ_key_pnt.x.bytes = (uint8_t *)publ_key + 1; + publ_key_pnt.x.bytes = publ_key + 1; publ_key_pnt.x.sz = priv_key_size; - publ_key_pnt.y.bytes = (uint8_t *)publ_key + priv_key_size + 1; + publ_key_pnt.y.bytes = publ_key + priv_key_size + 1; publ_key_pnt.y.sz = priv_key_size; psa_status = cracen_ecc_check_public_key(curve, &publ_key_pnt); @@ -90,8 +90,11 @@ static psa_status_t cracen_ecdh_wrstr_calc_secret(const struct sx_pk_ecurve *cur sx_status = sx_ecp_ptmult(curve, &priv_key_buff, &publ_key_pnt, &scratch_pnt); if (sx_status == SX_OK) { - sx_pk_ecop2mem(&scratch_pnt.x, output, scratch_pnt.x.sz); - *output_length = scratch_pnt.x.sz; + sx_pk_const_affine_point c_scratch_pnt; + + sx_get_const_affine_point(&scratch_pnt, &c_scratch_pnt); + sx_pk_ecop2mem(&c_scratch_pnt.x, output, c_scratch_pnt.x.sz); + *output_length = c_scratch_pnt.x.sz; } safe_memzero(scratch_pnt.x.bytes, scratch_pnt.x.sz); @@ -825,7 +828,7 @@ cracen_key_derivation_cmac_ctr_add_core_fixed_input(cracen_key_derivation_operat } /* L_4 */ - return sx_mac_feed(cmac_ctx, (uint8_t *)&operation->cmac_ctr.L, + return sx_mac_feed(cmac_ctx, (const uint8_t *)&operation->cmac_ctr.L, sizeof(operation->cmac_ctr.L)); } @@ -885,7 +888,7 @@ cracen_key_derivation_cmac_ctr_generate_block(cracen_key_derivation_operation_t } counter_be = uint32_to_be(operation->cmac_ctr.counter); - sx_status = sx_mac_feed(&cmac_ctx, (uint8_t *)&counter_be, sizeof(counter_be)); + sx_status = sx_mac_feed(&cmac_ctx, (const uint8_t *)&counter_be, sizeof(counter_be)); if (sx_status) { return silex_statuscodes_to_psa(sx_status); } @@ -999,7 +1002,7 @@ cracen_key_derivation_pbkdf2_generate_block(cracen_key_derivation_operation_t *o if (status != PSA_SUCCESS) { return status; } - status = cracen_mac_update(&operation->mac_op, (uint8_t *)&blk_counter_be, + status = cracen_mac_update(&operation->mac_op, (const uint8_t *)&blk_counter_be, sizeof(blk_counter_be)); if (status != PSA_SUCCESS) { return status; diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c index ca5db8dc7ffa..ec5a38464d25 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c @@ -225,12 +225,12 @@ static psa_status_t check_wstr_publ_key_for_ecdh(psa_ecc_family_t curve_family, psa_status_t psa_status; const struct sx_pk_ecurve *curve; - sx_pk_affine_point publ_key_pnt = {}; + sx_pk_const_affine_point publ_key_pnt = {}; - publ_key_pnt.x.bytes = (uint8_t *)&data[1]; + publ_key_pnt.x.bytes = &data[1]; publ_key_pnt.x.sz = priv_key_size; - publ_key_pnt.y.bytes = (uint8_t *)&data[1 + priv_key_size]; + publ_key_pnt.y.bytes = &data[1 + priv_key_size]; publ_key_pnt.y.sz = priv_key_size; psa_status = cracen_ecc_get_ecurve_from_psa(curve_family, curve_bits, &curve); @@ -496,13 +496,13 @@ static psa_status_t export_spake2p_public_key_from_keypair(const psa_key_attribu size_t key_bits_attr = psa_get_key_bits(attributes); psa_ecc_family_t psa_curve = PSA_KEY_TYPE_SPAKE2P_GET_FAMILY(psa_get_key_type(attributes)); const struct sx_pk_ecurve *sx_curve; - uint8_t *w0; - uint8_t *w1; + const uint8_t *w0; + const uint8_t *w1; switch (type) { case PSA_KEY_TYPE_SPAKE2P_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1): - w0 = (uint8_t *)priv_key; - w1 = (uint8_t *)priv_key + CRACEN_P256_KEY_SIZE; + w0 = priv_key; + w1 = priv_key + CRACEN_P256_KEY_SIZE; status = cracen_ecc_get_ecurve_from_psa(psa_curve, key_bits_attr, &sx_curve); if (status != PSA_SUCCESS) { return status; @@ -1093,7 +1093,14 @@ static psa_status_t generate_rsa_private_key(const psa_key_attributes_t *attribu } /* Generate n and d */ - status = silex_statuscodes_to_psa(sx_rsa_keygen(&p, &q, &e, &n, NULL, &d)); + sx_const_op c_p; + sx_const_op c_q; + sx_const_op c_e; + + sx_get_const_op(&p, &c_p); + sx_get_const_op(&q, &c_q); + sx_get_const_op(&e, &c_e); + status = silex_statuscodes_to_psa(sx_rsa_keygen(&c_p, &c_q, &c_e, &n, NULL, &d)); if (status != PSA_SUCCESS) { goto error_exit; } diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/kmu.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/kmu.c index 9ce354e1d521..c491c32ebf6c 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/kmu.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/kmu.c @@ -169,7 +169,7 @@ static psa_status_t cracen_kmu_encrypt(const uint8_t *key, size_t key_length, } psa_status = cracen_aead_encrypt(&attr, key_buffer, sizeof(key_buffer), PSA_ALG_GCM, nonce, - 12, (uint8_t *)metadata, sizeof(*metadata), key, + 12, (const uint8_t *)metadata, sizeof(*metadata), key, key_length, encrypted_buffer, encrypted_buffer_size, encrypted_buffer_length); @@ -198,7 +198,7 @@ static psa_status_t cracen_kmu_decrypt(kmu_metadata *metadata, size_t number_of_ size_t outlen = 0; return cracen_aead_decrypt(&attr, key_buffer, sizeof(key_buffer), PSA_ALG_GCM, - kmu_push_area, 12, (uint8_t *)metadata, sizeof(*metadata), + kmu_push_area, 12, (const uint8_t *)metadata, sizeof(*metadata), kmu_push_area + CRACEN_KMU_SLOT_KEY_SIZE, (number_of_slots - 1) * CRACEN_KMU_SLOT_KEY_SIZE, kmu_push_area, sizeof(kmu_push_area), &outlen); diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsa_keygen.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsa_keygen.c index 90478589b45a..725e57562c75 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsa_keygen.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsa_keygen.c @@ -158,9 +158,9 @@ static int rsagenpriv_crt_finish(struct sx_pk_acq_req *pkreq, size_t keysz, uint int sx_status; uint8_t *wmem = workmem + GENPRIVKEY_WORKMEM_OFST(keysz); size_t primefactorsz = keysz >> 1; - sx_op p; - sx_op q; - sx_op privexp; + sx_const_op p; + sx_const_op q; + sx_const_op privexp; /* p and q come out of the earlier key-gen call in workmem */ p.bytes = wmem; @@ -188,7 +188,7 @@ static int rsagenpriv_crt_finish(struct sx_pk_acq_req *pkreq, size_t keysz, uint return sx_status; } - const uint8_t **outputs = (const uint8_t **)sx_pk_get_output_ops(pkreq->req); + const uint8_t **outputs = sx_pk_get_output_ops(pkreq->req); if (pkreq->status != SX_OK) { sx_pk_release_req(pkreq->req); @@ -247,8 +247,8 @@ static int miller_rabin_get_random(uint8_t *workmem, struct cracen_rsacheckpq *r */ cracen_be_add(workmem, candidatesz, 1); uint8_t *candprime = get_candidate_prime(rsacheckpq); - struct sx_buf random; - struct sx_buf candidate; + struct sx_const_buf random; + struct sx_const_buf candidate; random.bytes = workmem; random.sz = candidatesz; @@ -570,9 +570,9 @@ int cracen_rsa_generate_privkey(uint8_t *pubexp, size_t pubexpsz, size_t keysz, struct sx_pk_acq_req pkreq; size_t primefactorsz = keysz >> 1; - sx_op p; - sx_op q; - sx_op pubexp_struct; + sx_const_op p; + sx_const_op q; + sx_const_op pubexp_struct; p.bytes = wmem; p.sz = primefactorsz; diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsaes_oaep.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsaes_oaep.c index ad9ff72782a0..1829a2e2c9a8 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsaes_oaep.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsaes_oaep.c @@ -56,8 +56,8 @@ static void rsa_oaep_decrypt_init(struct rsa_oaep_workmem *workmem, size_t diges } int cracen_rsa_oaep_decrypt(const struct sxhashalg *hashalg, struct cracen_rsa_key *rsa_key, - struct cracen_crypt_text *text, struct sx_buf *label, uint8_t *output, - size_t *output_length) + struct cracen_crypt_text *text, struct sx_const_buf *label, + uint8_t *output, size_t *output_length) { int sx_status; size_t digestsz = sx_hash_get_alg_digestsz(hashalg); @@ -171,8 +171,8 @@ static void rsa_oaep_encrypt_init(struct rsa_oaep_workmem *workmem, size_t diges } int cracen_rsa_oaep_encrypt(const struct sxhashalg *hashalg, struct cracen_rsa_key *rsa_key, - struct cracen_crypt_text *text, struct sx_buf *label, uint8_t *output, - size_t *output_length) + struct cracen_crypt_text *text, struct sx_const_buf *label, + uint8_t *output, size_t *output_length) { int sx_status; psa_status_t psa_status = PSA_ERROR_CORRUPTION_DETECTED; diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsapss.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsapss.c index 96c1cff26384..82672eba9cba 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsapss.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsapss.c @@ -262,7 +262,7 @@ static void rsa_pss_verify_init(struct rsa_pss_workmem *workmem, size_t emsz, si } int cracen_rsa_pss_verify_message(struct cracen_rsa_key *rsa_key, - struct cracen_signature *signature, + struct cracen_const_signature *signature, const struct sxhashalg *hashalg, const uint8_t *message, size_t message_length, size_t saltsz) { @@ -278,7 +278,8 @@ int cracen_rsa_pss_verify_message(struct cracen_rsa_key *rsa_key, return cracen_rsa_pss_verify_digest(rsa_key, signature, hashalg, digest, digestsz, saltsz); } -int cracen_rsa_pss_verify_digest(struct cracen_rsa_key *rsa_key, struct cracen_signature *signature, +int cracen_rsa_pss_verify_digest(struct cracen_rsa_key *rsa_key, + struct cracen_const_signature *signature, const struct sxhashalg *hashalg, const uint8_t *digest, size_t digest_length, size_t saltsz) { diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsassa_pkcs1v15.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsassa_pkcs1v15.c index b06899d2fb19..e0f6a41f06a7 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsassa_pkcs1v15.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/rsassa_pkcs1v15.c @@ -196,7 +196,7 @@ int cracen_rsa_pkcs1v15_sign_digest(struct cracen_rsa_key *rsa_key, } int cracen_rsa_pkcs1v15_verify_message(struct cracen_rsa_key *rsa_key, - struct cracen_signature *signature, + struct cracen_const_signature *signature, const struct sxhashalg *hashalg, const uint8_t *message, size_t message_length) { @@ -213,7 +213,7 @@ int cracen_rsa_pkcs1v15_verify_message(struct cracen_rsa_key *rsa_key, } int cracen_rsa_pkcs1v15_verify_digest(struct cracen_rsa_key *rsa_key, - struct cracen_signature *signature, + struct cracen_const_signature *signature, const struct sxhashalg *hashalg, const uint8_t *digest, size_t digest_length) { @@ -288,7 +288,7 @@ int cracen_rsa_pkcs1v15_verify_digest(struct cracen_rsa_key *rsa_key, const uint8_t *const encodedmsgend = encodedmsgstart + modulussz; /* pointer used to walk through the EM */ - uint8_t *encmsg = (uint8_t *)encodedmsgstart; + const uint8_t *encmsg = (const uint8_t *)encodedmsgstart; /* invalid signature if first two bytes of EM are not 0x00 0x01 */ r = (sx_rdpkmem_byte(encmsg) != 0x00); diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c index 1c9e0a552d10..64bc1ebdddbb 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c @@ -524,7 +524,7 @@ static psa_status_t cracen_signature_rsa_verify(bool is_message, int sx_status; size_t key_bits_attr = psa_get_key_bits(attributes); struct cracen_rsa_key privkey = {0}; - struct cracen_signature sign = {0}; + struct cracen_const_signature sign = {.sz = signature_length, .r = signature}; struct sxhashalg hashalg = {0}; const struct sxhashalg *hashalgpointer = &hashalg; struct sx_buf modulus; @@ -567,8 +567,7 @@ static psa_status_t cracen_signature_rsa_verify(bool is_message, } else { return PSA_ERROR_NOT_SUPPORTED; } - sign.sz = signature_length; - sign.r = (uint8_t *)signature; + if (PSA_ALG_IS_RSA_PSS(alg) && IS_ENABLED(PSA_NEED_CRACEN_RSA_PSS)) { if (is_message) { sx_status = cracen_rsa_pss_verify_message(&privkey, &sign, hashalgpointer, diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/spake2p.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/spake2p.c index d5ab8f215169..69a4d338eca9 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/spake2p.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/spake2p.c @@ -25,10 +25,6 @@ #include #include -#define MAKE_SX_POINT(name, ptr, point_size) \ - sx_pk_affine_point name = {{.bytes = (ptr), .sz = (point_size) / 2}, \ - {.bytes = (ptr) + (point_size) / 2, .sz = (point_size) / 2}}; - /* * This driver supports uncompressed points only. Uncompressed types * are prefixed with the byte 0x04. See 2.3.3.3.3 from "SEC 1: @@ -136,8 +132,8 @@ static psa_status_t cracen_get_ZV(cracen_spake2p_operation_t *operation, uint8_t uint8_t w0N[CRACEN_P256_POINT_SIZE]; MAKE_SX_POINT(pt_n_w0N, w0N, CRACEN_P256_POINT_SIZE); - MAKE_SX_POINT(pt_NM, (uint8_t *)operation->NM, CRACEN_P256_POINT_SIZE); - sx_ecop w0 = {.bytes = operation->w0, .sz = sizeof(operation->w0)}; + MAKE_SX_CONST_POINT(pt_NM, operation->NM, CRACEN_P256_POINT_SIZE); + sx_const_ecop w0 = {.bytes = operation->w0, .sz = sizeof(operation->w0)}; /* w0 * N. */ status = sx_ecp_ptmult(operation->curve, &w0, &pt_NM, &pt_n_w0N); @@ -150,41 +146,48 @@ static psa_status_t cracen_get_ZV(cracen_spake2p_operation_t *operation, uint8_t const struct sx_pk_cmd_def *cmd = SX_PK_CMD_MOD_SUB; const uint8_t *field_size = sx_pk_field_size(operation->curve); - sx_op modulo = {.sz = CRACEN_P256_KEY_SIZE, .bytes = (uint8_t *)field_size}; + sx_const_op modulo = {.sz = CRACEN_P256_KEY_SIZE, .bytes = field_size}; uint8_t zeroes[CRACEN_P256_KEY_SIZE] = {0}; - sx_op a = {.sz = CRACEN_P256_KEY_SIZE, .bytes = zeroes}; - sx_op b = {.sz = CRACEN_P256_KEY_SIZE, .bytes = &w0N[CRACEN_P256_KEY_SIZE]}; + sx_const_op a = {.sz = CRACEN_P256_KEY_SIZE, .bytes = zeroes}; + sx_const_op b = {.sz = CRACEN_P256_KEY_SIZE, .bytes = &w0N[CRACEN_P256_KEY_SIZE]}; + sx_op res = {.sz = CRACEN_P256_KEY_SIZE, .bytes = &w0N[CRACEN_P256_KEY_SIZE]}; - status = sx_mod_primitive_cmd(NULL, cmd, &modulo, &a, &b, &b); + status = sx_mod_primitive_cmd(NULL, cmd, &modulo, &a, &b, &res); if (status) { return silex_statuscodes_to_psa(status); } /* Calculate Y + (- w0 * N) */ - MAKE_SX_POINT(pt_Y, operation->YX + 1, CRACEN_P256_POINT_SIZE); - status = sx_ecp_ptadd(operation->curve, &pt_Y, &pt_n_w0N, &pt_n_w0N); + MAKE_SX_CONST_POINT(pt_Y, operation->YX + 1, CRACEN_P256_POINT_SIZE); + sx_pk_const_affine_point c_pt_n_w0N; + + sx_get_const_affine_point(&pt_n_w0N, &c_pt_n_w0N); + status = sx_ecp_ptadd(operation->curve, &pt_Y, &c_pt_n_w0N, &pt_n_w0N); if (status) { return silex_statuscodes_to_psa(status); } /* Calculate Z = x * (previous result) */ - sx_ecop x = {.sz = CRACEN_P256_KEY_SIZE, .bytes = operation->xy}; + sx_const_ecop x = {.sz = CRACEN_P256_KEY_SIZE, .bytes = operation->xy}; + sx_get_const_affine_point(&pt_n_w0N, &c_pt_n_w0N); MAKE_SX_POINT(pt_Z, Z, CRACEN_P256_POINT_SIZE); - status = sx_ecp_ptmult(operation->curve, &x, &pt_n_w0N, &pt_Z); + status = sx_ecp_ptmult(operation->curve, &x, &c_pt_n_w0N, &pt_Z); if (status) { return silex_statuscodes_to_psa(status); } /* Calculate V */ MAKE_SX_POINT(pt_V, V, CRACEN_P256_POINT_SIZE); - MAKE_SX_POINT(pt_L, operation->w1_or_L, CRACEN_P256_POINT_SIZE); - sx_ecop k = {.bytes = operation->role == PSA_PAKE_ROLE_CLIENT ? operation->w1_or_L - : operation->xy, - .sz = CRACEN_P256_KEY_SIZE}; + MAKE_SX_CONST_POINT(pt_L, operation->w1_or_L, CRACEN_P256_POINT_SIZE); + sx_const_ecop k = {.bytes = operation->role == PSA_PAKE_ROLE_CLIENT ? operation->w1_or_L + : operation->xy, + .sz = CRACEN_P256_KEY_SIZE}; + sx_get_const_affine_point(&pt_n_w0N, &c_pt_n_w0N); status = sx_ecp_ptmult(operation->curve, &k, - operation->role == PSA_PAKE_ROLE_SERVER ? &pt_L : &pt_n_w0N, &pt_V); + operation->role == PSA_PAKE_ROLE_SERVER ? &pt_L + : &c_pt_n_w0N, &pt_V); if (status) { return silex_statuscodes_to_psa(status); } @@ -236,7 +239,7 @@ static psa_status_t cracen_get_confirmation_keys(cracen_spake2p_operation_t *ope goto exit; } status = psa_driver_wrapper_key_derivation_input_bytes( - &kdf_op, PSA_KEY_DERIVATION_INPUT_INFO, (uint8_t *)"SharedKey", 9); + &kdf_op, PSA_KEY_DERIVATION_INPUT_INFO, (const uint8_t *)"SharedKey", 9); if (status) { goto exit; } @@ -262,7 +265,7 @@ static psa_status_t cracen_get_confirmation_keys(cracen_spake2p_operation_t *ope goto exit; } status = psa_driver_wrapper_key_derivation_input_bytes( - &kdf_op, PSA_KEY_DERIVATION_INPUT_INFO, (uint8_t *)"ConfirmationKeys", 16); + &kdf_op, PSA_KEY_DERIVATION_INPUT_INFO, (const uint8_t *)"ConfirmationKeys", 16); if (status) { goto exit; } @@ -310,15 +313,16 @@ static psa_status_t cracen_get_confirmation(cracen_spake2p_operation_t *operatio } static psa_status_t cracen_p256_reduce(cracen_spake2p_operation_t *operation, - uint8_t *result_buffer, uint8_t *input, size_t input_length) + uint8_t *result_buffer, const uint8_t *input, + size_t input_length) { if (!input_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } const uint8_t *order = sx_pk_curve_order(operation->curve); - sx_op modulo = {.sz = CRACEN_P256_KEY_SIZE, .bytes = (uint8_t *)order}; - sx_op b = {.sz = input_length, .bytes = input}; + sx_const_op modulo = {.sz = CRACEN_P256_KEY_SIZE, .bytes = order}; + sx_const_op b = {.sz = input_length, .bytes = input}; sx_op result = {.sz = CRACEN_P256_KEY_SIZE, .bytes = result_buffer}; /* The nistp256 curve order (n) is prime so we use the ODD variant of the reduce @@ -397,7 +401,7 @@ static psa_status_t cracen_get_key_share(cracen_spake2p_operation_t *operation) MAKE_SX_POINT(pt_xP, xP, CRACEN_P256_POINT_SIZE); /* Calculate x * P */ - sx_ecop x = {.bytes = operation->xy, .sz = CRACEN_P256_KEY_SIZE}; + sx_const_ecop x = {.bytes = operation->xy, .sz = CRACEN_P256_KEY_SIZE}; status = sx_ecp_ptmult(operation->curve, &x, SX_PTMULT_CURVE_GENERATOR, &pt_xP); if (status != SX_OK) { @@ -405,18 +409,23 @@ static psa_status_t cracen_get_key_share(cracen_spake2p_operation_t *operation) } /* Calculate w0 * M */ - sx_ecop w0 = {.bytes = operation->w0, .sz = sizeof(operation->w0)}; + sx_const_ecop w0 = {.bytes = operation->w0, .sz = sizeof(operation->w0)}; MAKE_SX_POINT(pt_w0M, w0M, CRACEN_P256_POINT_SIZE); - MAKE_SX_POINT(pt_M, (uint8_t *)operation->MN, CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(pt_M, operation->MN, CRACEN_P256_POINT_SIZE); status = sx_ecp_ptmult(operation->curve, &w0, &pt_M, &pt_w0M); if (status != SX_OK) { return silex_statuscodes_to_psa(status); } /* Add the two previous results. */ + sx_pk_const_affine_point c_pt_w0M; + sx_pk_const_affine_point c_pt_xP; + + sx_get_const_affine_point(&pt_w0M, &c_pt_w0M); + sx_get_const_affine_point(&pt_xP, &c_pt_xP); MAKE_SX_POINT(pt_XY, operation->XY + 1, CRACEN_P256_POINT_SIZE); - status = sx_ecp_ptadd(operation->curve, &pt_w0M, &pt_xP, &pt_XY); + status = sx_ecp_ptadd(operation->curve, &c_pt_w0M, &c_pt_xP, &pt_XY); if (status != SX_OK) { return silex_statuscodes_to_psa(status); } @@ -501,13 +510,13 @@ static psa_status_t set_password_key(cracen_spake2p_operation_t *operation, /* Compute w0 and w1 according to spec. */ if (password_length == 2 * CRACEN_P256_KEY_SIZE) { /* Password contains: w0 || w1 */ - status = cracen_p256_reduce(operation, operation->w0, (uint8_t *)password, + status = cracen_p256_reduce(operation, operation->w0, password, password_length / 2); if (status != PSA_SUCCESS) { return status; } status = cracen_p256_reduce(operation, operation->w1_or_L, - (uint8_t *)password + password_length / 2, + password + password_length / 2, password_length / 2); if (status != PSA_SUCCESS) { return status; @@ -515,8 +524,12 @@ static psa_status_t set_password_key(cracen_spake2p_operation_t *operation, } else if (password_length == CRACEN_P256_POINT_SIZE + CRACEN_P256_KEY_SIZE + 1) { /* Password contains: w0 || L */ - status = cracen_p256_reduce(operation, operation->w0, (uint8_t *)password, + status = cracen_p256_reduce(operation, operation->w0, password, CRACEN_P256_KEY_SIZE); + if (status != PSA_SUCCESS) { + return status; + } + password += password_length - CRACEN_P256_POINT_SIZE; /* Verify that the L part of password is an uncompressed point. */ @@ -524,7 +537,7 @@ static psa_status_t set_password_key(cracen_spake2p_operation_t *operation, return PSA_ERROR_INVALID_ARGUMENT; } - MAKE_SX_POINT(pt, (uint8_t *)password, CRACEN_P256_POINT_SIZE); + MAKE_SX_CONST_POINT(pt, password, CRACEN_P256_POINT_SIZE); status = cracen_ecc_check_public_key(operation->curve, &pt); if (status != PSA_SUCCESS) { return status; @@ -624,7 +637,7 @@ static psa_status_t cracen_spake2p_get_L_from_w1(cracen_spake2p_operation_t *ope { int sx_status; - struct sx_buf w1 = {.sz = operation->curve->sz, .bytes = w1_buf}; + sx_const_ecop w1 = {.sz = operation->curve->sz, .bytes = w1_buf}; sx_pk_affine_point L_pnt = {.x = {.sz = w1.sz, .bytes = L_buf}, .y = {.sz = w1.sz, .bytes = L_buf + w1.sz}}; diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/srp.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/srp.c index 340dee6a0889..4a1a84699f1c 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/srp.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/srp.c @@ -55,9 +55,9 @@ static const uint8_t cracen_G3072[] = {5}; static psa_status_t calculate_v_from_k(const uint8_t *k, size_t k_size, uint8_t *v, size_t v_size) { - sx_op g = {.sz = sizeof(cracen_G3072), .bytes = (uint8_t *)cracen_G3072}; - sx_op a = {.sz = k_size, .bytes = (uint8_t *)k}; - sx_op modulo = {.sz = sizeof(cracen_N3072), .bytes = (uint8_t *)cracen_N3072}; + sx_const_op g = {.sz = sizeof(cracen_G3072), .bytes = cracen_G3072}; + sx_const_op a = {.sz = k_size, .bytes = k}; + sx_const_op modulo = {.sz = sizeof(cracen_N3072), .bytes = cracen_N3072}; sx_op result = {.sz = v_size, .bytes = v}; return silex_statuscodes_to_psa(sx_mod_exp(NULL, &g, &a, &modulo, &result)); @@ -196,9 +196,9 @@ static psa_status_t cracen_srp_calculate_client_key_share(cracen_srp_operation_t } /* g^a mod N */ - sx_op g = {.sz = sizeof(cracen_G3072), .bytes = (uint8_t *)cracen_G3072}; - sx_op a = {.sz = sizeof(operation->ab), .bytes = operation->ab}; - sx_op modulo = {.sz = sizeof(cracen_N3072), .bytes = (uint8_t *)cracen_N3072}; + sx_const_op g = {.sz = sizeof(cracen_G3072), .bytes = cracen_G3072}; + sx_const_op a = {.sz = sizeof(operation->ab), .bytes = operation->ab}; + sx_const_op modulo = {.sz = sizeof(cracen_N3072), .bytes = cracen_N3072}; sx_op result = {.sz = sizeof(operation->A), .bytes = operation->A}; int sx_status = sx_mod_exp(NULL, &g, &a, &modulo, &result); @@ -230,9 +230,9 @@ static psa_status_t cracen_srp_calculate_server_key_share(cracen_srp_operation_t } /* b' = g^b */ - sx_op g = {.sz = sizeof(cracen_G3072), .bytes = (uint8_t *)cracen_G3072}; - sx_op b = {.sz = sizeof(operation->ab), .bytes = operation->ab}; - sx_op modulo = {.sz = sizeof(cracen_N3072), .bytes = (uint8_t *)cracen_N3072}; + sx_const_op g = {.sz = sizeof(cracen_G3072), .bytes = cracen_G3072}; + sx_const_op b = {.sz = sizeof(operation->ab), .bytes = operation->ab}; + sx_const_op modulo = {.sz = sizeof(cracen_N3072), .bytes = cracen_N3072}; sx_op temp_b = {.sz = sizeof(temp_value), .bytes = temp_value}; int sx_status = sx_mod_exp(NULL, &g, &b, &modulo, &temp_b); @@ -254,8 +254,8 @@ static psa_status_t cracen_srp_calculate_server_key_share(cracen_srp_operation_t goto error; } /* kv mod N, using output as temp storage */ - sx_op k = {.sz = CRACEN_SRP_HASH_LENGTH, .bytes = k_value}; - sx_op v = {.sz = sizeof(operation->v), .bytes = operation->v}; + sx_const_op k = {.sz = CRACEN_SRP_HASH_LENGTH, .bytes = k_value}; + sx_const_op v = {.sz = sizeof(operation->v), .bytes = operation->v}; sx_op kv = {.sz = sizeof(temp_value_2), .bytes = temp_value_2}; const struct sx_pk_cmd_def *cmd_mul = SX_PK_CMD_ODD_MOD_MULT; @@ -267,9 +267,14 @@ static psa_status_t cracen_srp_calculate_server_key_share(cracen_srp_operation_t /* B = (kv + b') mod N */ sx_op result = {.sz = sizeof(operation->B), .bytes = operation->B}; + sx_const_op c_temp_b; + sx_const_op c_kv; + + sx_get_const_op(&temp_b, &c_temp_b); + sx_get_const_op(&kv, &c_kv); const struct sx_pk_cmd_def *cmd_add = SX_PK_CMD_MOD_ADD; - sx_status = sx_mod_primitive_cmd(NULL, cmd_add, &modulo, &kv, &temp_b, &result); + sx_status = sx_mod_primitive_cmd(NULL, cmd_add, &modulo, &c_kv, &c_temp_b, &result); status = silex_statuscodes_to_psa(sx_status); if (status != PSA_SUCCESS) { goto error; @@ -330,9 +335,9 @@ static psa_status_t cracen_srp_calculate_client_S(cracen_srp_operation_t *operat } /* g'= g^x mod N; using S as temp storage */ - sx_op g = {.sz = sizeof(cracen_G3072), .bytes = (uint8_t *)cracen_G3072}; - sx_op x = {.sz = sizeof(operation->x), .bytes = operation->x}; - sx_op modulo = {.sz = sizeof(cracen_N3072), .bytes = (uint8_t *)cracen_N3072}; + sx_const_op g = {.sz = sizeof(cracen_G3072), .bytes = cracen_G3072}; + sx_const_op x = {.sz = sizeof(operation->x), .bytes = operation->x}; + sx_const_op modulo = {.sz = sizeof(cracen_N3072), .bytes = cracen_N3072}; sx_op temp_g = {.sz = CRACEN_SRP_FIELD_SIZE, .bytes = S}; int sx_status = sx_mod_exp(NULL, &g, &x, &modulo, &temp_g); @@ -346,31 +351,40 @@ static psa_status_t cracen_srp_calculate_client_S(cracen_srp_operation_t *operat return status; } /* k is only a hash there only using the first bytes of the buffer */ - sx_op k = {.sz = CRACEN_SRP_HASH_LENGTH, .bytes = temp_value_0}; + sx_const_op k = {.sz = CRACEN_SRP_HASH_LENGTH, .bytes = temp_value_0}; sx_op kg = {.sz = sizeof(temp_value_1), .bytes = temp_value_1}; + sx_const_op c_temp_g; const struct sx_pk_cmd_def *cmd_mul = SX_PK_CMD_ODD_MOD_MULT; - sx_status = sx_mod_primitive_cmd(NULL, cmd_mul, &modulo, &k, &temp_g, &kg); + sx_get_const_op(&temp_g, &c_temp_g); + sx_status = sx_mod_primitive_cmd(NULL, cmd_mul, &modulo, &k, &c_temp_g, &kg); status = silex_statuscodes_to_psa(sx_status); if (status != PSA_SUCCESS) { return silex_statuscodes_to_psa(sx_status); } /* B' = (B - kg) mod N */ - sx_op B = {.sz = sizeof(operation->B), .bytes = operation->B}; + sx_const_op B = {.sz = sizeof(operation->B), .bytes = operation->B}; sx_op temp_b = {.sz = CRACEN_SRP_FIELD_SIZE, .bytes = S}; + sx_const_op c_kg; const struct sx_pk_cmd_def *cmd_sub = SX_PK_CMD_MOD_SUB; - sx_status = sx_mod_primitive_cmd(NULL, cmd_sub, &modulo, &B, &kg, &temp_b); + sx_get_const_op(&kg, &c_kg); + sx_status = sx_mod_primitive_cmd(NULL, cmd_sub, &modulo, &B, &c_kg, &temp_b); if (sx_status != SX_OK) { return silex_statuscodes_to_psa(sx_status); } /* t_1 = (B')^a mod N */ - sx_op a = {.sz = sizeof(operation->ab), .bytes = operation->ab}; + sx_const_op c_temp_b; + sx_const_op a = {.sz = sizeof(operation->ab), .bytes = operation->ab}; sx_op temp_1 = {.sz = sizeof(temp_value_1), .bytes = temp_value_1}; - sx_status = sx_mod_exp(NULL, &temp_b, &a, &modulo, &temp_1); + sx_get_const_op(&temp_b, &c_temp_b); + sx_status = sx_mod_exp(NULL, &c_temp_b, &a, &modulo, &temp_1); + if (sx_status != SX_OK) { + return silex_statuscodes_to_psa(sx_status); + } /* get u */ status = cracen_srp_calculate_u(operation, temp_value_0, sizeof(temp_value_0)); @@ -379,26 +393,32 @@ static psa_status_t cracen_srp_calculate_client_S(cracen_srp_operation_t *operat } /* t_2 = (B')^u mod N */ - sx_op u = {.sz = CRACEN_SRP_HASH_LENGTH, .bytes = temp_value_0}; + sx_const_op u = {.sz = CRACEN_SRP_HASH_LENGTH, .bytes = temp_value_0}; sx_op temp_2 = {.sz = CRACEN_SRP_FIELD_SIZE, .bytes = S}; - sx_status = sx_mod_exp(NULL, &temp_b, &u, &modulo, &temp_2); + sx_status = sx_mod_exp(NULL, &c_temp_b, &u, &modulo, &temp_2); if (sx_status != SX_OK) { return silex_statuscodes_to_psa(sx_status); } /* t_3 = (t_2)^x mod N = ((B')^u)^x mod N = (B')^(ux) mod N */ + sx_const_op c_temp_2; sx_op temp_3 = {.sz = sizeof(temp_value_0), .bytes = temp_value_0}; - sx_status = sx_mod_exp(NULL, &temp_2, &x, &modulo, &temp_3); + sx_get_const_op(&temp_2, &c_temp_2); + sx_status = sx_mod_exp(NULL, &c_temp_2, &x, &modulo, &temp_3); if (sx_status != SX_OK) { return silex_statuscodes_to_psa(sx_status); } /* B = t_1 * t_3 mod N */ + sx_const_op c_temp_1; + sx_const_op c_temp_3; sx_op result = {.sz = CRACEN_SRP_FIELD_SIZE, .bytes = S}; - sx_status = sx_mod_primitive_cmd(NULL, cmd_mul, &modulo, &temp_1, &temp_3, &result); + sx_get_const_op(&temp_1, &c_temp_1); + sx_get_const_op(&temp_3, &c_temp_3); + sx_status = sx_mod_primitive_cmd(NULL, cmd_mul, &modulo, &c_temp_1, &c_temp_3, &result); return silex_statuscodes_to_psa(sx_status); } @@ -421,9 +441,9 @@ static psa_status_t cracen_srp_calculate_server_S(cracen_srp_operation_t *operat } /* t_1 = v^u mod N */ - sx_op v = {.sz = sizeof(operation->v), .bytes = operation->v}; - sx_op u = {.sz = sizeof(u_buffer), .bytes = u_buffer}; - sx_op modulo = {.sz = sizeof(cracen_N3072), .bytes = (uint8_t *)cracen_N3072}; + sx_const_op v = {.sz = sizeof(operation->v), .bytes = operation->v}; + sx_const_op u = {.sz = sizeof(u_buffer), .bytes = u_buffer}; + sx_const_op modulo = {.sz = sizeof(cracen_N3072), .bytes = cracen_N3072}; sx_op temp_1 = {.sz = CRACEN_SRP_FIELD_SIZE, .bytes = S}; int sx_status = sx_mod_exp(NULL, &v, &u, &modulo, &temp_1); @@ -433,19 +453,23 @@ static psa_status_t cracen_srp_calculate_server_S(cracen_srp_operation_t *operat /* t_2 = A * t_1 mod N = (Av^u) mod N */ sx_op temp_2 = {.sz = sizeof(temp_value), .bytes = temp_value}; - sx_op A = {.sz = sizeof(operation->A), .bytes = operation->A}; + sx_const_op A = {.sz = sizeof(operation->A), .bytes = operation->A}; + sx_const_op c_temp_1; const struct sx_pk_cmd_def *cmd_mul = SX_PK_CMD_ODD_MOD_MULT; - sx_status = sx_mod_primitive_cmd(NULL, cmd_mul, &modulo, &A, &temp_1, &temp_2); + sx_get_const_op(&temp_1, &c_temp_1); + sx_status = sx_mod_primitive_cmd(NULL, cmd_mul, &modulo, &A, &c_temp_1, &temp_2); if (sx_status != SX_OK) { return silex_statuscodes_to_psa(sx_status); } /* t_2^b mod N = (Av^u)^b mod N = S */ - sx_op b = {.sz = sizeof(operation->ab), .bytes = operation->ab}; + sx_const_op b = {.sz = sizeof(operation->ab), .bytes = operation->ab}; sx_op result = {.sz = CRACEN_SRP_FIELD_SIZE, .bytes = S}; + sx_const_op c_temp_2; - sx_status = sx_mod_exp(NULL, &temp_2, &b, &modulo, &result); + sx_get_const_op(&temp_2, &c_temp_2); + sx_status = sx_mod_exp(NULL, &c_temp_2, &b, &modulo, &result); return silex_statuscodes_to_psa(sx_status); } diff --git a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxbuf/sxbufop.h b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxbuf/sxbufop.h index dc8fb911963a..3dbaea8033bb 100644 --- a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxbuf/sxbufop.h +++ b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxbuf/sxbufop.h @@ -13,6 +13,16 @@ #include #include +#define PREPARE_SX_POINT(type, name, ptr, point_size) \ + type name = {{.bytes = (ptr), .sz = (point_size) / 2}, \ + {.bytes = (ptr) + (point_size) / 2, .sz = (point_size) / 2}} + +#define MAKE_SX_POINT(name, ptr, point_size) \ + PREPARE_SX_POINT(sx_pk_affine_point, name, ptr, point_size) + +#define MAKE_SX_CONST_POINT(name, ptr, point_size) \ + PREPARE_SX_POINT(sx_pk_const_affine_point, name, ptr, point_size) + /** Basic operand representation **/ struct sx_buf { /** Size in bytes of operand **/ @@ -20,11 +30,20 @@ struct sx_buf { /** Memory of operand bytes in big endian **/ uint8_t *bytes; }; -/** Simple "sxops" implementation based on sx_buf**/ + +struct sx_const_buf { + /** Size in bytes of operand **/ + size_t sz; + /** Memory of operand bytes in big endian **/ + const uint8_t *bytes; +}; +/** Simple "sxops" implementation based on sx_buf and sx_const_buf**/ typedef struct sx_buf sx_op; +typedef struct sx_const_buf sx_const_op; /** Simple Elliptic Curve operand implementation based on sx_buf**/ typedef struct sx_buf sx_ecop; +typedef struct sx_const_buf sx_const_ecop; /** Affine point for ECC **/ typedef struct sx_pk_affine_point { @@ -34,4 +53,37 @@ typedef struct sx_pk_affine_point { sx_ecop y; } sx_pk_affine_point; +typedef struct sx_pk_const_affine_point { + /** x-coordinate of const affine point */ + sx_const_ecop x; + /** y-coordinate of const affine point */ + sx_const_ecop y; +} sx_pk_const_affine_point; + +/** Initializes sx_const_op with values from provided sx_op + * + * @param[in] source_op Source sx operand + * @param[out] dest_op Destination operand initialized from source + */ +static inline void sx_get_const_op(const sx_op *source_op, sx_const_op *dest_op) +{ + dest_op->sz = source_op->sz; + dest_op->bytes = source_op->bytes; +} + +/** Initializes sx_pk_const_affine_point with values from provided sx_pk_affine_point + * + * @param[in] source_point Source affine point + * @param[out] dest_point Destination affine point initialized from source + */ +static inline void sx_get_const_affine_point(const sx_pk_affine_point *source_point, + sx_pk_const_affine_point *dest_point) +{ + dest_point->x.sz = source_point->x.sz; + dest_point->x.bytes = source_point->x.bytes; + + dest_point->y.sz = source_point->y.sz; + dest_point->y.bytes = source_point->y.bytes; +} + #endif diff --git a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/adapter.h b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/adapter.h index 8ccbea5f9187..703d7225e865 100644 --- a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/adapter.h +++ b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/adapter.h @@ -19,14 +19,14 @@ * @param[in] mem Memory address to write the operand to * @param[in] sz Size in bytes of the operand */ -void sx_pk_ecop2mem(const sx_ecop *op, uint8_t *mem, int sz); +void sx_pk_ecop2mem(const sx_const_ecop *op, uint8_t *mem, int sz); /** Write the operand into memory which has the exact size needed * * @param[in] op Operand written to memory. Data should be in big endian * @param[in] mem Memory address to write the operand to */ -void sx_pk_op2vmem(const sx_op *op, uint8_t *mem); +void sx_pk_op2vmem(const sx_const_op *op, uint8_t *mem); /** Convert raw bytes to operand * @@ -65,7 +65,7 @@ void sx_pk_mem2affpt(const uint8_t *mem_x, const uint8_t *mem_y, int sz, sx_pk_a * @param[in] mem_y Memory address to write the y-coordinate of the operand to * @param[in] sz Size in bytes of a single coordinate */ -void sx_pk_affpt2mem(const sx_pk_affine_point *op, uint8_t *mem_x, uint8_t *mem_y, int sz); +void sx_pk_affpt2mem(const sx_pk_const_affine_point *op, uint8_t *mem_x, uint8_t *mem_y, int sz); /** Return the size in bytes of the operand. * @@ -74,4 +74,11 @@ void sx_pk_affpt2mem(const sx_pk_affine_point *op, uint8_t *mem_x, uint8_t *mem_ */ int sx_op_size(const sx_op *op); +/** Return the size in bytes of the const operand. + * + * @param[in] op Const operand + * @return Operand size in bytes + */ +int sx_const_op_size(const sx_const_op *op); + #endif diff --git a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/dsa.h b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/dsa.h index 7b50063619f1..45e77a128540 100644 --- a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/dsa.h +++ b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/dsa.h @@ -61,10 +61,11 @@ struct sx_pk_cmd_def; * * @see sx_dsa_sign() for a synchronous version */ -static inline struct sx_pk_acq_req sx_async_dsa_sign_go(struct sx_pk_cnx *cnx, const sx_op *p, - const sx_op *q, const sx_op *g, - const sx_op *k, const sx_op *privkey, - const sx_op *h) +static inline struct sx_pk_acq_req sx_async_dsa_sign_go(struct sx_pk_cnx *cnx, const sx_const_op *p, + const sx_const_op *q, const sx_const_op *g, + const sx_const_op *k, + const sx_const_op *privkey, + const sx_const_op *h) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_dsa_sign inputs; @@ -76,8 +77,8 @@ static inline struct sx_pk_acq_req sx_async_dsa_sign_go(struct sx_pk_cnx *cnx, c /* convert and transfer operands */ int sizes[] = { - sx_op_size(p), sx_op_size(q), sx_op_size(g), - sx_op_size(k), sx_op_size(privkey), sx_op_size(h), + sx_const_op_size(p), sx_const_op_size(q), sx_const_op_size(g), + sx_const_op_size(k), sx_const_op_size(privkey), sx_const_op_size(h), }; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { @@ -173,10 +174,11 @@ int sx_dsa_sign(struct sx_pk_cnx *cnx, const sx_op *p, const sx_op *q, const sx_ * * @see sx_dsa_ver() for a synchronous version */ -static inline struct sx_pk_acq_req sx_async_dsa_ver_go(struct sx_pk_cnx *cnx, const sx_op *p, - const sx_op *q, const sx_op *g, - const sx_op *pubkey, const sx_op *h, - const sx_op *r, const sx_op *s) +static inline struct sx_pk_acq_req sx_async_dsa_ver_go(struct sx_pk_cnx *cnx, const sx_const_op *p, + const sx_const_op *q, const sx_const_op *g, + const sx_const_op *pubkey, + const sx_const_op *h, const sx_const_op *r, + const sx_const_op *s) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_dsa_ver inputs; @@ -188,8 +190,9 @@ static inline struct sx_pk_acq_req sx_async_dsa_ver_go(struct sx_pk_cnx *cnx, co /* convert and transfer operands */ int sizes[] = { - sx_op_size(p), sx_op_size(q), sx_op_size(g), sx_op_size(pubkey), - sx_op_size(h), sx_op_size(r), sx_op_size(s), + sx_const_op_size(p), sx_const_op_size(q), sx_const_op_size(g), + sx_const_op_size(pubkey), sx_const_op_size(h), sx_const_op_size(r), + sx_const_op_size(s), }; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { diff --git a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/eccweierstrass.h b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/eccweierstrass.h index 5dfb937a4334..fbf91499e030 100644 --- a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/eccweierstrass.h +++ b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/eccweierstrass.h @@ -79,8 +79,9 @@ struct sx_pk_ecurve; * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req sx_async_ecdsa_generate_go(const struct sx_pk_ecurve *curve, - const sx_ecop *d, const sx_ecop *k, - const sx_ecop *h) + const sx_const_op *d, + const sx_const_op *k, + const sx_const_op *h) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecdsa_generate inputs; @@ -160,8 +161,9 @@ static inline void sx_async_ecdsa_generate_end(sx_pk_req *req, sx_ecop *r, sx_ec * @see sx_async_ecdsa_generate_go(), sx_async_ecdsa_generate_end() for * an asynchronous version */ -static inline int sx_ecdsa_generate(const struct sx_pk_ecurve *curve, const sx_ecop *d, - const sx_ecop *k, const sx_ecop *h, sx_ecop *r, sx_ecop *s) +static inline int sx_ecdsa_generate(const struct sx_pk_ecurve *curve, const sx_const_ecop *d, + const sx_const_ecop *k, const sx_const_ecop *h, sx_ecop *r, + sx_ecop *s) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -203,10 +205,9 @@ static inline int sx_ecdsa_generate(const struct sx_pk_ecurve *curve, const sx_e * * @return Acquired acceleration request for this operation */ -static inline struct sx_pk_acq_req sx_async_ecdsa_verify_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *q, - const sx_ecop *r, const sx_ecop *s, - const sx_ecop *h) +static inline struct sx_pk_acq_req +sx_async_ecdsa_verify_go(const struct sx_pk_ecurve *curve, const sx_pk_const_affine_point *q, + const sx_const_ecop *r, const sx_const_ecop *s, const sx_const_ecop *h) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecdsa_verify inputs; @@ -269,8 +270,9 @@ static inline struct sx_pk_acq_req sx_async_ecdsa_verify_go(const struct sx_pk_e * * @see sx_async_ecdsa_verify_go() for an asynchronous version */ -static inline int sx_ecdsa_verify(const struct sx_pk_ecurve *curve, const sx_pk_affine_point *q, - const sx_ecop *r, const sx_ecop *s, const sx_ecop *h) +static inline int sx_ecdsa_verify(const struct sx_pk_ecurve *curve, + const sx_pk_const_affine_point *q, const sx_const_ecop *r, + const sx_const_ecop *s, const sx_const_ecop *h) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -317,8 +319,8 @@ static inline int sx_ecdsa_verify(const struct sx_pk_ecurve *curve, const sx_pk_ * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req sx_async_ecp_mult_go(const struct sx_pk_ecurve *curve, - const sx_ecop *k, - const sx_pk_affine_point *p) + const sx_const_ecop *k, + const sx_pk_const_affine_point *p) { struct sx_pk_acq_req pkreq; @@ -389,8 +391,8 @@ static inline void sx_async_ecp_mult_end(sx_pk_req *req, sx_pk_affine_point *r) * @see sx_async_ecp_mult_go(), sx_async_ecp_mult_end() * for an asynchronous versions */ -static inline int sx_ecp_ptmult(const struct sx_pk_ecurve *curve, const sx_ecop *k, - const sx_pk_affine_point *p, sx_pk_affine_point *r) +static inline int sx_ecp_ptmult(const struct sx_pk_ecurve *curve, const sx_const_ecop *k, + const sx_pk_const_affine_point *p, sx_pk_affine_point *r) { int status; struct sx_pk_acq_req pkreq; @@ -430,7 +432,7 @@ static inline int sx_ecp_ptmult(const struct sx_pk_ecurve *curve, const sx_ecop * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req sx_async_ecp_double_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *p) + const sx_pk_const_affine_point *p) { struct sx_pk_acq_req pkreq; @@ -496,7 +498,7 @@ static inline void sx_async_ecp_double_end(sx_pk_req *req, sx_pk_affine_point *r * @see sx_async_ecp_double_go(), sx_async_ecp_double_end() * for an asynchronous verion */ -static inline int sx_ecp_double(const struct sx_pk_ecurve *curve, const sx_pk_affine_point *p, +static inline int sx_ecp_double(const struct sx_pk_ecurve *curve, const sx_pk_const_affine_point *p, sx_pk_affine_point *r) { int status; @@ -528,7 +530,7 @@ static inline int sx_ecp_double(const struct sx_pk_ecurve *curve, const sx_pk_af * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req sx_async_ec_ptoncurve_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *p) + const sx_pk_const_affine_point *p) { struct sx_pk_acq_req pkreq; @@ -581,7 +583,8 @@ static inline struct sx_pk_acq_req sx_async_ec_ptoncurve_go(const struct sx_pk_e * @return ::SX_ERR_EXPIRED * @return ::SX_ERR_PK_RETRY */ -static inline int sx_ec_ptoncurve(const struct sx_pk_ecurve *curve, const sx_pk_affine_point *p) +static inline int sx_ec_ptoncurve(const struct sx_pk_ecurve *curve, + const sx_pk_const_affine_point *p) { int status; struct sx_pk_acq_req pkreq; @@ -612,8 +615,9 @@ static inline int sx_ec_ptoncurve(const struct sx_pk_ecurve *curve, const sx_pk_ * * @return Acquired acceleration request for this operation */ -static inline struct sx_pk_acq_req -sx_async_ec_pt_decompression_go(const struct sx_pk_ecurve *curve, const sx_ecop *x, const int y_lsb) +static inline struct sx_pk_acq_req sx_async_ec_pt_decompression_go(const struct sx_pk_ecurve *curve, + const sx_const_ecop *x, + const int y_lsb) { struct sx_pk_acq_req pkreq; @@ -682,7 +686,7 @@ static inline void sx_async_ec_pt_decompression_end(sx_pk_req *req, sx_ecop *y) * @return ::SX_ERR_EXPIRED * @return ::SX_ERR_PK_RETRY */ -static inline int sx_ec_pt_decompression(const struct sx_pk_ecurve *curve, const sx_ecop *x, +static inline int sx_ec_pt_decompression(const struct sx_pk_ecurve *curve, const sx_const_ecop *x, const int y_lsb, sx_ecop *y) { int status; @@ -728,7 +732,7 @@ static inline int sx_ec_pt_decompression(const struct sx_pk_ecurve *curve, const * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req -sx_async_eckcdsa_pubkey_generate_go(const struct sx_pk_ecurve *curve, const sx_ecop *d) +sx_async_eckcdsa_pubkey_generate_go(const struct sx_pk_ecurve *curve, const sx_const_ecop *d) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_eckcdsa_generate inputs; @@ -796,8 +800,8 @@ static inline void sx_async_eckcdsa_pubkey_generate_end(sx_pk_req *req, sx_pk_af * @see sx_async_eckcdsa_pubkey_generate_go(), * sx_async_eckcdsa_pubkey_generate_end() for an asynchronous verion */ -static inline int sx_eckcdsa_pubkey_generate(const struct sx_pk_ecurve *curve, const sx_op *d, - sx_pk_affine_point *q) +static inline int sx_eckcdsa_pubkey_generate(const struct sx_pk_ecurve *curve, + const sx_const_ecop *d, sx_pk_affine_point *q) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -841,9 +845,9 @@ static inline int sx_eckcdsa_pubkey_generate(const struct sx_pk_ecurve *curve, c * * @return Acquired acceleration request for this operation */ -static inline struct sx_pk_acq_req sx_async_eckcdsa_sign_go(const struct sx_pk_ecurve *curve, - const sx_ecop *d, const sx_ecop *k, - const sx_ecop *h, const sx_ecop *r) +static inline struct sx_pk_acq_req +sx_async_eckcdsa_sign_go(const struct sx_pk_ecurve *curve, const sx_const_ecop *d, + const sx_const_ecop *k, const sx_const_ecop *h, const sx_const_ecop *r) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_eckcdsa_sign inputs; @@ -921,8 +925,9 @@ static inline void sx_async_eckcdsa_sign_end(sx_pk_req *req, sx_ecop *s) * @see sx_async_eckcdsa_sign_go(), sx_async_eckcdsa_sign_end() * for an asynchronous verion */ -static inline int sx_eckcdsa_sign(const struct sx_pk_ecurve *curve, const sx_ecop *d, - const sx_ecop *k, const sx_ecop *h, const sx_ecop *r, sx_ecop *s) +static inline int sx_eckcdsa_sign(const struct sx_pk_ecurve *curve, const sx_const_ecop *d, + const sx_const_ecop *k, const sx_const_ecop *h, + const sx_const_ecop *r, sx_ecop *s) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -955,10 +960,9 @@ static inline int sx_eckcdsa_sign(const struct sx_pk_ecurve *curve, const sx_eco * * @return Acquired acceleration request for this operation */ -static inline struct sx_pk_acq_req sx_async_eckcdsa_verify_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *q, - const sx_ecop *r, const sx_ecop *s, - const sx_ecop *h) +static inline struct sx_pk_acq_req +sx_async_eckcdsa_verify_go(const struct sx_pk_ecurve *curve, const sx_pk_const_affine_point *q, + const sx_const_ecop *r, const sx_const_ecop *s, const sx_const_ecop *h) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecdsa_verify inputs; @@ -1040,8 +1044,9 @@ static inline void sx_async_eckcdsa_verify_end(sx_pk_req *req, sx_pk_affine_poin * @see sx_async_eckcdsa_verify_go(), sx_async_eckcdsa_verify_end() * for an asynchronous version */ -static inline int sx_eckcdsa_verify(const struct sx_pk_ecurve *curve, const sx_pk_affine_point *q, - const sx_ecop *r, const sx_ecop *s, const sx_ecop *h, +static inline int sx_eckcdsa_verify(const struct sx_pk_ecurve *curve, + const sx_pk_const_affine_point *q, const sx_const_ecop *r, + const sx_const_ecop *s, const sx_const_ecop *h, sx_pk_affine_point *w) { uint32_t status; @@ -1080,8 +1085,8 @@ static inline int sx_eckcdsa_verify(const struct sx_pk_ecurve *curve, const sx_p * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req sx_async_ecp_add_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *p1, - const sx_pk_affine_point *p2) + const sx_pk_const_affine_point *p1, + const sx_pk_const_affine_point *p2) { struct sx_pk_acq_req pkreq; @@ -1153,8 +1158,8 @@ static inline void sx_async_ecp_add_end(sx_pk_req *req, sx_pk_affine_point *r) * @remark Use point doubling operation for the addition of equal points * @see sx_ecp_double() */ -static inline int sx_ecp_ptadd(const struct sx_pk_ecurve *curve, const sx_pk_affine_point *p1, - const sx_pk_affine_point *p2, sx_pk_affine_point *r) +static inline int sx_ecp_ptadd(const struct sx_pk_ecurve *curve, const sx_pk_const_affine_point *p1, + const sx_pk_const_affine_point *p2, sx_pk_affine_point *r) { int status; struct sx_pk_acq_req pkreq; @@ -1185,7 +1190,7 @@ static inline int sx_ecp_ptadd(const struct sx_pk_ecurve *curve, const sx_pk_aff * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req sx_async_ecp_check_order_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *p) + const sx_pk_const_affine_point *p) { struct sx_pk_acq_req pkreq; @@ -1242,8 +1247,9 @@ static inline struct sx_pk_acq_req sx_async_ecp_check_order_go(const struct sx_p * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req sx_async_sm2_generate_go(const struct sx_pk_ecurve *curve, - const sx_ecop *d, const sx_ecop *k, - const sx_ecop *h) + const sx_const_ecop *d, + const sx_const_ecop *k, + const sx_const_ecop *h) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecdsa_generate inputs; @@ -1321,8 +1327,9 @@ static inline void sx_async_sm2_generate_end(sx_pk_req *req, sx_ecop *r, sx_ecop * @return ::SX_ERR_EXPIRED * @return ::SX_ERR_PK_RETRY */ -static inline int sx_sm2_generate(const struct sx_pk_ecurve *curve, const sx_ecop *d, - const sx_ecop *k, const sx_ecop *h, sx_ecop *r, sx_ecop *s) +static inline int sx_sm2_generate(const struct sx_pk_ecurve *curve, const sx_const_ecop *d, + const sx_const_ecop *k, const sx_const_ecop *h, sx_ecop *r, + sx_ecop *s) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -1364,10 +1371,9 @@ static inline int sx_sm2_generate(const struct sx_pk_ecurve *curve, const sx_eco * * @return Acquired acceleration request for this operation */ -static inline struct sx_pk_acq_req sx_async_sm2_verify_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *q, - const sx_ecop *r, const sx_ecop *s, - const sx_ecop *h) +static inline struct sx_pk_acq_req +sx_async_sm2_verify_go(const struct sx_pk_ecurve *curve, const sx_pk_const_affine_point *q, + const sx_const_ecop *r, const sx_const_ecop *s, const sx_const_ecop *h) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecdsa_verify inputs; @@ -1425,8 +1431,9 @@ static inline struct sx_pk_acq_req sx_async_sm2_verify_go(const struct sx_pk_ecu * @return ::SX_ERR_EXPIRED * @return ::SX_ERR_PK_RETRY */ -static inline int sx_sm2_verify(const struct sx_pk_ecurve *curve, const sx_pk_affine_point *q, - const sx_ecop *r, const sx_ecop *s, const sx_ecop *h) +static inline int sx_sm2_verify(const struct sx_pk_ecurve *curve, const sx_pk_const_affine_point *q, + const sx_const_ecop *r, const sx_const_ecop *s, + const sx_const_ecop *h) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -1467,9 +1474,10 @@ static inline int sx_sm2_verify(const struct sx_pk_ecurve *curve, const sx_pk_af * @see sx_async_sm2_exchange_end() */ static inline struct sx_pk_acq_req -sx_async_sm2_exchange_go(const struct sx_pk_ecurve *curve, const sx_ecop *d, const sx_ecop *k, - const sx_pk_affine_point *q, const sx_pk_affine_point *rb, - const sx_ecop *cof, const sx_ecop *rax, const sx_ecop *exp2_w) +sx_async_sm2_exchange_go(const struct sx_pk_ecurve *curve, const sx_const_ecop *d, + const sx_const_ecop *k, const sx_pk_const_affine_point *q, + const sx_pk_const_affine_point *rb, const sx_const_ecop *cof, + const sx_const_ecop *rax, const sx_const_ecop *exp2_w) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_sm2_exchange inputs; @@ -1555,10 +1563,11 @@ static inline void sx_async_sm2_exchange_end(sx_pk_req *req, sx_pk_affine_point * @return ::SX_ERR_EXPIRED * @return ::SX_ERR_PK_RETRY */ -static inline int sx_sm2_exchange(const struct sx_pk_ecurve *curve, const sx_ecop *d, - const sx_ecop *k, const sx_pk_affine_point *q, - const sx_pk_affine_point *rb, const sx_ecop *cof, - const sx_ecop *rax, const sx_ecop *exp2_w, sx_pk_affine_point *u) +static inline int sx_sm2_exchange(const struct sx_pk_ecurve *curve, const sx_const_ecop *d, + const sx_const_ecop *k, const sx_pk_const_affine_point *q, + const sx_pk_const_affine_point *rb, const sx_const_ecop *cof, + const sx_const_ecop *rax, const sx_const_ecop *exp2_w, + sx_pk_affine_point *u) { uint32_t status; struct sx_pk_acq_req pkreq; diff --git a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/ecjpake.h b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/ecjpake.h index 3fdaeab57d8d..d6018d40f43d 100644 --- a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/ecjpake.h +++ b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/ecjpake.h @@ -67,8 +67,9 @@ struct sx_pk_ecurve; * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req sx_ecjpake_generate_zkp_go(const struct sx_pk_ecurve *curve, - const sx_ecop *v, const sx_ecop *x, - const sx_ecop *h) + const sx_const_ecop *v, + const sx_const_ecop *x, + const sx_const_ecop *h) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecjpake_generate_zkp inputs; @@ -139,8 +140,9 @@ static inline void sx_ecjpake_generate_zkp_end(sx_pk_req *req, sx_ecop *r) * @see sx_async_ecjpake_generate_zkp_go(), sx_async_ecjpake_generate_zkp_end() * for an asynchronous version */ -static inline int sx_ecjpake_generate_zkp(const struct sx_pk_ecurve *curve, const sx_ecop *v, - const sx_ecop *x, const sx_ecop *h, sx_ecop *r) +static inline int sx_ecjpake_generate_zkp(const struct sx_pk_ecurve *curve, const sx_const_ecop *v, + const sx_const_ecop *x, const sx_const_ecop *h, + sx_ecop *r) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -177,11 +179,10 @@ static inline int sx_ecjpake_generate_zkp(const struct sx_pk_ecurve *curve, cons * * @return Acquired acceleration request for this operation */ -static inline struct sx_pk_acq_req sx_ecjpake_verify_zkp_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *v, - const sx_pk_affine_point *x, - const sx_ecop *r, const sx_ecop *h, - const sx_pk_affine_point *g) +static inline struct sx_pk_acq_req +sx_ecjpake_verify_zkp_go(const struct sx_pk_ecurve *curve, const sx_pk_const_affine_point *v, + const sx_pk_const_affine_point *x, const sx_const_ecop *r, + const sx_const_ecop *h, const sx_pk_const_affine_point *g) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecjpake_verify_zkp inputs; @@ -271,9 +272,9 @@ static inline void sx_ecjpake_verify_zkp_end(sx_pk_req *req) * an asynchronous version */ static inline int sx_ecjpake_verify_zkp(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *v, const sx_pk_affine_point *x, - const sx_ecop *r, const sx_ecop *h, - const sx_pk_affine_point *g) + const sx_pk_const_affine_point *v, + const sx_pk_const_affine_point *x, const sx_const_ecop *r, + const sx_const_ecop *h, const sx_pk_const_affine_point *g) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -309,9 +310,9 @@ static inline int sx_ecjpake_verify_zkp(const struct sx_pk_ecurve *curve, * */ static inline struct sx_pk_acq_req sx_ecjpake_3pt_add_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *a, - const sx_pk_affine_point *b, - const sx_pk_affine_point *c) + const sx_pk_const_affine_point *a, + const sx_pk_const_affine_point *b, + const sx_pk_const_affine_point *c) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecjpake_3pt_add inputs; @@ -389,9 +390,10 @@ static inline void sx_ecjpake_3pt_add_end(sx_pk_req *req, sx_pk_affine_point *gb * @see sx_async_ecjpake_verify_zkp_go(), sx_async_ecjpake_verify_zkp_end() for * an asynchronous version */ -static inline int sx_ecjpake_3pt_add(const struct sx_pk_ecurve *curve, const sx_pk_affine_point *a, - const sx_pk_affine_point *b, const sx_pk_affine_point *c, - sx_pk_affine_point *gb) +static inline int sx_ecjpake_3pt_add(const struct sx_pk_ecurve *curve, + const sx_pk_const_affine_point *a, + const sx_pk_const_affine_point *b, + const sx_pk_const_affine_point *c, sx_pk_affine_point *gb) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -427,9 +429,10 @@ static inline int sx_ecjpake_3pt_add(const struct sx_pk_ecurve *curve, const sx_ * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req sx_ecjpake_gen_sess_key_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *x4, - const sx_pk_affine_point *b, - const sx_ecop *x2, const sx_ecop *x2s) + const sx_pk_const_affine_point *x4, + const sx_pk_const_affine_point *b, + const sx_const_ecop *x2, + const sx_const_ecop *x2s) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecjpake_gen_sess_key inputs; @@ -510,8 +513,9 @@ static inline void sx_ecjpake_gen_sess_key_end(sx_pk_req *req, sx_pk_affine_poin * for an asynchronous version */ static inline int sx_ecjpake_gen_sess_key(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *x4, const sx_pk_affine_point *b, - const sx_ecop *x2, const sx_ecop *x2s, + const sx_pk_const_affine_point *x4, + const sx_pk_const_affine_point *b, + const sx_const_ecop *x2, const sx_const_ecop *x2s, sx_pk_affine_point *t) { uint32_t status; @@ -548,11 +552,10 @@ static inline int sx_ecjpake_gen_sess_key(const struct sx_pk_ecurve *curve, * * @return Acquired acceleration request for this operation */ -static inline struct sx_pk_acq_req sx_ecjpake_gen_step_2_go(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *x4, - const sx_pk_affine_point *x3, - const sx_pk_affine_point *x1, - const sx_ecop *x2, const sx_ecop *s) +static inline struct sx_pk_acq_req +sx_ecjpake_gen_step_2_go(const struct sx_pk_ecurve *curve, const sx_pk_const_affine_point *x4, + const sx_pk_const_affine_point *x3, const sx_pk_const_affine_point *x1, + const sx_const_ecop *x2, const sx_const_ecop *s) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_ecjpake_gen_step_2 inputs; @@ -645,9 +648,10 @@ static inline void sx_ecjpake_gen_step_2_end(sx_pk_req *req, sx_pk_affine_point * an asynchronous version */ static inline int sx_ecjpake_gen_step_2(const struct sx_pk_ecurve *curve, - const sx_pk_affine_point *x4, const sx_pk_affine_point *x3, - const sx_pk_affine_point *x1, const sx_ecop *x2, - const sx_ecop *s, sx_pk_affine_point *a, sx_ecop *x2s, + const sx_pk_const_affine_point *x4, + const sx_pk_const_affine_point *x3, + const sx_pk_const_affine_point *x1, const sx_const_ecop *x2, + const sx_const_ecop *s, sx_pk_affine_point *a, sx_ecop *x2s, sx_pk_affine_point *ga) { uint32_t status; diff --git a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/rsa.h b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/rsa.h index 7973a25f5fe6..0b48b5b4cb71 100644 --- a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/rsa.h +++ b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/rsa.h @@ -61,8 +61,9 @@ struct sx_pk_cmd_def; * * @return Acquired acceleration request for this operation */ -static inline struct sx_pk_acq_req -sx_async_mod_single_op_cmd_go(const struct sx_pk_cmd_def *cmd, const sx_op *modulo, const sx_op *b) +static inline struct sx_pk_acq_req sx_async_mod_single_op_cmd_go(const struct sx_pk_cmd_def *cmd, + const sx_const_op *modulo, + const sx_const_op *b) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_mod_single_op_cmd inputs; @@ -74,8 +75,8 @@ sx_async_mod_single_op_cmd_go(const struct sx_pk_cmd_def *cmd, const sx_op *modu /* convert and transfer operands */ int sizes[] = { - sx_op_size(modulo), - sx_op_size(b), + sx_const_op_size(modulo), + sx_const_op_size(b), }; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { @@ -123,8 +124,8 @@ sx_async_mod_single_op_cmd_go(const struct sx_pk_cmd_def *cmd, const sx_op *modu * @see sx_async_mod_single_op_cmd_go() and sx_async_finish_single() * for an asynchronous version */ -static inline int sx_mod_single_op_cmd(const struct sx_pk_cmd_def *cmd, const sx_op *modulo, - const sx_op *b, sx_op *result) +static inline int sx_mod_single_op_cmd(const struct sx_pk_cmd_def *cmd, const sx_const_op *modulo, + const sx_const_op *b, sx_op *result) { struct sx_pk_acq_req pkreq; int status; @@ -164,8 +165,8 @@ static inline int sx_mod_single_op_cmd(const struct sx_pk_cmd_def *cmd, const sx */ static inline struct sx_pk_acq_req sx_async_mod_cmd_go(struct sx_pk_cnx *cnx, const struct sx_pk_cmd_def *cmd, - const sx_op *modulo, const sx_op *a, - const sx_op *b) + const sx_const_op *modulo, + const sx_const_op *a, const sx_const_op *b) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_mod_cmd inputs; @@ -177,9 +178,9 @@ static inline struct sx_pk_acq_req sx_async_mod_cmd_go(struct sx_pk_cnx *cnx, /* convert and transfer operands */ int sizes[] = { - sx_op_size(modulo), - sx_op_size(a), - sx_op_size(b), + sx_const_op_size(modulo), + sx_const_op_size(a), + sx_const_op_size(b), }; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { @@ -228,8 +229,8 @@ static inline struct sx_pk_acq_req sx_async_mod_cmd_go(struct sx_pk_cnx *cnx, * for an asynchronous version */ static inline int sx_mod_primitive_cmd(struct sx_pk_cnx *cnx, const struct sx_pk_cmd_def *cmd, - const sx_op *modulo, const sx_op *a, const sx_op *b, - sx_op *result) + const sx_const_op *modulo, const sx_const_op *a, + const sx_const_op *b, sx_op *result) { struct sx_pk_acq_req pkreq; int status; @@ -262,8 +263,8 @@ static inline int sx_mod_primitive_cmd(struct sx_pk_cnx *cnx, const struct sx_pk * * @see sx_async_finish_single(), sx_mod_inv() */ -static inline struct sx_pk_acq_req sx_async_mod_inv_go(struct sx_pk_cnx *cnx, const sx_op *modulo, - const sx_op *b) +static inline struct sx_pk_acq_req +sx_async_mod_inv_go(struct sx_pk_cnx *cnx, const sx_const_op *modulo, const sx_const_op *b) { return sx_async_mod_single_op_cmd_go(SX_PK_CMD_ODD_MOD_INV, modulo, b); } @@ -291,7 +292,7 @@ static inline struct sx_pk_acq_req sx_async_mod_inv_go(struct sx_pk_cnx *cnx, co * * @see sx_async_mod_inv_go() for an asynchronous verion */ -static inline int sx_mod_inv(struct sx_pk_cnx *cnx, const sx_op *modulo, const sx_op *b, +static inline int sx_mod_inv(struct sx_pk_cnx *cnx, const sx_const_op *modulo, const sx_const_op *b, sx_op *result) { struct sx_pk_acq_req pkreq; @@ -327,8 +328,9 @@ static inline int sx_mod_inv(struct sx_pk_cnx *cnx, const sx_op *modulo, const s * * @see sx_mod_exp() for the synchronous version */ -static inline struct sx_pk_acq_req sx_async_mod_exp_go(struct sx_pk_cnx *cnx, const sx_op *input, - const sx_op *e, const sx_op *m) +static inline struct sx_pk_acq_req sx_async_mod_exp_go(struct sx_pk_cnx *cnx, + const sx_const_op *input, + const sx_const_op *e, const sx_const_op *m) { return sx_async_mod_cmd_go(cnx, SX_PK_CMD_MOD_EXP, m, input, e); } @@ -376,8 +378,8 @@ static inline void sx_async_mod_exp_end(sx_pk_req *req, sx_op *result) * @see sx_async_mod_exp_go(), sx_async_mod_exp_end() * for an asynchronous version */ -static inline int sx_mod_exp(struct sx_pk_cnx *cnx, const sx_op *input, const sx_op *e, - const sx_op *m, sx_op *result) +static inline int sx_mod_exp(struct sx_pk_cnx *cnx, const sx_const_op *input, const sx_const_op *e, + const sx_const_op *m, sx_op *result) { struct sx_pk_acq_req pkreq; int status; @@ -421,10 +423,10 @@ static inline int sx_mod_exp(struct sx_pk_cnx *cnx, const sx_op *input, const sx * * @see sx_async_crt_mod_exp_end() */ -static inline struct sx_pk_acq_req sx_async_crt_mod_exp_go(struct sx_pk_cnx *cnx, const sx_op *in, - const sx_op *p, const sx_op *q, - const sx_op *dp, const sx_op *dq, - const sx_op *qinv) +static inline struct sx_pk_acq_req +sx_async_crt_mod_exp_go(struct sx_pk_cnx *cnx, const sx_const_op *in, const sx_const_op *p, + const sx_const_op *q, const sx_const_op *dp, const sx_const_op *dq, + const sx_const_op *qinv) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_crt_mod_exp inputs; @@ -435,8 +437,8 @@ static inline struct sx_pk_acq_req sx_async_crt_mod_exp_go(struct sx_pk_cnx *cnx } /* convert and transfer operands */ - int sizes[] = {sx_op_size(p), sx_op_size(q), sx_op_size(in), - sx_op_size(dp), sx_op_size(dq), sx_op_size(qinv)}; + int sizes[] = {sx_const_op_size(p), sx_const_op_size(q), sx_const_op_size(in), + sx_const_op_size(dp), sx_const_op_size(dq), sx_const_op_size(qinv)}; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { return pkreq; @@ -504,9 +506,9 @@ static inline void sx_async_crt_mod_exp_end(sx_pk_req *req, sx_op *result) * @see sx_async_crt_mod_exp_go(), sx_async_crt_mod_exp_end() * for an asynchronous version */ -static inline int sx_crt_mod_exp(struct sx_pk_cnx *cnx, const sx_op *in, const sx_op *p, - const sx_op *q, const sx_op *dp, const sx_op *dq, - const sx_op *qinv, sx_op *result) +static inline int sx_crt_mod_exp(struct sx_pk_cnx *cnx, const sx_const_op *in, const sx_const_op *p, + const sx_const_op *q, const sx_const_op *dp, const sx_const_op *dq, + const sx_const_op *qinv, sx_op *result) { struct sx_pk_acq_req pkreq; int status; @@ -535,8 +537,9 @@ static inline int sx_crt_mod_exp(struct sx_pk_cnx *cnx, const sx_op *in, const s * @return Acquired acceleration request for this operation */ -static inline struct sx_pk_acq_req sx_async_rsa_keygen_go(const sx_op *p, const sx_op *q, - const sx_op *public_expo) +static inline struct sx_pk_acq_req sx_async_rsa_keygen_go(const sx_const_op *p, + const sx_const_op *q, + const sx_const_op *public_expo) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_rsa_keygen inputs; @@ -547,7 +550,7 @@ static inline struct sx_pk_acq_req sx_async_rsa_keygen_go(const sx_op *p, const } /* convert and transfer operands */ - int sizes[] = {sx_op_size(p), sx_op_size(q), sx_op_size(public_expo)}; + int sizes[] = {sx_const_op_size(p), sx_const_op_size(q), sx_const_op_size(public_expo)}; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { @@ -621,8 +624,9 @@ static inline void sx_async_rsa_keygen_end(sx_pk_req *req, sx_op *n, sx_op *lamb * @see sx_async_rsa_keygen_go(), sx_async_rsa_keygen_end() * for an asynchronous version */ -static inline int sx_rsa_keygen(const sx_op *p, const sx_op *q, const sx_op *public_expo, sx_op *n, - sx_op *lambda_n, sx_op *privkey) +static inline int sx_rsa_keygen(const sx_const_op *p, const sx_const_op *q, + const sx_const_op *public_expo, sx_op *n, sx_op *lambda_n, + sx_op *privkey) { struct sx_pk_acq_req pkreq; int status; @@ -655,8 +659,9 @@ static inline int sx_rsa_keygen(const sx_op *p, const sx_op *q, const sx_op *pub * * @see sx_async_rsa_crt_keyparams_end() and sx_async_rsa_crt_keyparams() */ -static inline struct sx_pk_acq_req sx_async_rsa_crt_keyparams_go(const sx_op *p, const sx_op *q, - const sx_op *privkey) +static inline struct sx_pk_acq_req sx_async_rsa_crt_keyparams_go(const sx_const_op *p, + const sx_const_op *q, + const sx_const_op *privkey) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_rsa_crt_keyparams inputs; @@ -667,7 +672,7 @@ static inline struct sx_pk_acq_req sx_async_rsa_crt_keyparams_go(const sx_op *p, } /* convert and transfer operands */ - int sizes[] = {sx_op_size(p), sx_op_size(q), sx_op_size(privkey)}; + int sizes[] = {sx_const_op_size(p), sx_const_op_size(q), sx_const_op_size(privkey)}; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { @@ -741,8 +746,9 @@ static inline void sx_async_rsa_crt_keyparams_end(sx_pk_req *req, sx_op *dp, sx_ * @see sx_async_rsa_crt_keyparams_go(), sx_async_rsa_crt_keyparams_end() * for an asynchronous version */ -static inline int sx_rsa_crt_keyparams(const sx_op *p, const sx_op *q, const sx_op *privkey, - sx_op *dp, sx_op *dq, sx_op *qinv) +static inline int sx_rsa_crt_keyparams(const sx_const_op *p, const sx_const_op *q, + const sx_const_op *privkey, sx_op *dp, sx_op *dq, + sx_op *qinv) { struct sx_pk_acq_req pkreq; int status; @@ -782,7 +788,8 @@ static inline int sx_rsa_crt_keyparams(const sx_op *p, const sx_op *q, const sx_ * * @see sx_miller_rabin() for a synchronous version */ -static inline struct sx_pk_acq_req sx_async_miller_rabin_go(const sx_op *n, const sx_op *a) +static inline struct sx_pk_acq_req sx_async_miller_rabin_go(const sx_const_op *n, + const sx_const_op *a) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_miller_rabin inputs; @@ -793,7 +800,7 @@ static inline struct sx_pk_acq_req sx_async_miller_rabin_go(const sx_op *n, cons } /* convert and transfer operands */ - int sizes[] = {sx_op_size(n), sx_op_size(a)}; + int sizes[] = {sx_const_op_size(n), sx_const_op_size(a)}; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { @@ -833,7 +840,7 @@ static inline struct sx_pk_acq_req sx_async_miller_rabin_go(const sx_op *n, cons * @see sx_async_miller_rabin_go() for an asynchronous version */ -static inline int sx_miller_rabin(const sx_op *n, const sx_op *a) +static inline int sx_miller_rabin(const sx_const_op *n, const sx_const_op *a) { struct sx_pk_acq_req pkreq; uint32_t status; diff --git a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/sm9.h b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/sm9.h index 6e43f985989d..8c3b9c245f07 100644 --- a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/sm9.h +++ b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/sm9.h @@ -98,7 +98,7 @@ static const uint8_t sm9_f[32] = "\x3f\x23\xea\x58\xe5\x72\x0b\xdb\x84\x3c\x6c\x * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req -sx_async_sm9_exp_go(struct sx_pk_cnx *cnx, const struct sx_pk_ef_12 *g, const sx_ecop *h) +sx_async_sm9_exp_go(struct sx_pk_cnx *cnx, const struct sx_pk_ef_12 *g, const sx_const_ecop *h) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_sm9_exp inputs; @@ -171,8 +171,8 @@ static inline void sx_async_sm9_exp_end(sx_pk_req *req, struct sx_pk_ef_12 *r) * @see sx_async_sm9_exp_go(), sx_async_sm9_exp_end() for * an asynchronous version */ -static inline int sx_sm9_exp(struct sx_pk_cnx *cnx, const struct sx_pk_ef_12 *g, const sx_ecop *h, - struct sx_pk_ef_12 *z) +static inline int sx_sm9_exp(struct sx_pk_cnx *cnx, const struct sx_pk_ef_12 *g, + const sx_const_ecop *h, struct sx_pk_ef_12 *z) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -206,7 +206,7 @@ static inline int sx_sm9_exp(struct sx_pk_cnx *cnx, const struct sx_pk_ef_12 *g, * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req -sx_async_sm9_pmulg1_go(struct sx_pk_cnx *cnx, const struct sx_pk_point *p1, const sx_ecop *ke) +sx_async_sm9_pmulg1_go(struct sx_pk_cnx *cnx, const struct sx_pk_point *p1, const sx_const_ecop *ke) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_sm9_pmulg1 inputs; @@ -281,7 +281,7 @@ static inline void sx_async_sm9_pmulg1_end(sx_pk_req *req, struct sx_pk_point *r * an asynchronous version */ static inline int sx_sm9_pmulg1(struct sx_pk_cnx *cnx, const struct sx_pk_point *p1, - const sx_ecop *ke, struct sx_pk_point *ppube) + const sx_const_ecop *ke, struct sx_pk_point *ppube) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -315,7 +315,7 @@ static inline int sx_sm9_pmulg1(struct sx_pk_cnx *cnx, const struct sx_pk_point * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req -sx_async_sm9_pmulg2_go(struct sx_pk_cnx *cnx, const struct sx_pk_ef_4 *p2, const sx_ecop *ke) +sx_async_sm9_pmulg2_go(struct sx_pk_cnx *cnx, const struct sx_pk_ef_4 *p2, const sx_const_ecop *ke) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_sm9_pmulg2 inputs; @@ -393,7 +393,7 @@ static inline void sx_async_sm9_pmulg2_end(sx_pk_req *req, struct sx_pk_ef_4 *r) * an asynchronous version */ static inline int sx_sm9_pmulg2(struct sx_pk_cnx *cnx, const struct sx_pk_ef_4 *p2, - const sx_ecop *ke, struct sx_pk_ef_4 *ppubs) + const sx_const_ecop *ke, struct sx_pk_ef_4 *ppubs) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -539,7 +539,7 @@ static inline int sx_sm9_pair(struct sx_pk_cnx *cnx, const struct sx_pk_point *p */ static inline struct sx_pk_acq_req sx_async_sm9_generate_signature_private_key_go(struct sx_pk_cnx *cnx, const struct sx_pk_point *p1, - const sx_ecop *h, const sx_ecop *ks) + const sx_const_ecop *h, const sx_const_ecop *ks) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_sm9_sigpkgen inputs; @@ -622,7 +622,8 @@ static inline void sx_async_sm9_generate_signature_private_key_end(sx_pk_req *re */ static inline int sx_sm9_generate_signature_private_key(struct sx_pk_cnx *cnx, const struct sx_pk_point *p1, - const sx_ecop *h, const sx_ecop *ks, + const sx_const_ecop *h, + const sx_const_ecop *ks, struct sx_pk_point *ds) { uint32_t status; @@ -659,7 +660,8 @@ static inline int sx_sm9_generate_signature_private_key(struct sx_pk_cnx *cnx, */ static inline struct sx_pk_acq_req sx_async_sm9_sign_go(struct sx_pk_cnx *cnx, const struct sx_pk_point *ds, - const sx_ecop *h, const sx_ecop *r) + const sx_const_ecop *h, + const sx_const_ecop *r) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_sm9_signaturegen inputs; @@ -736,8 +738,9 @@ static inline void sx_async_sm9_sign_end(sx_pk_req *req, struct sx_pk_point *s) * @see sx_async_sm9_sign_go(), sx_async_sm9_sign_end() for * an asynchronous version */ -static inline int sx_sm9_sign(struct sx_pk_cnx *cnx, const struct sx_pk_point *ds, const sx_ecop *h, - const sx_ecop *r, struct sx_pk_point *s) +static inline int sx_sm9_sign(struct sx_pk_cnx *cnx, const struct sx_pk_point *ds, + const sx_const_ecop *h, const sx_const_ecop *r, + struct sx_pk_point *s) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -775,9 +778,9 @@ static inline int sx_sm9_sign(struct sx_pk_cnx *cnx, const struct sx_pk_point *d * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req -sx_async_sm9_signature_verify_go(struct sx_pk_cnx *cnx, const sx_ecop *h1, +sx_async_sm9_signature_verify_go(struct sx_pk_cnx *cnx, const sx_const_ecop *h1, const struct sx_pk_ef_4 *p2, const struct sx_pk_ef_4 *ppubs, - const struct sx_pk_point *s, const sx_ecop *h, + const struct sx_pk_point *s, const sx_const_ecop *h, const struct sx_pk_ef_12 *g) { struct sx_pk_acq_req pkreq; @@ -874,10 +877,10 @@ static inline void sx_async_sm9_signature_verify_end(sx_pk_req *req, struct sx_p * Truncation or padding should be done by user application * */ -static inline int sx_sm9_signature_verify(struct sx_pk_cnx *cnx, const sx_ecop *h1, +static inline int sx_sm9_signature_verify(struct sx_pk_cnx *cnx, const sx_const_ecop *h1, const struct sx_pk_ef_4 *p2, const struct sx_pk_ef_4 *ppubs, - const struct sx_pk_point *s, const sx_ecop *h, + const struct sx_pk_point *s, const sx_const_ecop *h, const struct sx_pk_ef_12 *g, struct sx_pk_ef_12 *w) { uint32_t status; @@ -914,7 +917,7 @@ static inline int sx_sm9_signature_verify(struct sx_pk_cnx *cnx, const sx_ecop * */ static inline struct sx_pk_acq_req sx_async_sm9_generate_encryption_private_key_go(struct sx_pk_cnx *cnx, const struct sx_pk_ef_4 *p2, - const sx_ecop *h, const sx_ecop *ke) + const sx_const_ecop *h, const sx_const_ecop *ke) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_sm9_privencrkeygen inputs; @@ -1001,7 +1004,8 @@ static inline void sx_async_sm9_generate_encryption_private_key_end(sx_pk_req *r */ static inline int sx_sm9_generate_encryption_private_key(struct sx_pk_cnx *cnx, const struct sx_pk_ef_4 *p2, - const sx_ecop *h, const sx_ecop *ke, + const sx_const_ecop *h, + const sx_const_ecop *ke, struct sx_pk_ef_4 *de) { uint32_t status; @@ -1041,7 +1045,8 @@ static inline int sx_sm9_generate_encryption_private_key(struct sx_pk_cnx *cnx, static inline struct sx_pk_acq_req sx_async_sm9_send_key_go(struct sx_pk_cnx *cnx, const struct sx_pk_point *p1, const struct sx_pk_point *ppube, - const sx_ecop *h, const sx_ecop *r) + const sx_const_ecop *h, + const sx_const_ecop *r) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_sm9_sendkey inputs; @@ -1121,8 +1126,8 @@ static inline void sx_async_sm9_send_key_end(sx_pk_req *req, struct sx_pk_point * an asynchronous version */ static inline int sx_sm9_send_key(struct sx_pk_cnx *cnx, const struct sx_pk_point *p1, - const struct sx_pk_point *ppube, const sx_ecop *h, - const sx_ecop *r, struct sx_pk_point *rx) + const struct sx_pk_point *ppube, const sx_const_ecop *h, + const sx_const_ecop *r, struct sx_pk_point *rx) { uint32_t status; struct sx_pk_acq_req pkreq; @@ -1154,7 +1159,8 @@ static inline int sx_sm9_send_key(struct sx_pk_cnx *cnx, const struct sx_pk_poin * * @return Acquired acceleration request for this operation */ -static inline struct sx_pk_acq_req sx_async_sm9_reduce_h_go(struct sx_pk_cnx *cnx, const sx_op *h) +static inline struct sx_pk_acq_req sx_async_sm9_reduce_h_go(struct sx_pk_cnx *cnx, + const sx_const_op *h) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_sm9_reduceh inputs; @@ -1164,7 +1170,7 @@ static inline struct sx_pk_acq_req sx_async_sm9_reduce_h_go(struct sx_pk_cnx *cn return pkreq; } - int sizes[] = {sx_op_size(h), sizeof(sm9_t)}; + int sizes[] = {sx_const_op_size(h), sizeof(sm9_t)}; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { @@ -1219,7 +1225,7 @@ static inline void sx_async_sm9_reduce_h_end(sx_pk_req *req, sx_ecop *rh) * @see sx_async_sm9_reduce_h_go(), sx_async_sm9_reduce_h_end() for * an asynchronous version */ -static inline int sx_sm9_reduce_h(struct sx_pk_cnx *cnx, const sx_ecop *h, sx_ecop *rh) +static inline int sx_sm9_reduce_h(struct sx_pk_cnx *cnx, const sx_const_ecop *h, sx_ecop *rh) { uint32_t status; struct sx_pk_acq_req pkreq; diff --git a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/srp.h b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/srp.h index c46dcd0c6142..66e5507d90a1 100644 --- a/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/srp.h +++ b/subsys/nrf_security/src/drivers/cracen/silexpk/include/silexpk/sxops/srp.h @@ -61,8 +61,9 @@ struct sx_pk_cmd_def; * */ static inline struct sx_pk_acq_req -sx_async_srp_user_keygen_go(struct sx_pk_cnx *cnx, const sx_op *n, const sx_op *g, const sx_op *a, - const sx_op *b, const sx_op *x, const sx_op *k, const sx_op *u) +sx_async_srp_user_keygen_go(struct sx_pk_cnx *cnx, const sx_const_op *n, const sx_const_op *g, + const sx_const_op *a, const sx_const_op *b, const sx_const_op *x, + const sx_const_op *k, const sx_const_op *u) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_srp_user_keyparams inputs; @@ -73,8 +74,9 @@ sx_async_srp_user_keygen_go(struct sx_pk_cnx *cnx, const sx_op *n, const sx_op * } /* convert and transfer operands */ - int sizes[] = {sx_op_size(n), sx_op_size(g), sx_op_size(a), sx_op_size(b), - sx_op_size(x), sx_op_size(k), sx_op_size(u)}; + int sizes[] = {sx_const_op_size(n), sx_const_op_size(g), sx_const_op_size(a), + sx_const_op_size(b), sx_const_op_size(x), sx_const_op_size(k), + sx_const_op_size(u)}; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { return pkreq; @@ -185,8 +187,9 @@ static inline int sx_srp_user_keygen(struct sx_pk_cnx *cnx, const sx_op *n, cons * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req -sx_async_srp_server_public_key_gen_go(struct sx_pk_cnx *cnx, const sx_op *n, const sx_op *g, - const sx_op *k, const sx_op *v, const sx_op *b) +sx_async_srp_server_public_key_gen_go(struct sx_pk_cnx *cnx, const sx_const_op *n, + const sx_const_op *g, const sx_const_op *k, + const sx_const_op *v, const sx_const_op *b) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_srp_server_public_key_gen inputs; @@ -196,7 +199,8 @@ sx_async_srp_server_public_key_gen_go(struct sx_pk_cnx *cnx, const sx_op *n, con return pkreq; } - int sizes[] = {sx_op_size(n), sx_op_size(g), sx_op_size(k), sx_op_size(v), sx_op_size(b)}; + int sizes[] = {sx_const_op_size(n), sx_const_op_size(g), sx_const_op_size(k), + sx_const_op_size(v), sx_const_op_size(b)}; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { @@ -298,8 +302,9 @@ static inline int sx_srp_server_public_key_gen(struct sx_pk_cnx *cnx, const sx_o * @return Acquired acceleration request for this operation */ static inline struct sx_pk_acq_req -sx_async_srp_server_session_key_gen_go(struct sx_pk_cnx *cnx, const sx_op *n, const sx_op *a, - const sx_op *u, const sx_op *v, const sx_op *b) +sx_async_srp_server_session_key_gen_go(struct sx_pk_cnx *cnx, const sx_const_op *n, + const sx_const_op *a, const sx_const_op *u, + const sx_const_op *v, const sx_const_op *b) { struct sx_pk_acq_req pkreq; struct sx_pk_inops_srp_server_session_key_gen inputs; @@ -309,7 +314,8 @@ sx_async_srp_server_session_key_gen_go(struct sx_pk_cnx *cnx, const sx_op *n, co return pkreq; } - int sizes[] = {sx_op_size(n), sx_op_size(a), sx_op_size(u), sx_op_size(v), sx_op_size(b)}; + int sizes[] = {sx_const_op_size(n), sx_const_op_size(a), sx_const_op_size(u), + sx_const_op_size(v), sx_const_op_size(b)}; pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs); if (pkreq.status) { diff --git a/subsys/nrf_security/src/drivers/cracen/silexpk/interface/sxbuf/sxbufops.c b/subsys/nrf_security/src/drivers/cracen/silexpk/interface/sxbuf/sxbufops.c index 9ab2dc8f0283..ac7a1b176356 100644 --- a/subsys/nrf_security/src/drivers/cracen/silexpk/interface/sxbuf/sxbufops.c +++ b/subsys/nrf_security/src/drivers/cracen/silexpk/interface/sxbuf/sxbufops.c @@ -16,7 +16,7 @@ #endif /** Little endian function of sx_pk_ecop2mem() */ -void sx_pk_ecop2mem_le(const sx_ecop *op, uint8_t *mem, int sz) +void sx_pk_ecop2mem_le(const sx_const_ecop *op, uint8_t *mem, int sz) { int cursz = op->sz; int diff = sz - cursz; @@ -25,7 +25,7 @@ void sx_pk_ecop2mem_le(const sx_ecop *op, uint8_t *mem, int sz) sx_clrpkmem(mem + cursz, diff); uint8_t buf[SX_PK_MAX_OP_SZ]; - uint8_t *ptr = op->bytes; + const uint8_t *ptr = op->bytes; assert(cursz <= SX_PK_MAX_OP_SZ); for (int i = 0; i < cursz; i += 1) { @@ -35,7 +35,7 @@ void sx_pk_ecop2mem_le(const sx_ecop *op, uint8_t *mem, int sz) } /** Big endian function of sx_pk_ecop2mem() */ -void sx_pk_ecop2mem_be(const sx_ecop *op, uint8_t *mem, int sz) +void sx_pk_ecop2mem_be(const sx_const_ecop *op, uint8_t *mem, int sz) { int cursz = op->sz; int diff = sz - cursz; @@ -46,7 +46,7 @@ void sx_pk_ecop2mem_be(const sx_ecop *op, uint8_t *mem, int sz) sx_wrpkmem(mem + diff, op->bytes, cursz); } -void sx_pk_ecop2mem(const sx_ecop *op, uint8_t *mem, int sz) +void sx_pk_ecop2mem(const sx_const_ecop *op, uint8_t *mem, int sz) { sx_pk_ecop2mem_be(op, mem, sz); } @@ -66,12 +66,12 @@ void sx_pk_op2vmem_le(const sx_op *op, uint8_t *mem) } /** Big endian function of sx_pk_op2vmem() */ -void sx_pk_op2vmem_be(const sx_op *op, uint8_t *mem) +void sx_pk_op2vmem_be(const sx_const_op *op, uint8_t *mem) { sx_wrpkmem(mem, op->bytes, op->sz); } -void sx_pk_op2vmem(const sx_op *op, uint8_t *mem) +void sx_pk_op2vmem(const sx_const_op *op, uint8_t *mem) { sx_pk_op2vmem_be(op, mem); } @@ -81,6 +81,11 @@ int sx_op_size(sx_op *op) return op->sz; } +int sx_const_op_size(sx_const_op *op) +{ + return op->sz; +} + /** Big endian function of sx_pk_mem2op() */ void sx_pk_mem2op_be(const uint8_t *mem, int sz, sx_op *op) { @@ -111,7 +116,7 @@ void sx_pk_mem2affpt(const uint8_t *mem_x, const uint8_t *mem_y, int sz, sx_pk_a sx_pk_mem2ecop(mem_y, sz, &op->y); } -void sx_pk_affpt2mem(const sx_pk_affine_point *op, uint8_t *mem_x, uint8_t *mem_y, int sz) +void sx_pk_affpt2mem(const sx_pk_const_affine_point *op, uint8_t *mem_x, uint8_t *mem_y, int sz) { sx_pk_ecop2mem(&op->x, mem_x, sz); sx_pk_ecop2mem(&op->y, mem_y, sz); diff --git a/subsys/nrf_security/src/drivers/cracen/silexpk/target/hw/ik/ikhardware.c b/subsys/nrf_security/src/drivers/cracen/silexpk/target/hw/ik/ikhardware.c index 8353e4c5ef69..8fdfbf2a11f8 100644 --- a/subsys/nrf_security/src/drivers/cracen/silexpk/target/hw/ik/ikhardware.c +++ b/subsys/nrf_security/src/drivers/cracen/silexpk/target/hw/ik/ikhardware.c @@ -62,7 +62,7 @@ int sx_pk_list_ik_inslots(sx_pk_req *req, unsigned int key, struct sx_pk_slot *i req->ik_mode = 0; } else { if (!req->ik_mode) { - int status = cracen_prepare_ik_key((uint8_t *)&key); + int status = cracen_prepare_ik_key((const uint8_t *)&key); if (status != SX_OK) { sx_pk_release_req(req); return SX_ERR_INVALID_PARAM; From 47f5ed52d0ac8092ae1dabb8db03f34dbca47c26 Mon Sep 17 00:00:00 2001 From: Andrei Urs-Hadadea Date: Mon, 17 Nov 2025 16:09:50 +0200 Subject: [PATCH 011/155] nrf_security: CRACEN: Implemended PureEdDSA and HashEdDSA for Ed448 Jira: NCSDK-31033 Signed-off-by: Andrei Urs-Hadadea --- .../releases/release-notes-changelog.rst | 3 + .../crypto/crypto_supported_features.rst | 22 +- .../cmake/psa_crypto_config.cmake | 2 + .../configs/psa_crypto_config.h.template | 2 + .../drivers/cracen/cracenpsa/cracenpsa.cmake | 2 + .../cracenpsa/include/cracen_psa_eddsa.h | 14 + .../src/drivers/cracen/cracenpsa/src/common.c | 3 + .../drivers/cracen/cracenpsa/src/ec_helpers.c | 1 + .../src/drivers/cracen/cracenpsa/src/ed448.c | 244 ++++++++++++++++++ .../cracen/cracenpsa/src/key_management.c | 15 +- .../src/drivers/cracen/cracenpsa/src/sign.c | 52 +++- .../src/drivers/cracen/psa_driver.Kconfig | 23 +- .../sxsymcrypt/include/sxsymcrypt/hashdefs.h | 7 +- .../src/drivers/cracen/sxsymcrypt/src/sha3.c | 5 + 14 files changed, 365 insertions(+), 30 deletions(-) create mode 100644 subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ed448.c diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index c722e8c0f32f..18a73500bea1 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -148,6 +148,9 @@ Security * Experimental support for KMU on the nRF54LV10A SoC. * Experimental support for compression and encryption on the nRF54LV10A SoC. + * Support for the PureEdDSA and HashEdDSA for Ed448 curve in the :ref:`CRACEN driver `. + * Support for the SHAKE256 hash function with 64-byte and 114-byte digests in the :ref:`CRACEN driver `. + * Updated: * The :ref:`security_index` page with a table that lists the versions of security components implemented in the |NCS|. diff --git a/doc/nrf/security/crypto/crypto_supported_features.rst b/doc/nrf/security/crypto/crypto_supported_features.rst index bc74544bc4ff..dd73509d6afd 100644 --- a/doc/nrf/security/crypto/crypto_supported_features.rst +++ b/doc/nrf/security/crypto/crypto_supported_features.rst @@ -6246,11 +6246,11 @@ The options are grouped by Series and drivers available for the device Series, a - Experimental * - Edwards448 (Ed448) - :kconfig:option:`CONFIG_PSA_WANT_ECC_TWISTED_EDWARDS_448` - - -- - - -- - - -- - - -- - - -- + - Supported + - Supported + - Supported + - Experimental + - Experimental * - secp192k1 - :kconfig:option:`CONFIG_PSA_WANT_ECC_SECP_K1_192` - Supported @@ -6744,6 +6744,7 @@ Based on this setting, Oberon PSA Crypto selects the most appropriate driver for | :kconfig:option:`CONFIG_PSA_WANT_ECC_BRAINPOOL_P_R1_512` | :kconfig:option:`CONFIG_PSA_WANT_ECC_MONTGOMERY_255` | :kconfig:option:`CONFIG_PSA_WANT_ECC_TWISTED_EDWARDS_255` + | :kconfig:option:`CONFIG_PSA_WANT_ECC_TWISTED_EDWARDS_448` | :kconfig:option:`CONFIG_PSA_WANT_ECC_SECP_K1_192` | :kconfig:option:`CONFIG_PSA_WANT_ECC_SECP_K1_256` | :kconfig:option:`CONFIG_PSA_WANT_ECC_SECP_R1_192` @@ -7688,11 +7689,11 @@ The options are grouped by Series and drivers available for the device Series, a - Experimental * - SHAKE256 512 bits - :kconfig:option:`CONFIG_PSA_WANT_ALG_SHAKE256_512` - - -- - - -- - - -- - - -- - - -- + - Supported + - Supported + - Supported + - Experimental + - Experimental .. tab:: nrf_oberon @@ -8116,6 +8117,7 @@ Based on this setting, Oberon PSA Crypto selects the most appropriate driver for | :kconfig:option:`CONFIG_PSA_WANT_ALG_SHA3_256` | :kconfig:option:`CONFIG_PSA_WANT_ALG_SHA3_384` | :kconfig:option:`CONFIG_PSA_WANT_ALG_SHA3_512` + | :kconfig:option:`CONFIG_PSA_WANT_ALG_SHAKE256_512` .. tab:: nrf_oberon diff --git a/subsys/nrf_security/cmake/psa_crypto_config.cmake b/subsys/nrf_security/cmake/psa_crypto_config.cmake index 9e2c47533362..5e7006bbb0a3 100644 --- a/subsys/nrf_security/cmake/psa_crypto_config.cmake +++ b/subsys/nrf_security/cmake/psa_crypto_config.cmake @@ -57,6 +57,7 @@ kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448 kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS) kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_RSA_PKCS1V15_SIGN) kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_ED25519PH) +kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_ED448PH) kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_RSA_PSS) kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_ASYMMETRIC_SIGNATURE_ANY_ECC) kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_ASYMMETRIC_SIGNATURE_ANY_RSA) @@ -74,6 +75,7 @@ kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_SHA3_224) kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_SHA3_256) kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_SHA3_384) kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_SHA3_512) +kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_SHAKE256_512) kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_HASH_DRIVER) # Key management driver configurations diff --git a/subsys/nrf_security/configs/psa_crypto_config.h.template b/subsys/nrf_security/configs/psa_crypto_config.h.template index 75ed63624a69..b5254fbacd1a 100644 --- a/subsys/nrf_security/configs/psa_crypto_config.h.template +++ b/subsys/nrf_security/configs/psa_crypto_config.h.template @@ -319,6 +319,7 @@ #cmakedefine PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448 @PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448@ #cmakedefine PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS @PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS@ #cmakedefine PSA_NEED_CRACEN_ED25519PH @PSA_NEED_CRACEN_ED25519PH@ +#cmakedefine PSA_NEED_CRACEN_ED448PH @PSA_NEED_CRACEN_ED448PH@ #cmakedefine PSA_NEED_CRACEN_RSA_PKCS1V15_SIGN @PSA_NEED_CRACEN_RSA_PKCS1V15_SIGN@ #cmakedefine PSA_NEED_CRACEN_RSA_PSS @PSA_NEED_CRACEN_RSA_PSS@ #cmakedefine PSA_NEED_CRACEN_RSA_OAEP @PSA_NEED_CRACEN_RSA_OAEP@ @@ -332,6 +333,7 @@ #cmakedefine PSA_NEED_CRACEN_SHA3_256 @PSA_NEED_CRACEN_SHA3_256@ #cmakedefine PSA_NEED_CRACEN_SHA3_384 @PSA_NEED_CRACEN_SHA3_384@ #cmakedefine PSA_NEED_CRACEN_SHA3_512 @PSA_NEED_CRACEN_SHA3_512@ +#cmakedefine PSA_NEED_CRACEN_SHAKE256_512 @PSA_NEED_CRACEN_SHAKE256_512@ /* Key management driver configurations */ #cmakedefine PSA_NEED_CRACEN_KEY_TYPE_ECC_PUBLIC_KEY_SECP_R1_224 @PSA_NEED_CRACEN_KEY_TYPE_ECC_PUBLIC_KEY_SECP_R1_224@ diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake b/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake index 784e8295c4a1..94853658d21d 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake @@ -70,6 +70,7 @@ if(CONFIG_PSA_NEED_CRACEN_ASYMMETRIC_SIGNATURE_DRIVER) ${CMAKE_CURRENT_LIST_DIR}/src/ecdsa.c ${CMAKE_CURRENT_LIST_DIR}/src/ecc.c ${CMAKE_CURRENT_LIST_DIR}/src/ed25519.c + ${CMAKE_CURRENT_LIST_DIR}/src/ed448.c ${CMAKE_CURRENT_LIST_DIR}/src/hmac.c ${CMAKE_CURRENT_LIST_DIR}/src/rndinrange.c ) @@ -152,6 +153,7 @@ endif() if(CONFIG_PSA_NEED_CRACEN_KEY_AGREEMENT_DRIVER) list(APPEND cracen_driver_sources ${CMAKE_CURRENT_LIST_DIR}/src/ed25519.c + ${CMAKE_CURRENT_LIST_DIR}/src/ed448.c ${CMAKE_CURRENT_LIST_DIR}/src/montgomery.c ) endif() diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_eddsa.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_eddsa.h index 4962324a3acf..11fab040ebb5 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_eddsa.h +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_eddsa.h @@ -25,4 +25,18 @@ int cracen_ed25519ph_verify(const uint8_t *pub_key, const uint8_t *message, size int cracen_ed25519_create_pubkey(const uint8_t *priv_key, uint8_t *pub_key); +int cracen_ed448_sign(const uint8_t *priv_key, uint8_t *signature, const uint8_t *message, + size_t message_length); + +int cracen_ed448_verify(const uint8_t *pub_key, const uint8_t *message, size_t message_length, + const uint8_t *signature); + +int cracen_ed448ph_sign(const uint8_t *priv_key, uint8_t *signature, const uint8_t *message, + size_t message_length, bool is_message); + +int cracen_ed448ph_verify(const uint8_t *pub_key, const uint8_t *message, size_t message_length, + const uint8_t *signature, bool is_message); + +int cracen_ed448_create_pubkey(const uint8_t *priv_key, uint8_t *pub_key); + #endif /* CRACEN_PSA_EDDSA_H */ diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.c index 58ef97378433..ab1326b141d9 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.c @@ -126,6 +126,9 @@ hash_get_algo(psa_algorithm_t alg, const struct sxhashalg **sx_hash_algo) case PSA_ALG_SHA3_512: IF_ENABLED(PSA_NEED_CRACEN_SHA3_512, (*sx_hash_algo = &sxhashalg_sha3_512)); break; + case PSA_ALG_SHAKE256_512: + IF_ENABLED(PSA_NEED_CRACEN_SHAKE256_512, (*sx_hash_algo = &sxhashalg_shake256_64)); + break; default: return PSA_ALG_IS_HASH(alg) ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT; } diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ec_helpers.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ec_helpers.c index b4fae3d664d2..c18d4ed240de 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ec_helpers.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ec_helpers.c @@ -21,5 +21,6 @@ void decode_scalar_25519(uint8_t *k) void decode_scalar_448(uint8_t *k) { k[0] &= ~0x03; /* Clear bits 0 and 1. */ + k[56] = 0x00; /* Clear the last byte */ k[55] |= 0x80; /* Set bit 447. */ } diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ed448.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ed448.c new file mode 100644 index 000000000000..b2e097418076 --- /dev/null +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ed448.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + * + */ +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "cracen_psa_eddsa.h" + +/* Define SHAKE 256, 64 bit Digest size*/ +#define SHAKE256_64_DGST 64 + +/* Define PHflag byte location in DOM4*/ +#define PHFLAG_BYTE 8 + +#define AREA2_MEM_OFFSET 57 +#define AREA4_MEM_OFFSET 171 + +/* This is the ASCII string with the + * PHflag 1 and context size 0 appended as defined in: + * https://datatracker.ietf.org/doc/html/rfc8032.html#section-2. + * It is used for domain separation between Ed448 and Ed448ph. + * This can not be stored as a const due to hardware limitations + */ +static uint8_t dom4[] = {0x53, 0x69, 0x67, 0x45, 0x64, 0x34, 0x34, 0x38, 0x01, 0x00}; + +static int ed448_calculate_r(uint8_t *workmem, const uint8_t *message, size_t message_length, + bool prehash) +{ + /* update the PHflag in dom4*/ + dom4[PHFLAG_BYTE] = prehash ? 0x01 : 0x00; + uint8_t const *hash_array[] = {dom4, workmem, message}; + size_t hash_array_lengths[] = {sizeof(dom4), SX_ED448_SZ, message_length}; + size_t input_count = 3; + + return cracen_hash_all_inputs(hash_array, hash_array_lengths, input_count, + &sxhashalg_shake256_114, workmem + SX_ED448_DGST_SZ); +} + +static int ed448_calculate_k(uint8_t *workmem, uint8_t *point_r, const uint8_t *message, + size_t message_length, bool prehash) +{ + /* update the PHflag in dom4*/ + dom4[PHFLAG_BYTE] = prehash ? 0x01 : 0x00; + uint8_t const *hash_array[] = {dom4, point_r, workmem, message}; + size_t hash_array_lengths[] = {sizeof(dom4), SX_ED448_SZ, SX_ED448_SZ, message_length}; + size_t input_count = 4; + + return cracen_hash_all_inputs(hash_array, hash_array_lengths, input_count, + &sxhashalg_shake256_114, workmem); +} + +static int ed448_sign_internal(const uint8_t *priv_key, uint8_t *signature, + const uint8_t *message, size_t message_length, bool prehash) +{ + int status; + uint8_t workmem[5 * SX_ED448_SZ]; + uint8_t pnt_r[SX_ED448_DGST_SZ]; + uint8_t *area_1 = workmem; + uint8_t *area_2 = workmem + AREA2_MEM_OFFSET; + uint8_t *area_4 = workmem + AREA4_MEM_OFFSET; + + /* Hash the private key, the digest is stored in the first 114 bytes of workmem*/ + status = cracen_hash_input(priv_key, SX_ED448_SZ, &sxhashalg_shake256_114, area_1); + if (status != SX_OK) { + return status; + } + + /* Obtain r by hashing (prefix || message), where prefix is the second + * half of the private key digest. + */ + status = ed448_calculate_r(area_2, message, message_length, prehash); + if (status != SX_OK) { + return status; + } + + /* Perform point multiplication R = [r]B. This is the encoded point R, + * which is the first part of the signature. + */ + status = sx_ed448_ptmult((const struct sx_ed448_dgst *)area_4, + (struct sx_ed448_pt *)pnt_r); + if (status != SX_OK) { + return status; + } + + /* The secret scalar s is computed in place from the first half of the + * private key digest. + */ + decode_scalar_448(area_1); + + /* Clear second half of private key digest: sx_ed448_ptmult() + * works on an input of SX_ED448_DGST_SZ bytes. + */ + safe_memzero(area_2, SX_ED448_SZ); + + /* Perform point multiplication A = [s]B, + * to obtain the public key A. which is stored in workmem[57:113] + */ + status = sx_ed448_ptmult((const struct sx_ed448_dgst *)area_1, + (struct sx_ed448_pt *)area_2); + + if (status != SX_OK) { + return status; + } + + status = ed448_calculate_k(area_2, pnt_r, message, message_length, prehash); + if (status != SX_OK) { + return status; + } + + /* Compute (r + k * s) mod L. This gives the second part of the + * signature, which is the encoded S which is stored in pnt_r. + */ + status = sx_ed448_sign((const struct sx_ed448_dgst *)area_2, + (const struct sx_ed448_dgst *)area_4, + (const struct sx_ed448_v *)area_1, + (struct sx_ed448_v *)(pnt_r + SX_ED448_PT_SZ)); + if (status != SX_OK) { + return status; + } + + memcpy(signature, pnt_r, SX_ED448_DGST_SZ); + safe_memzero(workmem, sizeof(workmem)); + + return status; +} + +int cracen_ed448_sign(const uint8_t *priv_key, uint8_t *signature, const uint8_t *message, + size_t message_length) +{ + return ed448_sign_internal(priv_key, signature, message, message_length, false); +} + +int cracen_ed448ph_sign(const uint8_t *priv_key, uint8_t *signature, const uint8_t *message, + size_t message_length, bool is_message) +{ + uint8_t hashedmessage[SX_ED448_DGST_SZ]; + int status; + + if (is_message) { + status = cracen_hash_input(message, message_length, &sxhashalg_shake256_64, + hashedmessage); + if (status != SX_OK) { + return status; + } + + return ed448_sign_internal(priv_key, signature, hashedmessage, SHAKE256_64_DGST, + true); + } else { + return ed448_sign_internal(priv_key, signature, message, message_length, true); + } +} + +static int ed448_verify_internal(const uint8_t *pub_key, const uint8_t *message, + size_t message_length, const uint8_t *signature, bool prehash) +{ + /* update the PHflag in dom4*/ + dom4[PHFLAG_BYTE] = prehash ? 0x01 : 0x00; + int status; + uint8_t digest[SX_ED448_DGST_SZ]; + size_t ed448_sz = SX_ED448_SZ; + size_t input_count = 4; + + uint8_t const *hash_array[] = {dom4, signature, pub_key, message}; + size_t hash_array_lengths[] = {sizeof(dom4), ed448_sz, ed448_sz, message_length}; + + status = cracen_hash_all_inputs(hash_array, hash_array_lengths, + input_count, &sxhashalg_shake256_114, digest); + if (status != SX_OK) { + return status; + } + status = + sx_ed448_verify((struct sx_ed448_dgst *)digest, (const struct sx_ed448_pt *)pub_key, + (const struct sx_ed448_v *)(signature + SX_ED448_SZ), + (const struct sx_ed448_pt *)signature); + + return status; +} + +int cracen_ed448_verify(const uint8_t *pub_key, const uint8_t *message, size_t message_length, + const uint8_t *signature) +{ + return ed448_verify_internal(pub_key, message, message_length, signature, false); +} + +int cracen_ed448ph_verify(const uint8_t *pub_key, const uint8_t *message, size_t message_length, + const uint8_t *signature, bool is_message) +{ + int status; + uint8_t message_digest[SX_ED448_DGST_SZ]; + + if (is_message) { + status = cracen_hash_input(message, message_length, &sxhashalg_shake256_64, + message_digest); + if (status != SX_OK) { + return status; + } + + return ed448_verify_internal(pub_key, message_digest, SHAKE256_64_DGST, + signature, true); + } + return ed448_verify_internal(pub_key, message, message_length, signature, true); +} + +int cracen_ed448_create_pubkey(const uint8_t *priv_key, uint8_t *pub_key) +{ + int status; + uint8_t digest[SX_ED448_DGST_SZ]; + uint8_t *pub_key_A = digest + SX_ED448_SZ; + + status = cracen_hash_input(priv_key, SX_ED448_SZ, &sxhashalg_shake256_114, digest); + if (status != SX_OK) { + return status; + } + /* The secret scalar s is computed in place from the first half of the + * private key digest. + */ + decode_scalar_448(digest); + + /* Clear second half of private key digest: ed448_ptmult() + * works on an input of SX_ED448_DGST_SZ bytes. + */ + safe_memzero(pub_key_A, SX_ED448_SZ); + + /* Perform point multiplication A = [s]B, to obtain the public key A. */ + status = sx_ed448_ptmult((const struct sx_ed448_dgst *)digest, + (struct sx_ed448_pt *)pub_key_A); + + if (status != SX_OK) { + return status; + } + + memcpy(pub_key, pub_key_A, SX_ED448_SZ); + safe_memzero(digest, SX_ED448_DGST_SZ); + + return status; +} diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c index ec5a38464d25..345a35b1902b 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c @@ -81,7 +81,8 @@ static struct { /* Twisted Edwards */ {PSA_ECC_FAMILY_TWISTED_EDWARDS, 255, 32, 32, IS_ENABLED(PSA_NEED_CRACEN_KEY_TYPE_ECC_TWISTED_EDWARDS)}, - {PSA_ECC_FAMILY_TWISTED_EDWARDS, 448, 57, 57, false}, + {PSA_ECC_FAMILY_TWISTED_EDWARDS, 448, 57, 57, + IS_ENABLED(PSA_NEED_CRACEN_KEY_TYPE_ECC_TWISTED_EDWARDS)}, }; static psa_status_t check_ecc_key_attributes(const psa_key_attributes_t *attributes, @@ -119,10 +120,9 @@ static psa_status_t check_ecc_key_attributes(const psa_key_attributes_t *attribu } if (status == PSA_SUCCESS) { - if (curve == PSA_ECC_FAMILY_TWISTED_EDWARDS) { - if (key_alg != PSA_ALG_PURE_EDDSA && key_alg != PSA_ALG_ED25519PH) { - return PSA_ERROR_INVALID_ARGUMENT; - } + if ((curve == PSA_ECC_FAMILY_TWISTED_EDWARDS) && (key_alg != PSA_ALG_PURE_EDDSA && + key_alg != PSA_ALG_ED25519PH && key_alg != PSA_ALG_ED448PH)) { + return PSA_ERROR_INVALID_ARGUMENT; } } @@ -716,9 +716,8 @@ static psa_status_t handle_curve_family(psa_ecc_family_t psa_curve, size_t key_b cracen_ed25519_create_pubkey(key_buffer, data)); } else if (key_bits_attr == 448 && IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448)) { - /* This if-statement is kept to make it easier to add ed448 in the future - * even though it does nothing. - */ + return silex_statuscodes_to_psa( + cracen_ed448_create_pubkey(key_buffer, data)); return PSA_ERROR_NOT_SUPPORTED; } else { return PSA_ERROR_NOT_SUPPORTED; diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c index 64bc1ebdddbb..0150a2ee4b47 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c @@ -122,6 +122,17 @@ cracen_signature_prepare_ec_pubkey(const uint8_t *key_buffer, size_t key_buffer_ } } + if (IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448)) { + if (alg == PSA_ALG_PURE_EDDSA || alg == PSA_ALG_ED448PH) { + if (PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(psa_get_key_type(attributes))) { + memcpy(pubkey_buffer, key_buffer, key_buffer_size); + return PSA_SUCCESS; + } + sx_status = cracen_ed448_create_pubkey(key_buffer, pubkey_buffer); + return silex_statuscodes_to_psa(sx_status); + } + } + if (IS_ENABLED(PSA_NEED_CRACEN_ECDSA_SECP_R1) || IS_ENABLED(PSA_NEED_CRACEN_ECDSA_SECP_K1) || IS_ENABLED(PSA_NEED_CRACEN_ECDSA_BRAINPOOL_P_R1)) { @@ -152,7 +163,7 @@ static psa_status_t validate_key_attributes(const psa_key_attributes_t *attribut size_t key_buffer_size, const struct sx_pk_ecurve **ecurve) { - if (key_buffer_size != PSA_BITS_TO_BYTES(psa_get_key_bits(attributes))) { + if (key_buffer_size != (*ecurve)->sz) { return PSA_ERROR_BUFFER_TOO_SMALL; } if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(psa_get_key_type(attributes))) { @@ -166,7 +177,8 @@ static psa_status_t validate_signing_conditions(bool is_message, psa_algorithm_t const psa_key_attributes_t *attributes, size_t ecurve_sz, size_t signature_size) { - if (!PSA_ALG_IS_ECDSA(alg) && alg != PSA_ALG_PURE_EDDSA && alg != PSA_ALG_ED25519PH) { + if (!PSA_ALG_IS_ECDSA(alg) && alg != PSA_ALG_PURE_EDDSA && alg != PSA_ALG_ED25519PH + && alg != PSA_ALG_ED448PH) { return PSA_ERROR_INVALID_ARGUMENT; } @@ -200,6 +212,14 @@ static psa_status_t handle_eddsa_sign(bool is_message, const psa_key_attributes_ } return silex_statuscodes_to_psa(status); } + if (alg == PSA_ALG_ED448PH && IS_ENABLED(PSA_NEED_CRACEN_ED448PH)) { + status = cracen_ed448ph_sign(key_buffer, signature, input, input_length, + is_message); + if (status == SX_OK) { + *signature_length = 2 * ecurve->sz; + } + return silex_statuscodes_to_psa(status); + } if (alg == PSA_ALG_PURE_EDDSA && psa_get_key_bits(attributes) == 255 && IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_255)) { status = cracen_ed25519_sign(key_buffer, signature, input, input_length); @@ -208,6 +228,15 @@ static psa_status_t handle_eddsa_sign(bool is_message, const psa_key_attributes_ } return silex_statuscodes_to_psa(status); } + if (alg == PSA_ALG_PURE_EDDSA && psa_get_key_bits(attributes) == 448 && + IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448)) { + status = cracen_ed448_sign(key_buffer, signature, input, input_length); + if (status == SX_OK) { + *signature_length = 2 * ecurve->sz; + } + return silex_statuscodes_to_psa(status); + } + return PSA_ERROR_NOT_SUPPORTED; } @@ -327,8 +356,10 @@ static psa_status_t cracen_signature_ecc_sign(bool is_message, } if ((alg == PSA_ALG_PURE_EDDSA && - IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_255)) || - (alg == PSA_ALG_ED25519PH && IS_ENABLED(PSA_NEED_CRACEN_ED25519PH))) { + (IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_255) || + IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448))) || + (alg == PSA_ALG_ED25519PH && IS_ENABLED(PSA_NEED_CRACEN_ED25519PH)) || + (alg == PSA_ALG_ED448PH && IS_ENABLED(PSA_NEED_CRACEN_ED448PH))) { return handle_eddsa_sign(is_message, attributes, key_buffer, alg, signature, input, input_length, ecurve, signature_length); } else if (PSA_ALG_IS_ECDSA(alg) && (IS_ENABLED(PSA_NEED_CRACEN_ECDSA) || @@ -350,7 +381,7 @@ static psa_status_t validate_ec_signature_inputs(bool is_message, if (!(PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) || alg == PSA_ALG_PURE_EDDSA || alg == PSA_ALG_ED25519PH || - PSA_ALG_IS_HASH_EDDSA(alg))) { + alg == PSA_ALG_ED448PH || PSA_ALG_IS_HASH_EDDSA(alg))) { return PSA_ERROR_NOT_SUPPORTED; } @@ -401,10 +432,19 @@ static psa_status_t cracen_signature_ecc_verify(bool is_message, signature, is_message); } else if (IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_255) && - alg == PSA_ALG_PURE_EDDSA) { + alg == PSA_ALG_PURE_EDDSA && signature_length == SX_ED25519_DGST_SZ) { sx_status = cracen_ed25519_verify(pubkey_buffer, input, input_length, signature); + } else if (IS_ENABLED(PSA_NEED_CRACEN_ED448PH) && alg == PSA_ALG_ED448PH) { + sx_status = cracen_ed448ph_verify(pubkey_buffer, input, input_length, + signature, is_message); + + } else if (IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448) && + alg == PSA_ALG_PURE_EDDSA) { + sx_status = cracen_ed448_verify(pubkey_buffer, input, input_length, + signature); + } else if ((PSA_ALG_IS_ECDSA(alg) && IS_ENABLED(PSA_NEED_CRACEN_ECDSA)) || (IS_ENABLED(PSA_NEED_CRACEN_DETERMINISTIC_ECDSA) && PSA_ALG_IS_DETERMINISTIC_ECDSA(alg))) { diff --git a/subsys/nrf_security/src/drivers/cracen/psa_driver.Kconfig b/subsys/nrf_security/src/drivers/cracen/psa_driver.Kconfig index 6ba84c8bb33e..cd51c7f923a4 100644 --- a/subsys/nrf_security/src/drivers/cracen/psa_driver.Kconfig +++ b/subsys/nrf_security/src/drivers/cracen/psa_driver.Kconfig @@ -356,6 +356,14 @@ config PSA_NEED_CRACEN_ED25519PH depends on PSA_WANT_ECC_TWISTED_EDWARDS_255 depends on PSA_USE_CRACEN_ASYMMETRIC_SIGNATURE_DRIVER +config PSA_NEED_CRACEN_ED448PH + bool + default y + select PSA_ACCEL_ED448PH + depends on PSA_WANT_ALG_ED448PH + depends on PSA_WANT_ECC_TWISTED_EDWARDS_448 + depends on PSA_USE_CRACEN_ASYMMETRIC_SIGNATURE_DRIVER + config PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS bool default y @@ -368,7 +376,8 @@ config PSA_NEED_CRACEN_ASYMMETRIC_SIGNATURE_ANY_ECC depends on PSA_NEED_CRACEN_ECDSA_BRAINPOOL_P_R1 || \ PSA_NEED_CRACEN_ECDSA_SECP_R1 || \ PSA_NEED_CRACEN_ECDSA_SECP_K1 || \ - PSA_NEED_CRACEN_ED25519PH || \ + PSA_NEED_CRACEN_ED25519PH || \ + PSA_NEED_CRACEN_ED448PH || \ PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS config PSA_NEED_CRACEN_RSA_PKCS1V15_SIGN @@ -513,12 +522,14 @@ config PSA_NEED_CRACEN_SHA_512 select PSA_ACCEL_SHA_512 depends on PSA_WANT_ALG_SHA_512 depends on PSA_USE_CRACEN_HASH_DRIVER + config PSA_NEED_CRACEN_SHA3_224 bool default y select PSA_ACCEL_SHA3_224 depends on PSA_WANT_ALG_SHA3_224 depends on PSA_USE_CRACEN_HASH_DRIVER + config PSA_NEED_CRACEN_SHA3_256 bool default y @@ -540,6 +551,13 @@ config PSA_NEED_CRACEN_SHA3_512 depends on PSA_WANT_ALG_SHA3_512 depends on PSA_USE_CRACEN_HASH_DRIVER +config PSA_NEED_CRACEN_SHAKE256_512 + bool + default y + select PSA_ACCEL_SHAKE256_512 + depends on PSA_WANT_ALG_SHAKE256_512 + depends on PSA_USE_CRACEN_HASH_DRIVER + config PSA_NEED_CRACEN_HASH_DRIVER bool default y @@ -551,7 +569,8 @@ config PSA_NEED_CRACEN_HASH_DRIVER PSA_NEED_CRACEN_SHA3_224 || \ PSA_NEED_CRACEN_SHA3_256 || \ PSA_NEED_CRACEN_SHA3_384 || \ - PSA_NEED_CRACEN_SHA3_512 + PSA_NEED_CRACEN_SHA3_512 || \ + PSA_NEED_CRACEN_SHAKE256_512 # CRACEN Key Generation Driver diff --git a/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/include/sxsymcrypt/hashdefs.h b/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/include/sxsymcrypt/hashdefs.h index 539dc57fdf27..926ff7e10ad4 100644 --- a/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/include/sxsymcrypt/hashdefs.h +++ b/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/include/sxsymcrypt/hashdefs.h @@ -39,8 +39,7 @@ */ #if defined(PSA_NEED_CRACEN_SHA3_224) #define SX_HASH_MAX_ENABLED_BLOCK_SIZE SX_HASH_BLOCKSZ_SHA3_224 -#elif defined(PSA_NEED_CRACEN_SHA3_256) -/* SHAKE256 has the same size but doesn't have a PSA_NEED yet */ +#elif defined(PSA_NEED_CRACEN_SHA3_256) || defined(PSA_NEED_CRACEN_SHAKE256_512) #define SX_HASH_MAX_ENABLED_BLOCK_SIZE SX_HASH_BLOCKSZ_SHA3_256 #elif defined(PSA_NEED_CRACEN_SHA_512) || defined(PSA_NEED_CRACEN_SHA_384) #define SX_HASH_MAX_ENABLED_BLOCK_SIZE SX_HASH_BLOCKSZ_SHA2_512 @@ -67,8 +66,7 @@ */ #if defined(PSA_NEED_CRACEN_SHA3_224) #define SX_HASH_OPERATION_CONTEXT_SZ 344 -#elif defined(PSA_NEED_CRACEN_SHA3_256) -/* SHAKE256 has the same size but doesn't have a PSA_NEED yet */ +#elif defined(PSA_NEED_CRACEN_SHA3_256) || defined(PSA_NEED_CRACEN_SHAKE256_512) #define SX_HASH_OPERATION_CONTEXT_SZ 336 #elif defined(PSA_NEED_CRACEN_SHA3_384) #define SX_HASH_OPERATION_CONTEXT_SZ 304 @@ -172,6 +170,7 @@ extern const struct sxhashalg sxhashalg_sha3_512; /** Hash algorithm SHAKE256, with output size fixed to 114 bytes (for Ed448). */ extern const struct sxhashalg sxhashalg_shake256_114; +extern const struct sxhashalg sxhashalg_shake256_64; /** GM/T 0004-2012: SM3 cryptographic hash algorithm */ extern const struct sxhashalg sxhashalg_sm3; diff --git a/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/src/sha3.c b/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/src/sha3.c index df23a4cc4d0b..427ad489453c 100644 --- a/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/src/sha3.c +++ b/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/src/sha3.c @@ -150,3 +150,8 @@ const struct sxhashalg sxhashalg_shake256_114 = { SHA3_MODE_SHAKE(7, 114), SHA3_SW_PAD, SHA3_SAVE_CONTEXT, 114, SX_HASH_BLOCKSZ_SHA3_256, 200, 136, sx_hash_create_ba418_shake256 }; + +const struct sxhashalg sxhashalg_shake256_64 = { + SHA3_MODE_SHAKE(7, 64), SHA3_SW_PAD, SHA3_SAVE_CONTEXT, 64, + SX_HASH_BLOCKSZ_SHA3_256, 200, 136, sx_hash_create_ba418_shake256 +}; From ef357c1ee8189d878668f7fc26cc97ed42e5cc13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Ed=C3=B8y=20Hanssen?= Date: Fri, 14 Nov 2025 14:20:40 +0100 Subject: [PATCH 012/155] samples: crypto: psa_tls: Enable SSL cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable SSL cache by default for the psa_tls sample. Signed-off-by: Håkon Edøy Hanssen --- samples/crypto/psa_tls/prj.conf | 1 + samples/crypto/psa_tls/src/psa_dtls_functions_client.c | 9 +++++++++ samples/crypto/psa_tls/src/psa_dtls_functions_server.c | 9 +++++++++ samples/crypto/psa_tls/src/psa_tls_functions_client.c | 9 +++++++++ samples/crypto/psa_tls/src/psa_tls_functions_server.c | 9 +++++++++ 5 files changed, 37 insertions(+) diff --git a/samples/crypto/psa_tls/prj.conf b/samples/crypto/psa_tls/prj.conf index 5f3442c516d8..c39b1333f43d 100644 --- a/samples/crypto/psa_tls/prj.conf +++ b/samples/crypto/psa_tls/prj.conf @@ -52,6 +52,7 @@ CONFIG_MBEDTLS_HEAP_SIZE=32768 CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=2304 CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=2304 CONFIG_MBEDTLS_SSL_CLI_C=y +CONFIG_MBEDTLS_SSL_CACHE_C=y CONFIG_MBEDTLS_TLS_LIBRARY=y CONFIG_MBEDTLS_X509_LIBRARY=y diff --git a/samples/crypto/psa_tls/src/psa_dtls_functions_client.c b/samples/crypto/psa_tls/src/psa_dtls_functions_client.c index 167777717d4b..c9ff33de16b1 100644 --- a/samples/crypto/psa_tls/src/psa_dtls_functions_client.c +++ b/samples/crypto/psa_tls/src/psa_dtls_functions_client.c @@ -64,6 +64,15 @@ static int setup_dtls_client_socket(void) return -errno; } + int cache = TLS_SESSION_CACHE_ENABLED; + + err = setsockopt(sock, SOL_TLS, TLS_SESSION_CACHE, &cache, sizeof(cache)); + if (err < 0) { + LOG_ERR("Failed to set TLS Session cache. Err: %d", errno); + (void)close(sock); + return -errno; + } + return sock; } diff --git a/samples/crypto/psa_tls/src/psa_dtls_functions_server.c b/samples/crypto/psa_tls/src/psa_dtls_functions_server.c index 58e938f6ea25..b9eb5c2aa2d5 100644 --- a/samples/crypto/psa_tls/src/psa_dtls_functions_server.c +++ b/samples/crypto/psa_tls/src/psa_dtls_functions_server.c @@ -63,6 +63,15 @@ static int setup_dtls_server_socket(void) return -errno; } + int cache = TLS_SESSION_CACHE_ENABLED; + + err = setsockopt(sock, SOL_TLS, TLS_SESSION_CACHE, &cache, sizeof(cache)); + if (err < 0) { + LOG_ERR("Failed to set TLS Session cache. Err: %d", errno); + (void)close(sock); + return -errno; + } + err = bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (err < 0) { LOG_ERR("Failed to bind DTLS socket. Err: %d", errno); diff --git a/samples/crypto/psa_tls/src/psa_tls_functions_client.c b/samples/crypto/psa_tls/src/psa_tls_functions_client.c index ee8b8031c3db..30b6b4feaf0f 100644 --- a/samples/crypto/psa_tls/src/psa_tls_functions_client.c +++ b/samples/crypto/psa_tls/src/psa_tls_functions_client.c @@ -72,6 +72,15 @@ static int setup_tls_client_socket(void) return -errno; } + int cache = TLS_SESSION_CACHE_ENABLED; + + err = setsockopt(sock, SOL_TLS, TLS_SESSION_CACHE, &cache, sizeof(cache)); + if (err < 0) { + LOG_ERR("Failed to set TLS Session cache. Err: %d", errno); + (void)close(sock); + return -errno; + } + return sock; } diff --git a/samples/crypto/psa_tls/src/psa_tls_functions_server.c b/samples/crypto/psa_tls/src/psa_tls_functions_server.c index 3ea0030cd467..fdd472f69b0a 100644 --- a/samples/crypto/psa_tls/src/psa_tls_functions_server.c +++ b/samples/crypto/psa_tls/src/psa_tls_functions_server.c @@ -55,6 +55,15 @@ static int setup_tls_server_socket(void) return -errno; } + int cache = TLS_SESSION_CACHE_ENABLED; + + err = setsockopt(sock, SOL_TLS, TLS_SESSION_CACHE, &cache, sizeof(cache)); + if (err < 0) { + LOG_ERR("Failed to set TLS Session cache. Err: %d", errno); + (void)close(sock); + return -errno; + } + err = bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (err < 0) { LOG_ERR("Failed to bind TLS socket. Err: %d", errno); From c4ccbb88868bb6f7012673ff454e3fa866b5fde5 Mon Sep 17 00:00:00 2001 From: Szymon Antkowiak Date: Mon, 1 Dec 2025 08:18:10 +0100 Subject: [PATCH 013/155] esb: fix timer initialization error codes nrfx 4.0 switching to using errno error codes. Fix missing align in ESB. Signed-off-by: Szymon Antkowiak --- subsys/esb/esb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/esb/esb.c b/subsys/esb/esb.c index 4dda6ca6f03c..b8f6c832d582 100644 --- a/subsys/esb/esb.c +++ b/subsys/esb/esb.c @@ -1241,16 +1241,16 @@ static void esb_timer_handler(nrf_timer_event_t event_type, void *context) static int sys_timer_init(void) { - nrfx_err_t nrfx_err; + int err; const nrfx_timer_config_t config = { .frequency = NRFX_MHZ_TO_HZ(1), .mode = NRF_TIMER_MODE_TIMER, .bit_width = NRF_TIMER_BIT_WIDTH_16, }; - nrfx_err = nrfx_timer_init(&esb_timer, &config, esb_timer_handler); - if (nrfx_err != NRFX_SUCCESS) { - LOG_ERR("Failed to initialize nrfx timer (err %d)", nrfx_err); + err = nrfx_timer_init(&esb_timer, &config, esb_timer_handler); + if (err) { + LOG_ERR("Failed to initialize nrfx timer (err %d)", err); return -EFAULT; } From 1a5d23e3e38a2f094a2d156dfdc250efbd2924c6 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Thu, 27 Nov 2025 13:15:02 +0000 Subject: [PATCH 014/155] manifest: Update sdk-connectedhomeip revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-connectedhomeip/pull/681 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 4e869f686633..c392c13ab861 100644 --- a/west.yml +++ b/west.yml @@ -155,7 +155,7 @@ manifest: - name: matter repo-path: sdk-connectedhomeip path: modules/lib/matter - revision: bce9dd5a9e2e58bf2c0b762c4385dbb3f11f686a + revision: b9ffabef417865b481d1d737c6d539ff8dab21a2 west-commands: scripts/west/west-commands.yml submodules: - name: nlio From be9f5d7e2922007b5a44c8484cc6e376968e97f3 Mon Sep 17 00:00:00 2001 From: Dominik Chat Date: Thu, 27 Nov 2025 11:58:20 +0100 Subject: [PATCH 015/155] esb: Cleanup workaround implementations Remove HMPAN-18 and HMPAN-102. Correct HMPAN-103 and HMPAN-229. Move workarounds to separate file for easier tracking. Jira: NCSDK-36550 Signed-off-by: Dominik Chat --- subsys/esb/esb.c | 143 +++++------------------------- subsys/esb/esb_workarounds.h | 166 +++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 121 deletions(-) create mode 100644 subsys/esb/esb_workarounds.h diff --git a/subsys/esb/esb.c b/subsys/esb/esb.c index b8f6c832d582..20d9eeb57e5c 100644 --- a/subsys/esb/esb.c +++ b/subsys/esb/esb.c @@ -22,14 +22,12 @@ #include #include #include -#if NRF54H_ERRATA_216_PRESENT -#include -#endif /* NRF54H_ERRATA_216_PRESENT */ #include #include "esb_peripherals.h" #include "esb_ppi_api.h" +#include "esb_workarounds.h" LOG_MODULE_REGISTER(esb, CONFIG_ESB_LOG_LEVEL); @@ -267,13 +265,6 @@ enum { static atomic_t errata_216_status = ATOMIC_INIT(ERRATA_216_DISABLED); static uint32_t errata_216_timer_shorts; -#if NRF54H_ERRATA_216_PRESENT -static const struct mbox_dt_spec on_channel = - MBOX_DT_SPEC_GET(DT_NODELABEL(cpurad_cpusys_errata216_mboxes), on_req); -static const struct mbox_dt_spec off_channel = - MBOX_DT_SPEC_GET(DT_NODELABEL(cpurad_cpusys_errata216_mboxes), off_req); -#endif /* NRF54H_ERRATA_216_PRESENT */ - static esb_event_handler event_handler; static struct esb_payload *current_payload; @@ -380,39 +371,14 @@ static inline void apply_errata143_workaround(void) * use a unique address 0 since this will avoid the 3dBm penalty * incurred from the workaround. */ - uint32_t base_address_mask = - esb_addr.addr_length == 5 ? 0xFFFF0000 : 0xFF000000; - /* Load the two addresses before comparing them to ensure - * defined ordering of volatile accesses. - */ - uint32_t addr0 = nrf_radio_base0_get(NRF_RADIO) & base_address_mask; - uint32_t addr1 = nrf_radio_base1_get(NRF_RADIO) & base_address_mask; - - if (addr0 == addr1) { - uint32_t radio_prefix0 = nrf_radio_prefix0_get(NRF_RADIO); - uint32_t radio_prefix1 = nrf_radio_prefix1_get(NRF_RADIO); - - uint8_t prefix0 = radio_prefix0 & RADIO_PREFIX0_AP0_Msk; - uint8_t prefix1 = (radio_prefix0 & RADIO_PREFIX0_AP1_Msk) >> RADIO_PREFIX0_AP1_Pos; - uint8_t prefix2 = (radio_prefix0 & RADIO_PREFIX0_AP2_Msk) >> RADIO_PREFIX0_AP2_Pos; - uint8_t prefix3 = (radio_prefix0 & RADIO_PREFIX0_AP3_Msk) >> RADIO_PREFIX0_AP3_Pos; - uint8_t prefix4 = radio_prefix1 & RADIO_PREFIX1_AP4_Msk; - uint8_t prefix5 = (radio_prefix1 & RADIO_PREFIX1_AP5_Msk) >> RADIO_PREFIX1_AP5_Pos; - uint8_t prefix6 = (radio_prefix1 & RADIO_PREFIX1_AP6_Msk) >> RADIO_PREFIX1_AP6_Pos; - uint8_t prefix7 = (radio_prefix1 & RADIO_PREFIX1_AP7_Msk) >> RADIO_PREFIX1_AP7_Pos; - - if ((prefix0 == prefix1) || (prefix0 == prefix2) || - (prefix0 == prefix3) || (prefix0 == prefix4) || - (prefix0 == prefix5) || (prefix0 == prefix6) || - (prefix0 == prefix7)) { - /* This will cause a 3dBm sensitivity loss, - * avoid using such address combinations if possible. - */ - *(volatile uint32_t *)0x40001774 = - ((*(volatile uint32_t *)0x40001774) & 0xfffffffe) | 0x01000000; - } + if (!nrf52_errata_143()) { + return; } + + uint32_t base_address_mask = + esb_addr.addr_length == 5 ? 0xFFFF0000 : 0xFF000000; + esb_apply_nrf52_143(base_address_mask); } static void errata_216_on(void) @@ -421,15 +387,11 @@ static void errata_216_on(void) return; } -#if NRF54H_ERRATA_216_PRESENT - if (mbox_send_dt(&on_channel, NULL) != 0) { - LOG_ERR("Failed to enable Errata 216"); - /* Should not happen. */ - __ASSERT_NO_MSG(false); - } else { - atomic_set(&errata_216_status, ERRATA_216_ENABLED); - } -#endif /* NRF54H_ERRATA_216_PRESENT */ + esb_apply_nrf54h_216(true); + +#if NRF54H_ERRATA_216_ENABLE_WORKAROUND + atomic_set(&errata_216_status, ERRATA_216_ENABLED); +#endif /* NRF54H_ERRATA_216_ENABLE_WORKAROUND */ } static void errata_216_off(void) @@ -438,86 +400,25 @@ static void errata_216_off(void) return; } -#if NRF54H_ERRATA_216_PRESENT - if (mbox_send_dt(&off_channel, NULL) != 0) { - LOG_ERR("Failed to disable Errata 216"); - /* Should not happen. */ - __ASSERT_NO_MSG(false); - } else { - atomic_set(&errata_216_status, ERRATA_216_DISABLED); - } -#endif /* NRF54H_ERRATA_216_PRESENT */ + esb_apply_nrf54h_216(false); + +#if NRF54H_ERRATA_216_ENABLE_WORKAROUND + atomic_set(&errata_216_status, ERRATA_216_DISABLED); +#endif /* NRF54H_ERRATA_216_ENABLE_WORKAROUND */ } static void apply_radio_init_workarounds(void) { if (nrf52_errata_182()) { - /* Check if the device is an nRF52832 Rev. 2. */ - /* Workaround for nRF52832 rev 2 errata 182 */ - *(volatile uint32_t *)0x4000173C |= (1 << 10); - } - -#if defined(CONFIG_SOC_SERIES_NRF54HX) - /* Apply HMPAN-102 workaround for nRF54H series */ - *(volatile uint32_t *)0x5302C7E4 = - (((*((volatile uint32_t *)0x5302C7E4)) & 0xFF000FFF) | 0x0012C000); - - /* Apply HMPAN-18 workaround for nRF54H series - load trim values*/ - if (*(volatile uint32_t *)0x0FFFE458 != TRIM_VALUE_EMPTY) { - *(volatile uint32_t *)0x5302C734 = *(volatile uint32_t *)0x0FFFE458; - } - - if (*(volatile uint32_t *)0x0FFFE45C != TRIM_VALUE_EMPTY) { - *(volatile uint32_t *)0x5302C738 = *(volatile uint32_t *)0x0FFFE45C; - } - - if (*(volatile uint32_t *)0x0FFFE460 != TRIM_VALUE_EMPTY) { - *(volatile uint32_t *)0x5302C73C = *(volatile uint32_t *)0x0FFFE460; - } - - if (*(volatile uint32_t *)0x0FFFE464 != TRIM_VALUE_EMPTY) { - *(volatile uint32_t *)0x5302C740 = *(volatile uint32_t *)0x0FFFE464; - } - - if (*(volatile uint32_t *)0x0FFFE468 != TRIM_VALUE_EMPTY) { - *(volatile uint32_t *)0x5302C74C = *(volatile uint32_t *)0x0FFFE468; - } - - /* HMPAN-229 provides hardcoded value if the trim value is 0 */ - if ((*(volatile uint32_t *)0x0FFFE46C != TRIM_VALUE_EMPTY) && - (*(volatile uint32_t *)0x0FFFE46C != 0)) { - *(volatile uint32_t *)0x5302C7D8 = *(volatile uint32_t *)0x0FFFE46C; - } else { - *(volatile uint32_t *)0x5302C7D8 = 0x00000004; - } - - if (*(volatile uint32_t *)0x0FFFE470 != TRIM_VALUE_EMPTY) { - *(volatile uint32_t *)0x5302C840 = *(volatile uint32_t *)0x0FFFE470; - } - - if (*(volatile uint32_t *)0x0FFFE474 != TRIM_VALUE_EMPTY) { - *(volatile uint32_t *)0x5302C844 = *(volatile uint32_t *)0x0FFFE474; - } - - if (*(volatile uint32_t *)0x0FFFE478 != TRIM_VALUE_EMPTY) { - *(volatile uint32_t *)0x5302C848 = *(volatile uint32_t *)0x0FFFE478; - } - - if (*(volatile uint32_t *)0x0FFFE47C != TRIM_VALUE_EMPTY) { - *(volatile uint32_t *)0x5302C84C = *(volatile uint32_t *)0x0FFFE47C; + esb_apply_nrf52_182(); } - /* Apply HMPAN-103 workaround for nRF54H series*/ - if ((*(volatile uint32_t *)0x5302C8A0 == 0x80000000) || - (*(volatile uint32_t *)0x5302C8A0 == 0x0058120E)) { - *(volatile uint32_t *)0x5302C8A0 = 0x0058090E; + if (nrf54h_errata_103()) { + esb_apply_nrf54h_103(); } - *(volatile uint32_t *)0x5302C8A4 = 0x00F8AA5F; - *(volatile uint32_t *)0x5302C7AC = 0x8672827A; - *(volatile uint32_t *)0x5302C7B0 = 0x7E768672; - *(volatile uint32_t *)0x5302C7B4 = 0x0406007E; -#endif /* (CONFIG_SOC_SERIES_NRF54HX) */ + /* Currently there is no check for this workaround */ + esb_apply_nrf54h_229(); } static void esb_fem_for_tx_set(bool ack) diff --git a/subsys/esb/esb_workarounds.h b/subsys/esb/esb_workarounds.h new file mode 100644 index 000000000000..6882fb930794 --- /dev/null +++ b/subsys/esb/esb_workarounds.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef ESB_WORKAROUNDS_H__ +#define ESB_WORKAROUNDS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include + +#if NRF54H_ERRATA_216_ENABLE_WORKAROUND +#include +#endif /* NRF54H_ERRATA_216_ENABLE_WORKAROUND */ + +/* nRF52 Workaround 182 */ +static void esb_apply_nrf52_182(void); + +/* nRF52 Workaround 143 */ +static void esb_apply_nrf52_143(uint32_t base_address_mask); + +/* nRF54H Workaround 84 */ +/* HMPAN-84 is implemented in the ESB samples in the clocks_start function */ + +/* nRF54H Workaround 103 */ +static void esb_apply_nrf54h_103(void); + +/* nRF54H Workaround 216 */ +static void esb_apply_nrf54h_216(bool on); + +/* nRF54H Workaround 229 */ +static void esb_apply_nrf54h_229(void); + +/* nRF54L Workaround 20 */ +/* MLTPAN-20 is implemented in the ESB samples in the clocks_start function */ + +/* nRF54L Workaround 39 */ +/* MLTPAN-39 is implemented in the ESB samples in the clocks_start function */ + +#if NRF52_ERRATA_143_ENABLE_WORKAROUND +static void esb_apply_nrf52_143(uint32_t base_address_mask) +{ + /* Load the two addresses before comparing them to ensure + * defined ordering of volatile accesses. + */ + uint32_t addr0 = nrf_radio_base0_get(NRF_RADIO) & base_address_mask; + uint32_t addr1 = nrf_radio_base1_get(NRF_RADIO) & base_address_mask; + + if (addr0 == addr1) { + uint32_t radio_prefix0 = nrf_radio_prefix0_get(NRF_RADIO); + uint32_t radio_prefix1 = nrf_radio_prefix1_get(NRF_RADIO); + + uint8_t prefix0 = radio_prefix0 & RADIO_PREFIX0_AP0_Msk; + uint8_t prefix1 = (radio_prefix0 & RADIO_PREFIX0_AP1_Msk) >> RADIO_PREFIX0_AP1_Pos; + uint8_t prefix2 = (radio_prefix0 & RADIO_PREFIX0_AP2_Msk) >> RADIO_PREFIX0_AP2_Pos; + uint8_t prefix3 = (radio_prefix0 & RADIO_PREFIX0_AP3_Msk) >> RADIO_PREFIX0_AP3_Pos; + uint8_t prefix4 = radio_prefix1 & RADIO_PREFIX1_AP4_Msk; + uint8_t prefix5 = (radio_prefix1 & RADIO_PREFIX1_AP5_Msk) >> RADIO_PREFIX1_AP5_Pos; + uint8_t prefix6 = (radio_prefix1 & RADIO_PREFIX1_AP6_Msk) >> RADIO_PREFIX1_AP6_Pos; + uint8_t prefix7 = (radio_prefix1 & RADIO_PREFIX1_AP7_Msk) >> RADIO_PREFIX1_AP7_Pos; + + if ((prefix0 == prefix1) || (prefix0 == prefix2) || + (prefix0 == prefix3) || (prefix0 == prefix4) || + (prefix0 == prefix5) || (prefix0 == prefix6) || + (prefix0 == prefix7)) { + /* This will cause a 3dBm sensitivity loss, + * avoid using such address combinations if possible. + */ + *(volatile uint32_t *)0x40001774 = + ((*(volatile uint32_t *)0x40001774) & 0xfffffffe) | 0x01000000; + } + } +} +#else +static void esb_apply_nrf52_143(uint32_t base_address_mask) +{ + ARG_UNUSED(base_address_mask); +} +#endif /* NRF52_ERRATA_143_ENABLE_WORKAROUND */ + +#if NRF52_ERRATA_182_ENABLE_WORKAROUND +static void esb_apply_nrf52_182(void) +{ + *(volatile uint32_t *)0x4000173C |= (1 << 10); +} +#else +static void esb_apply_nrf52_182(void) +{ + /* No implementation needed */ +} +#endif /* NRF52_ERRATA_182_ENABLE_WORKAROUND */ + +#if NRF54H_ERRATA_103_ENABLE_WORKAROUND +static void esb_apply_nrf54h_103(void) +{ + if ((*(volatile uint32_t *)0x5302C8A0 == 0x80000000) || + (*(volatile uint32_t *)0x5302C8A0 == 0x0058120E)) { + *(volatile uint32_t *)0x5302C8A0 = 0x0058090E; + } + + *(volatile uint32_t *)0x5302C8A4 = 0x00F8AA5F; + *(volatile uint32_t *)0x5302C8A8 = 0x00C00030; + *(volatile uint32_t *)0x5302C8AC = 0x00A80030; + *(volatile uint32_t *)0x5302C7AC = 0x8672827A; + *(volatile uint32_t *)0x5302C7B0 = 0x7E768672; + *(volatile uint32_t *)0x5302C7B4 = 0x0406007E; + *(volatile uint32_t *)0x5302C7E4 = 0x0412C384; +} +#else +static void esb_apply_nrf54h_103(void) +{ + /* No implementation needed */ +} +#endif /* NRF54H_ERRATA_103_ENABLE_WORKAROUND */ + +#if NRF54H_ERRATA_216_ENABLE_WORKAROUND +static inline void esb_apply_nrf54h_216(bool on) +{ + static const struct mbox_dt_spec on_channel = + MBOX_DT_SPEC_GET(DT_NODELABEL(cpurad_cpusys_errata216_mboxes), on_req); + static const struct mbox_dt_spec off_channel = + MBOX_DT_SPEC_GET(DT_NODELABEL(cpurad_cpusys_errata216_mboxes), off_req); + const struct mbox_dt_spec *spec = on ? &on_channel : &off_channel; + + if (!IS_ENABLED(NRF54H_ERRATA_216_ENABLE_WORKAROUND)) { + return; + } + + if (mbox_send_dt(spec, NULL)) { + /* Should not happen. */ + __ASSERT_NO_MSG(false); + } +} +#else +static void esb_apply_nrf54h_216(bool on) +{ + ARG_UNUSED(on); +} +#endif /* NRF54H_ERRATA_216_ENABLE_WORKAROUND*/ + +#if defined(CONFIG_SOC_SERIES_NRF54HX) +static void esb_apply_nrf54h_229(void) +{ + if (*(volatile uint32_t *)0x0FFFE46C == 0x0) { + *(volatile uint32_t *)0x5302C7D8 = 0x00000004; + } +} +#else +static void esb_apply_nrf54h_229(void) +{ + /* No implementation needed */ +} +#endif /* (CONFIG_SOC_SERIES_NRF54HX) */ + +#ifdef __cplusplus +} +#endif + +#endif /* ESB_WORKAROUNDS_H__ */ From 78238e5db61c4d97b3307e7d8e0209d367ed1245 Mon Sep 17 00:00:00 2001 From: Dominik Chat Date: Thu, 27 Nov 2025 15:15:55 +0100 Subject: [PATCH 016/155] samples: esb: Add note and check about HMPAN-84 Add check if to apply HMPAN-84. Add note about HMPAN-84 to esb samples. Jira: NCSDK-36550 Signed-off-by: Dominik Chat --- samples/esb/esb_monitor/src/main.c | 7 +++++-- samples/esb/esb_prx/src/main.c | 7 +++++-- samples/esb/esb_ptx/src/main.c | 7 +++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/samples/esb/esb_monitor/src/main.c b/samples/esb/esb_monitor/src/main.c index d4f5a07e4c94..e629b68495fc 100644 --- a/samples/esb/esb_monitor/src/main.c +++ b/samples/esb/esb_monitor/src/main.c @@ -183,8 +183,11 @@ int clocks_start(void) } } while (err == -EAGAIN); - nrf_lrcconf_clock_always_run_force_set(NRF_LRCCONF000, 0, true); - nrf_lrcconf_task_trigger(NRF_LRCCONF000, NRF_LRCCONF_TASK_CLKSTART_0); + /* HMPAN-84 */ + if (nrf54h_errata_84()) { + nrf_lrcconf_clock_always_run_force_set(NRF_LRCCONF000, 0, true); + nrf_lrcconf_task_trigger(NRF_LRCCONF000, NRF_LRCCONF_TASK_CLKSTART_0); + } LOG_DBG("HF clock started"); diff --git a/samples/esb/esb_prx/src/main.c b/samples/esb/esb_prx/src/main.c index 27a387a85034..acdf28e203b1 100644 --- a/samples/esb/esb_prx/src/main.c +++ b/samples/esb/esb_prx/src/main.c @@ -144,8 +144,11 @@ int clocks_start(void) } } while (err == -EAGAIN); - nrf_lrcconf_clock_always_run_force_set(NRF_LRCCONF000, 0, true); - nrf_lrcconf_task_trigger(NRF_LRCCONF000, NRF_LRCCONF_TASK_CLKSTART_0); + /* HMPAN-84 */ + if (nrf54h_errata_84()) { + nrf_lrcconf_clock_always_run_force_set(NRF_LRCCONF000, 0, true); + nrf_lrcconf_task_trigger(NRF_LRCCONF000, NRF_LRCCONF_TASK_CLKSTART_0); + } LOG_DBG("HF clock started"); diff --git a/samples/esb/esb_ptx/src/main.c b/samples/esb/esb_ptx/src/main.c index 9effc6bde522..9b84ade02df2 100644 --- a/samples/esb/esb_ptx/src/main.c +++ b/samples/esb/esb_ptx/src/main.c @@ -134,8 +134,11 @@ int clocks_start(void) } } while (err == -EAGAIN); - nrf_lrcconf_clock_always_run_force_set(NRF_LRCCONF000, 0, true); - nrf_lrcconf_task_trigger(NRF_LRCCONF000, NRF_LRCCONF_TASK_CLKSTART_0); + /* HMPAN-84 */ + if (nrf54h_errata_84()) { + nrf_lrcconf_clock_always_run_force_set(NRF_LRCCONF000, 0, true); + nrf_lrcconf_task_trigger(NRF_LRCCONF000, NRF_LRCCONF_TASK_CLKSTART_0); + } LOG_DBG("HF clock started"); return 0; From be663023e40bd6e6ace3f58cfb23442d6aae5d0c Mon Sep 17 00:00:00 2001 From: Dominik Chat Date: Thu, 27 Nov 2025 15:22:07 +0100 Subject: [PATCH 017/155] doc: Add changelog entry to ESB about Erratas Add changelog entry to ESB about handling erratas. Signed-off-by: Dominik Chat --- .../releases/release-notes-changelog.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index 18a73500bea1..b332588b1842 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -229,6 +229,11 @@ Enhanced ShockBurst (ESB) * A workaround for the hardware errata HMPAN-229 for the nRF54H20 SoC. +* Updated: + + * Workaround handling for the hardware erratas. + * The implementation of the hardware errata HMPAN-103 for the nRF54H20 SoC. + Gazell ------ From 0fa342c78130026ed35ae76fe92ddc68ed53dbdf Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Thu, 27 Nov 2025 11:56:00 +0100 Subject: [PATCH 018/155] samples: nrf_rpc: protocols_serialization: nRF54LM20 support Bring the support for nRF54LM20 DK in protocols serialization client and server samples. Signed-off-by: Damian Krolik --- .../protocols_serialization/client/README.rst | 2 +- .../nrf54lm20dk_nrf54lm20a_cpuapp.overlay | 54 ++++++++++++++++++ .../client/sample.yaml | 2 + .../protocols_serialization/server/README.rst | 34 ++++++++++- .../boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf | 7 +++ .../nrf54lm20dk_nrf54lm20a_cpuapp.overlay | 57 +++++++++++++++++++ ...m_static_nrf54lm20dk_nrf54lm20a_cpuapp.yml | 4 ++ .../server/sample.yaml | 2 + 8 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 samples/nrf_rpc/protocols_serialization/client/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay create mode 100644 samples/nrf_rpc/protocols_serialization/server/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf create mode 100644 samples/nrf_rpc/protocols_serialization/server/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay create mode 100644 samples/nrf_rpc/protocols_serialization/server/pm_static_nrf54lm20dk_nrf54lm20a_cpuapp.yml diff --git a/samples/nrf_rpc/protocols_serialization/client/README.rst b/samples/nrf_rpc/protocols_serialization/client/README.rst index d2cba9a8f827..d945d3441f07 100644 --- a/samples/nrf_rpc/protocols_serialization/client/README.rst +++ b/samples/nrf_rpc/protocols_serialization/client/README.rst @@ -64,7 +64,7 @@ Testing To test the client sample, follow the instructions in the :ref:`protocols_serialization_server_sample_testing` section of the protocol serialization server sample test procedure. .. note:: - When using the nRF54L15 DK, do not press **Button 1** or **Button 2**. + When using the nRF54L15 DK or nRF54LM20 DK, do not press **Button 1** or **Button 2**. The GPIO pins connected to these buttons are used by the UART peripheral for communication with the server device. Dependencies diff --git a/samples/nrf_rpc/protocols_serialization/client/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/samples/nrf_rpc/protocols_serialization/client/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 000000000000..e744993e0723 --- /dev/null +++ b/samples/nrf_rpc/protocols_serialization/client/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,54 @@ +/* Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + chosen { + nordic,rpc-uart = &uart21; + }; + + /* delete all buttons except button0 to free GPIO pins assigned to uart21 below */ + aliases { + /delete-property/ sw1; + /delete-property/ sw2; + /delete-property/ sw3; + }; +}; + +/delete-node/ &button1; +/delete-node/ &button2; +/delete-node/ &button3; + +&pinctrl { + uart21_default: uart21_default { + group1 { + psels = , + , + ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart21_sleep: uart21_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; +}; + +&uart21 { + status = "okay"; + current-speed = <1000000>; + pinctrl-0 = <&uart21_default>; + pinctrl-1 = <&uart21_sleep>; + pinctrl-names = "default", "sleep"; + hw-flow-control; +}; diff --git a/samples/nrf_rpc/protocols_serialization/client/sample.yaml b/samples/nrf_rpc/protocols_serialization/client/sample.yaml index 92ab0b1bc333..50f750545fd0 100644 --- a/samples/nrf_rpc/protocols_serialization/client/sample.yaml +++ b/samples/nrf_rpc/protocols_serialization/client/sample.yaml @@ -9,9 +9,11 @@ common: platform_allow: - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp tags: - ci_build - ci_samples_nrf_rpc diff --git a/samples/nrf_rpc/protocols_serialization/server/README.rst b/samples/nrf_rpc/protocols_serialization/server/README.rst index d4ceac722f2e..78a33ba6d249 100644 --- a/samples/nrf_rpc/protocols_serialization/server/README.rst +++ b/samples/nrf_rpc/protocols_serialization/server/README.rst @@ -63,7 +63,7 @@ User interface This is used for testing the core dump feature. * Otherwise: not available. - .. group-tab:: nRF54L15 DK + .. group-tab:: nRF54L15 and nRF54LM20 DKs Button 0: @@ -86,7 +86,7 @@ Testing After building the Protocols serialization server sample and programming it to your development kit, connect it to a second device running the :ref:`Protocol serialization client ` sample to test either the Bluetooth LE, OpenThread or NFC functionality. .. note:: - When using the nRF54L15 DK, do not press **Button 1** or **Button 2**. + When using the nRF54L15 DK or nRF54LM20 DK, do not press **Button 1** or **Button 2**. The GPIO pins connected to these buttons are used by the UART peripheral for communication with the client device. .. _protocols_serialization_server_app_connection: @@ -167,6 +167,36 @@ One peripheral is used for shell and logging purposes, similarly to other applic .. figure:: /images/ps_nrf54l_connections.webp :alt: nRF54L15 DK server and client pin connections + .. group-tab:: nRF54LM20 DK + + By default, the nRF54LM20 DK uses the ``uart20`` peripheral for shell and logging purposes, and the ``uart21`` peripheral for sending and receiving remote procedure calls (RPCs). + + The ``uart21`` peripheral is configured to use the following pins: + + .. list-table:: + :header-rows: 1 + + * - Server + - Client + - Function on server + * - **P1.9** + - **P1.8** + - RX + * - **P1.8** + - **P1.9** + - TX + * - **P1.11** + - **P1.12** + - RTS (hardware flow control) + * - **P1.12** + - **P1.11** + - CTS (hardware flow control) + * - **GND** + - **GND** + - Ground + + To enable the communication between the client and the server devices, connect the pins on the two nRF54LM20 DKs using jumper wires. + Testing Bluetooth LE API serialization ====================================== diff --git a/samples/nrf_rpc/protocols_serialization/server/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/samples/nrf_rpc/protocols_serialization/server/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf new file mode 100644 index 000000000000..d81cd861e744 --- /dev/null +++ b/samples/nrf_rpc/protocols_serialization/server/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf @@ -0,0 +1,7 @@ +# +# Copyright (c) 2025 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +CONFIG_MAIN_STACK_SIZE=4196 +CONFIG_NRF_RPC_THREAD_STACK_SIZE=6144 diff --git a/samples/nrf_rpc/protocols_serialization/server/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/samples/nrf_rpc/protocols_serialization/server/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 000000000000..cd029f94c778 --- /dev/null +++ b/samples/nrf_rpc/protocols_serialization/server/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,57 @@ +/* Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + chosen { + nordic,rpc-uart = &uart21; + }; + + aliases { + rpc-alive-led = &led0; + fatal-error-trigger = &button0; + + /* delete all buttons except button0 to free GPIO pins assigned to uart21 below */ + /delete-property/ sw1; + /delete-property/ sw2; + /delete-property/ sw3; + }; +}; + +/delete-node/ &button1; +/delete-node/ &button2; +/delete-node/ &button3; + +&pinctrl { + uart21_default: uart21_default { + group1 { + psels = , + , + ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart21_sleep: uart21_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; +}; + +&uart21 { + status = "okay"; + current-speed = <1000000>; + pinctrl-0 = <&uart21_default>; + pinctrl-1 = <&uart21_sleep>; + pinctrl-names = "default", "sleep"; + hw-flow-control; +}; diff --git a/samples/nrf_rpc/protocols_serialization/server/pm_static_nrf54lm20dk_nrf54lm20a_cpuapp.yml b/samples/nrf_rpc/protocols_serialization/server/pm_static_nrf54lm20dk_nrf54lm20a_cpuapp.yml new file mode 100644 index 000000000000..cff1116c1d7e --- /dev/null +++ b/samples/nrf_rpc/protocols_serialization/server/pm_static_nrf54lm20dk_nrf54lm20a_cpuapp.yml @@ -0,0 +1,4 @@ +coredump_partition: + region: flash_primary + address: 0x1fa000 + size: 0x3000 diff --git a/samples/nrf_rpc/protocols_serialization/server/sample.yaml b/samples/nrf_rpc/protocols_serialization/server/sample.yaml index 138c86587e9b..79b0ede838dc 100644 --- a/samples/nrf_rpc/protocols_serialization/server/sample.yaml +++ b/samples/nrf_rpc/protocols_serialization/server/sample.yaml @@ -9,9 +9,11 @@ common: platform_allow: - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp tags: - ci_build - ci_samples_nrf_rpc From a423f4b14d2da252fc7bea7e79c27e0e509dcf10 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 27 Nov 2025 19:17:39 +0530 Subject: [PATCH 019/155] doc: sml: wifi: Add nRF54LM20A support Add support as "experimental" for Wi-Fi using nRF7002 EB-II. Signed-off-by: Chaitanya Tata --- .../releases_and_maturity/software_maturity.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/nrf/releases_and_maturity/software_maturity.rst b/doc/nrf/releases_and_maturity/software_maturity.rst index 66d6e909a5ac..70fd7b76edfa 100644 --- a/doc/nrf/releases_and_maturity/software_maturity.rst +++ b/doc/nrf/releases_and_maturity/software_maturity.rst @@ -379,7 +379,7 @@ The following table indicates the software maturity levels of the support for ea - -- - -- - Experimental\ :sup:`3` - - -- + - Experimental\ :sup:`3` - -- * - **Zigbee** - --\ :sup:`5` @@ -2063,25 +2063,25 @@ The following table indicates the software maturity levels of the support for ea - -- - -- - -- - - -- + - Experimental\ :sup:`4` - -- * - **Monitor Mode** - -- - -- - Experimental\ :sup:`4` - - -- + - Experimental\ :sup:`4` - -- * - **Promiscuous Mode** - -- - -- - Experimental\ :sup:`4` - - -- + - Experimental\ :sup:`4` - -- * - **STA Mode** - -- - -- - Experimental\ :sup:`4` - - -- + - Experimental\ :sup:`4` - -- * - **Scan only (for location accuracy)** - -- @@ -2093,13 +2093,13 @@ The following table indicates the software maturity levels of the support for ea - -- - -- - Experimental\ :sup:`4` - - -- + - Experimental\ :sup:`4` - -- * - **TX injection Mode** - -- - -- - Experimental\ :sup:`4` - - -- + - Experimental\ :sup:`4` - -- * - **Thread Coexistence** - -- From 8458f8ba63f382f67d6e76ef739054cb5cb8e1f7 Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Wed, 19 Nov 2025 10:09:19 +0100 Subject: [PATCH 020/155] openthread: rpc: avoid sending instance pointer over RPC All functions except otInstanceXXX skipped sending a pointer to otInstance and simply assumed that only a single instance is supported. Rework otInstanceXXX APIs to make them consistent with the rest and more portable. Signed-off-by: Damian Krolik --- .../openthread/rpc/client/ot_rpc_instance.c | 31 ++++---- .../openthread/rpc/server/ot_rpc_instance.c | 71 +++--------------- .../rpc/client/src/instance_suite.c | 74 +++++++------------ .../rpc/server/src/instance_suite.c | 73 +++++------------- 4 files changed, 74 insertions(+), 175 deletions(-) diff --git a/subsys/net/openthread/rpc/client/ot_rpc_instance.c b/subsys/net/openthread/rpc/client/ot_rpc_instance.c index 06f4d7f87ac4..7f96af04caaf 100644 --- a/subsys/net/openthread/rpc/client/ot_rpc_instance.c +++ b/subsys/net/openthread/rpc/client/ot_rpc_instance.c @@ -13,18 +13,23 @@ #include +/* + * The actual otInstance object resides on OT RPC server and is only accessed by OT RPC client using + * remote OpenThread API calls. Nevertheless, otInstanceInitSingle() on OT RPC client shall return a + * valid non-null address, so the variable below is defined to represent otInstance object. + */ +static char ot_instance; + otInstance *otInstanceInitSingle(void) { struct nrf_rpc_cbor_ctx ctx; - uintptr_t instance_rep; NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 0); - nrf_rpc_cbor_cmd_rsp_no_err(&ot_group, OT_RPC_CMD_INSTANCE_INIT_SINGLE, &ctx); - nrf_rpc_rsp_decode_uint(&ot_group, &ctx, &instance_rep, sizeof(instance_rep)); - nrf_rpc_cbor_decoding_done(&ot_group, &ctx); + nrf_rpc_cbor_cmd_no_err(&ot_group, OT_RPC_CMD_INSTANCE_INIT_SINGLE, &ctx, + nrf_rpc_rsp_decode_void, NULL); - return (otInstance *)instance_rep; + return (otInstance *)&ot_instance; } uint32_t otInstanceGetId(otInstance *aInstance) @@ -32,9 +37,9 @@ uint32_t otInstanceGetId(otInstance *aInstance) struct nrf_rpc_cbor_ctx ctx; uint32_t id; - NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 1 + sizeof(uintptr_t)); - nrf_rpc_encode_uint(&ctx, (uintptr_t)aInstance); + ARG_UNUSED(aInstance); + NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 0); nrf_rpc_cbor_cmd_no_err(&ot_group, OT_RPC_CMD_INSTANCE_GET_ID, &ctx, nrf_rpc_rsp_decode_u32, &id); @@ -46,9 +51,9 @@ bool otInstanceIsInitialized(otInstance *aInstance) struct nrf_rpc_cbor_ctx ctx; bool initialized; - NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 1 + sizeof(uintptr_t)); - nrf_rpc_encode_uint(&ctx, (uintptr_t)aInstance); + ARG_UNUSED(aInstance); + NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 0); nrf_rpc_cbor_cmd_no_err(&ot_group, OT_RPC_CMD_INSTANCE_IS_INITIALIZED, &ctx, nrf_rpc_rsp_decode_bool, &initialized); @@ -59,9 +64,9 @@ void otInstanceFinalize(otInstance *aInstance) { struct nrf_rpc_cbor_ctx ctx; - NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 1 + sizeof(uintptr_t)); - nrf_rpc_encode_uint(&ctx, (uintptr_t)aInstance); + ARG_UNUSED(aInstance); + NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 0); nrf_rpc_cbor_cmd_no_err(&ot_group, OT_RPC_CMD_INSTANCE_FINALIZE, &ctx, nrf_rpc_rsp_decode_void, NULL); } @@ -71,9 +76,9 @@ otError otInstanceErasePersistentInfo(otInstance *aInstance) struct nrf_rpc_cbor_ctx ctx; otError error; - NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 1 + sizeof(uintptr_t)); - nrf_rpc_encode_uint(&ctx, (uintptr_t)aInstance); + ARG_UNUSED(aInstance); + NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 0); nrf_rpc_cbor_cmd_no_err(&ot_group, OT_RPC_CMD_INSTANCE_ERASE_PERSISTENT_INFO, &ctx, ot_rpc_decode_error, &error); diff --git a/subsys/net/openthread/rpc/server/ot_rpc_instance.c b/subsys/net/openthread/rpc/server/ot_rpc_instance.c index eb963228d606..aa6c45a5869a 100644 --- a/subsys/net/openthread/rpc/server/ot_rpc_instance.c +++ b/subsys/net/openthread/rpc/server/ot_rpc_instance.c @@ -72,15 +72,13 @@ static ot_rpc_callback_t *ot_rpc_callback_del(uint32_t callback, uint32_t contex static void ot_rpc_cmd_instance_init_single(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx, void *handler_data) { - otInstance *instance; - nrf_rpc_cbor_decoding_done(group, ctx); ot_rpc_mutex_lock(); - instance = otInstanceInitSingle(); + (void)otInstanceInitSingle(); ot_rpc_mutex_unlock(); - nrf_rpc_rsp_send_uint(group, (uintptr_t)instance); + nrf_rpc_rsp_send_void(group); } NRF_RPC_CBOR_CMD_DECODER(ot_group, ot_rpc_cmd_instance_init_single, OT_RPC_CMD_INSTANCE_INIT_SINGLE, @@ -89,24 +87,12 @@ NRF_RPC_CBOR_CMD_DECODER(ot_group, ot_rpc_cmd_instance_init_single, OT_RPC_CMD_I static void ot_rpc_cmd_instance_get_id(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx, void *handler_data) { - otInstance *instance; uint32_t instance_id; - instance = (otInstance *)nrf_rpc_decode_uint(ctx); - - if (!nrf_rpc_decoding_done_and_check(group, ctx)) { - ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_INSTANCE_GET_ID); - return; - } - - if (instance != openthread_get_default_instance()) { - /* The instance is unknown to the OT RPC server. */ - ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_INSTANCE_GET_ID); - return; - } + nrf_rpc_cbor_decoding_done(group, ctx); ot_rpc_mutex_lock(); - instance_id = otInstanceGetId(instance); + instance_id = otInstanceGetId(openthread_get_default_instance()); ot_rpc_mutex_unlock(); nrf_rpc_rsp_send_uint(group, instance_id); @@ -118,24 +104,12 @@ NRF_RPC_CBOR_CMD_DECODER(ot_group, ot_rpc_cmd_instance_get_id, OT_RPC_CMD_INSTAN static void ot_rpc_cmd_instance_is_initialized(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx, void *handler_data) { - otInstance *instance; bool initialized; - instance = (otInstance *)nrf_rpc_decode_uint(ctx); - - if (!nrf_rpc_decoding_done_and_check(group, ctx)) { - ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_INSTANCE_GET_ID); - return; - } - - if (instance != openthread_get_default_instance()) { - /* The instance is unknown to the OT RPC server. */ - ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_INSTANCE_GET_ID); - return; - } + nrf_rpc_cbor_decoding_done(group, ctx); ot_rpc_mutex_lock(); - initialized = otInstanceIsInitialized(instance); + initialized = otInstanceIsInitialized(openthread_get_default_instance()); ot_rpc_mutex_unlock(); nrf_rpc_rsp_send_bool(group, initialized); @@ -148,23 +122,10 @@ NRF_RPC_CBOR_CMD_DECODER(ot_group, ot_rpc_cmd_instance_is_initialized, static void ot_rpc_cmd_instance_finalize(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx, void *handler_data) { - otInstance *instance; - - instance = (otInstance *)nrf_rpc_decode_uint(ctx); - - if (!nrf_rpc_decoding_done_and_check(group, ctx)) { - ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_INSTANCE_GET_ID); - return; - } - - if (instance != openthread_get_default_instance()) { - /* The instance is unknown to the OT RPC server. */ - ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_INSTANCE_GET_ID); - return; - } + nrf_rpc_cbor_decoding_done(group, ctx); ot_rpc_mutex_lock(); - otInstanceFinalize(instance); + otInstanceFinalize(openthread_get_default_instance()); ot_rpc_mutex_unlock(); nrf_rpc_rsp_send_void(group); @@ -177,24 +138,12 @@ static void ot_rpc_cmd_instance_erase_persistent_info(const struct nrf_rpc_group struct nrf_rpc_cbor_ctx *ctx, void *handler_data) { - otInstance *instance; otError error; - instance = (otInstance *)nrf_rpc_decode_uint(ctx); - - if (!nrf_rpc_decoding_done_and_check(group, ctx)) { - ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_INSTANCE_GET_ID); - return; - } - - if (instance != openthread_get_default_instance()) { - /* The instance is unknown to the OT RPC server. */ - ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_INSTANCE_GET_ID); - return; - } + nrf_rpc_cbor_decoding_done(group, ctx); ot_rpc_mutex_lock(); - error = otInstanceErasePersistentInfo(instance); + error = otInstanceErasePersistentInfo(openthread_get_default_instance()); ot_rpc_mutex_unlock(); nrf_rpc_rsp_send_uint(group, error); diff --git a/tests/subsys/net/openthread/rpc/client/src/instance_suite.c b/tests/subsys/net/openthread/rpc/client/src/instance_suite.c index 941ce1c165e4..cddd1429ba7f 100644 --- a/tests/subsys/net/openthread/rpc/client/src/instance_suite.c +++ b/tests/subsys/net/openthread/rpc/client/src/instance_suite.c @@ -13,9 +13,6 @@ #include -/* Instance address used when testing serialization of a function that takes otInstance* */ -#define INSTANCE_ADDR UINT32_MAX - static void nrf_rpc_err_handler(const struct nrf_rpc_err_report *report) { zassert_ok(report->code); @@ -28,40 +25,34 @@ static void tc_setup(void *f) mock_nrf_rpc_tr_expect_reset(); } -/* Test serialization of otInstanceInitSingle() returning 0 */ +/* Test serialization of otInstanceInitSingle() */ ZTEST(ot_rpc_instance, test_otInstanceInitSingle_0) { otInstance *instance; + otInstance *instance2; - mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_INIT_SINGLE), RPC_RSP(0)); + /* Verify a non-null instance is returned from the function. */ + mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_INIT_SINGLE), RPC_RSP()); instance = otInstanceInitSingle(); mock_nrf_rpc_tr_expect_done(); - zassert_equal(instance, NULL); -} - -/* Test serialization of otInstanceInitSingle() returning max allowed 0xffffffff */ -ZTEST(ot_rpc_instance, test_otInstanceInitSingle_max) -{ - otInstance *instance; + zassert_not_null(instance, NULL); - mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_INIT_SINGLE), - RPC_RSP(CBOR_UINT32(UINT32_MAX))); - instance = otInstanceInitSingle(); + /* Verify that the same instance is returned for subsequent calls. */ + mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_INIT_SINGLE), RPC_RSP()); + instance2 = otInstanceInitSingle(); mock_nrf_rpc_tr_expect_done(); - zassert_equal(instance, (void *)UINT32_MAX); + zassert_equal(instance, instance2); } /* Test serialization of otInstanceGetId() returning 0 */ ZTEST(ot_rpc_instance, test_otInstanceGetId_0) { - otInstance *instance = (otInstance *)INSTANCE_ADDR; uint32_t id; - mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_GET_ID, CBOR_UINT32(INSTANCE_ADDR)), - RPC_RSP(0)); - id = otInstanceGetId(instance); + mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_GET_ID), RPC_RSP(0)); + id = otInstanceGetId(NULL); mock_nrf_rpc_tr_expect_done(); zassert_equal(id, 0); @@ -70,12 +61,11 @@ ZTEST(ot_rpc_instance, test_otInstanceGetId_0) /* Test serialization of otInstanceGetId() returning max allowed UINT32_MAX */ ZTEST(ot_rpc_instance, test_otInstanceGetId_max) { - otInstance *instance = (otInstance *)INSTANCE_ADDR; uint32_t id; - mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_GET_ID, CBOR_UINT32(INSTANCE_ADDR)), + mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_GET_ID), RPC_RSP(CBOR_UINT32(UINT32_MAX))); - id = otInstanceGetId(instance); + id = otInstanceGetId(NULL); mock_nrf_rpc_tr_expect_done(); zassert_equal(id, UINT32_MAX); @@ -84,13 +74,11 @@ ZTEST(ot_rpc_instance, test_otInstanceGetId_max) /* Test serialization of otInstanceIsInitialized() returning false */ ZTEST(ot_rpc_instance, test_otInstanceIsInitialized_false) { - otInstance *instance = (otInstance *)INSTANCE_ADDR; bool initialized; - mock_nrf_rpc_tr_expect_add( - RPC_CMD(OT_RPC_CMD_INSTANCE_IS_INITIALIZED, CBOR_UINT32(INSTANCE_ADDR)), - RPC_RSP(CBOR_FALSE)); - initialized = otInstanceIsInitialized(instance); + mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_IS_INITIALIZED), + RPC_RSP(CBOR_FALSE)); + initialized = otInstanceIsInitialized(NULL); mock_nrf_rpc_tr_expect_done(); zassert_false(initialized); @@ -99,13 +87,10 @@ ZTEST(ot_rpc_instance, test_otInstanceIsInitialized_false) /* Test serialization of otInstanceIsInitialized() returning true */ ZTEST(ot_rpc_instance, test_otInstanceIsInitialized_true) { - otInstance *instance = (otInstance *)INSTANCE_ADDR; bool initialized; - mock_nrf_rpc_tr_expect_add( - RPC_CMD(OT_RPC_CMD_INSTANCE_IS_INITIALIZED, CBOR_UINT32(INSTANCE_ADDR)), - RPC_RSP(CBOR_TRUE)); - initialized = otInstanceIsInitialized(instance); + mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_IS_INITIALIZED), RPC_RSP(CBOR_TRUE)); + initialized = otInstanceIsInitialized(NULL); mock_nrf_rpc_tr_expect_done(); zassert_true(initialized); @@ -114,24 +99,19 @@ ZTEST(ot_rpc_instance, test_otInstanceIsInitialized_true) /* Test serialization of otInstanceFinalize() */ ZTEST(ot_rpc_instance, test_otInstanceFinalize) { - otInstance *instance = (otInstance *)INSTANCE_ADDR; - - mock_nrf_rpc_tr_expect_add( - RPC_CMD(OT_RPC_CMD_INSTANCE_FINALIZE, CBOR_UINT32(INSTANCE_ADDR)), RPC_RSP()); - otInstanceFinalize(instance); + mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_FINALIZE), RPC_RSP()); + otInstanceFinalize(NULL); mock_nrf_rpc_tr_expect_done(); } /* Test serialization of otInstanceErasePersistentInfo() returning success */ ZTEST(ot_rpc_instance, test_otInstanceErasePersistentInfo_ok) { - otInstance *instance = (otInstance *)INSTANCE_ADDR; otError error; - mock_nrf_rpc_tr_expect_add( - RPC_CMD(OT_RPC_CMD_INSTANCE_ERASE_PERSISTENT_INFO, CBOR_UINT32(INSTANCE_ADDR)), - RPC_RSP(OT_ERROR_NONE)); - error = otInstanceErasePersistentInfo(instance); + mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_ERASE_PERSISTENT_INFO), + RPC_RSP(OT_ERROR_NONE)); + error = otInstanceErasePersistentInfo(NULL); mock_nrf_rpc_tr_expect_done(); zassert_equal(error, OT_ERROR_NONE); @@ -140,13 +120,11 @@ ZTEST(ot_rpc_instance, test_otInstanceErasePersistentInfo_ok) /* Test serialization of otInstanceErasePersistentInfo() returning error */ ZTEST(ot_rpc_instance, test_otInstanceErasePersistentInfo_error) { - otInstance *instance = (otInstance *)INSTANCE_ADDR; otError error; - mock_nrf_rpc_tr_expect_add( - RPC_CMD(OT_RPC_CMD_INSTANCE_ERASE_PERSISTENT_INFO, CBOR_UINT32(INSTANCE_ADDR)), - RPC_RSP(OT_ERROR_INVALID_STATE)); - error = otInstanceErasePersistentInfo(instance); + mock_nrf_rpc_tr_expect_add(RPC_CMD(OT_RPC_CMD_INSTANCE_ERASE_PERSISTENT_INFO), + RPC_RSP(OT_ERROR_INVALID_STATE)); + error = otInstanceErasePersistentInfo(NULL); mock_nrf_rpc_tr_expect_done(); zassert_equal(error, OT_ERROR_INVALID_STATE); diff --git a/tests/subsys/net/openthread/rpc/server/src/instance_suite.c b/tests/subsys/net/openthread/rpc/server/src/instance_suite.c index 61b1b6c31866..cff8484a626c 100644 --- a/tests/subsys/net/openthread/rpc/server/src/instance_suite.c +++ b/tests/subsys/net/openthread/rpc/server/src/instance_suite.c @@ -54,28 +54,10 @@ static void tc_setup(void *f) /* * Test reception of otInstanceInitSingle() command. - * Test serialization of the result: NULL. */ -ZTEST(ot_rpc_instance, test_otInstanceInitSingle_0) +ZTEST(ot_rpc_instance, test_otInstanceInitSingle) { - otInstanceInitSingle_fake.return_val = NULL; - - mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); - mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_INIT_SINGLE)); - mock_nrf_rpc_tr_expect_done(); - - zassert_equal(otInstanceInitSingle_fake.call_count, 1); -} - -/* - * Test reception of otInstanceInitSingle() command. - * Test serialization of the result: 0xffffffff. - */ -ZTEST(ot_rpc_instance, test_otInstanceInitSingle_max) -{ - otInstanceInitSingle_fake.return_val = (otInstance *)UINT32_MAX; - - mock_nrf_rpc_tr_expect_add(RPC_RSP(CBOR_UINT32(UINT32_MAX)), NO_RSP); + mock_nrf_rpc_tr_expect_add(RPC_RSP(), NO_RSP); mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_INIT_SINGLE)); mock_nrf_rpc_tr_expect_done(); @@ -88,16 +70,14 @@ ZTEST(ot_rpc_instance, test_otInstanceInitSingle_max) */ ZTEST(ot_rpc_instance, test_otInstanceGetId_0) { - uintptr_t instance = (uintptr_t)openthread_get_default_instance(); - otInstanceGetId_fake.return_val = 0; mock_nrf_rpc_tr_expect_add(RPC_RSP(0), NO_RSP); - mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_GET_ID, CBOR_UINT32(instance))); + mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_GET_ID)); mock_nrf_rpc_tr_expect_done(); zassert_equal(otInstanceGetId_fake.call_count, 1); - zassert_equal(otInstanceGetId_fake.arg0_val, (otInstance *)instance); + zassert_equal(otInstanceGetId_fake.arg0_val, openthread_get_default_instance()); } /* @@ -106,16 +86,14 @@ ZTEST(ot_rpc_instance, test_otInstanceGetId_0) */ ZTEST(ot_rpc_instance, test_otInstanceGetId_max) { - uintptr_t instance = (uintptr_t)openthread_get_default_instance(); - - otInstanceGetId_fake.return_val = 0xffffffff; + otInstanceGetId_fake.return_val = UINT32_MAX; mock_nrf_rpc_tr_expect_add(RPC_RSP(CBOR_UINT32(UINT32_MAX)), NO_RSP); - mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_GET_ID, CBOR_UINT32(instance))); + mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_GET_ID)); mock_nrf_rpc_tr_expect_done(); zassert_equal(otInstanceGetId_fake.call_count, 1); - zassert_equal(otInstanceGetId_fake.arg0_val, (otInstance *)instance); + zassert_equal(otInstanceGetId_fake.arg0_val, openthread_get_default_instance()); } /* @@ -124,16 +102,14 @@ ZTEST(ot_rpc_instance, test_otInstanceGetId_max) */ ZTEST(ot_rpc_instance, test_otInstanceIsInitialized_false) { - uintptr_t instance = (uintptr_t)openthread_get_default_instance(); - otInstanceIsInitialized_fake.return_val = false; mock_nrf_rpc_tr_expect_add(RPC_RSP(CBOR_FALSE), NO_RSP); - mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_IS_INITIALIZED, CBOR_UINT32(instance))); + mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_IS_INITIALIZED)); mock_nrf_rpc_tr_expect_done(); zassert_equal(otInstanceIsInitialized_fake.call_count, 1); - zassert_equal(otInstanceIsInitialized_fake.arg0_val, (otInstance *)instance); + zassert_equal(otInstanceIsInitialized_fake.arg0_val, openthread_get_default_instance()); } /* @@ -142,16 +118,14 @@ ZTEST(ot_rpc_instance, test_otInstanceIsInitialized_false) */ ZTEST(ot_rpc_instance, test_otInstanceIsInitialized_true) { - uintptr_t instance = (uintptr_t)openthread_get_default_instance(); - otInstanceIsInitialized_fake.return_val = true; mock_nrf_rpc_tr_expect_add(RPC_RSP(CBOR_TRUE), NO_RSP); - mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_IS_INITIALIZED, CBOR_UINT32(instance))); + mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_IS_INITIALIZED)); mock_nrf_rpc_tr_expect_done(); zassert_equal(otInstanceIsInitialized_fake.call_count, 1); - zassert_equal(otInstanceIsInitialized_fake.arg0_val, (otInstance *)instance); + zassert_equal(otInstanceIsInitialized_fake.arg0_val, openthread_get_default_instance()); } /* @@ -159,13 +133,12 @@ ZTEST(ot_rpc_instance, test_otInstanceIsInitialized_true) */ ZTEST(ot_rpc_instance, test_otInstanceFinalize) { - uintptr_t instance = (uintptr_t)openthread_get_default_instance(); - mock_nrf_rpc_tr_expect_add(RPC_RSP(), NO_RSP); - mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_FINALIZE, CBOR_UINT32(instance))); + mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_FINALIZE)); mock_nrf_rpc_tr_expect_done(); zassert_equal(otInstanceFinalize_fake.call_count, 1); + zassert_equal(otInstanceFinalize_fake.arg0_val, openthread_get_default_instance()); } /* @@ -174,17 +147,15 @@ ZTEST(ot_rpc_instance, test_otInstanceFinalize) */ ZTEST(ot_rpc_instance, test_otInstanceErasePersistentInfo_ok) { - uintptr_t instance = (uintptr_t)openthread_get_default_instance(); - otInstanceErasePersistentInfo_fake.return_val = OT_ERROR_NONE; mock_nrf_rpc_tr_expect_add(RPC_RSP(OT_ERROR_NONE), NO_RSP); - mock_nrf_rpc_tr_receive( - RPC_CMD(OT_RPC_CMD_INSTANCE_ERASE_PERSISTENT_INFO, CBOR_UINT32(instance))); + mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_ERASE_PERSISTENT_INFO)); mock_nrf_rpc_tr_expect_done(); zassert_equal(otInstanceErasePersistentInfo_fake.call_count, 1); - zassert_equal(otInstanceErasePersistentInfo_fake.arg0_val, (otInstance *)instance); + zassert_equal(otInstanceErasePersistentInfo_fake.arg0_val, + openthread_get_default_instance()); } /* @@ -193,17 +164,15 @@ ZTEST(ot_rpc_instance, test_otInstanceErasePersistentInfo_ok) */ ZTEST(ot_rpc_instance, test_otInstanceErasePersistentInfo_error) { - uintptr_t instance = (uintptr_t)openthread_get_default_instance(); - otInstanceErasePersistentInfo_fake.return_val = OT_ERROR_INVALID_STATE; mock_nrf_rpc_tr_expect_add(RPC_RSP(OT_ERROR_INVALID_STATE), NO_RSP); - mock_nrf_rpc_tr_receive( - RPC_CMD(OT_RPC_CMD_INSTANCE_ERASE_PERSISTENT_INFO, CBOR_UINT32(instance))); + mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_ERASE_PERSISTENT_INFO)); mock_nrf_rpc_tr_expect_done(); zassert_equal(otInstanceErasePersistentInfo_fake.call_count, 1); - zassert_equal(otInstanceErasePersistentInfo_fake.arg0_val, (otInstance *)instance); + zassert_equal(otInstanceErasePersistentInfo_fake.arg0_val, + openthread_get_default_instance()); } /* @@ -211,14 +180,12 @@ ZTEST(ot_rpc_instance, test_otInstanceErasePersistentInfo_error) */ ZTEST(ot_rpc_instance, test_otInstanceFactoryReset) { - uintptr_t instance = (uintptr_t)openthread_get_default_instance(); - mock_nrf_rpc_tr_expect_add(RPC_RSP(), NO_RSP); mock_nrf_rpc_tr_receive(RPC_CMD(OT_RPC_CMD_INSTANCE_FACTORY_RESET)); mock_nrf_rpc_tr_expect_done(); zassert_equal(otInstanceFactoryReset_fake.call_count, 1); - zassert_equal(otInstanceFactoryReset_fake.arg0_val, (otInstance *)instance); + zassert_equal(otInstanceFactoryReset_fake.arg0_val, openthread_get_default_instance()); } /* From 0d181b5cc5260585982fa9240d376bd73d4b6b6d Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Fri, 28 Nov 2025 13:44:19 +0100 Subject: [PATCH 021/155] mpsl: hwres: dppi: Adapt ppib_get_domain for bsim We need to update the changes done in 00bd43cf86f94389bbcaebfe70e563eb503b9532 to support compiling the code for bsim. A switch case statement cannot be used because it requires compile time constants in each label. When compiling for babblesim this is not the case. Simply transforming it to a set of if statements also works. Signed-off-by: Rubin Gerritsen --- subsys/mpsl/hwres/mpsl_hwres.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/subsys/mpsl/hwres/mpsl_hwres.c b/subsys/mpsl/hwres/mpsl_hwres.c index d84bfef22b5c..a47b64a121d2 100644 --- a/subsys/mpsl/hwres/mpsl_hwres.c +++ b/subsys/mpsl/hwres/mpsl_hwres.c @@ -35,25 +35,20 @@ bool mpsl_hwres_dppi_channel_alloc(NRF_DPPIC_Type *p_dppic, uint8_t *p_dppi_ch) #include static uint32_t ppib_get_domain(NRF_PPIB_Type *p_ppib) { - switch ((uint32_t)p_ppib) { - case (uint32_t)NRF_PPIB00: - /* fall through */ - case (uint32_t)NRF_PPIB10: + if ((uint32_t)p_ppib == (uint32_t)NRF_PPIB00 || + (uint32_t)p_ppib == (uint32_t)NRF_PPIB10) { return NRFX_GPPI_NODE_PPIB00_10; - case (uint32_t)NRF_PPIB11: - /* fall through */ - case (uint32_t)NRF_PPIB21: + } else if ((uint32_t)p_ppib == (uint32_t)NRF_PPIB11 || + (uint32_t)p_ppib == (uint32_t)NRF_PPIB21) { return NRFX_GPPI_NODE_PPIB11_21; - case (uint32_t)NRF_PPIB01: - /* fall through */ - case (uint32_t)NRF_PPIB20: + } else if ((uint32_t)p_ppib == (uint32_t)NRF_PPIB01 || + (uint32_t)p_ppib == (uint32_t)NRF_PPIB20) { return NRFX_GPPI_NODE_PPIB01_20; - case (uint32_t)NRF_PPIB22: - /* fall through */ - case (uint32_t)NRF_PPIB30: + } else if ((uint32_t)p_ppib == (uint32_t)NRF_PPIB22 || + (uint32_t)p_ppib == (uint32_t)NRF_PPIB30) { return NRFX_GPPI_NODE_PPIB22_30; - default: - __ASSERT_NO_MSG("Unexpected PPIB"); + } else { + __ASSERT(false, "Unexpected PPIB"); return 0; } } From b119194be6a98917e9c42e2c003531444be579cb Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Thu, 6 Nov 2025 13:44:23 +0100 Subject: [PATCH 022/155] applications: nrf_desktop: doc: dfu_mcumgr: align with IronSide SE Updated the DFU MCUmgr application module that is part of the nRF Desktop application to align with the IronSide SE architecture for the nRF54H20 SoC. Ref: NCSDK-35488 Signed-off-by: Kamil Piszczek --- applications/nrf_desktop/doc/dfu_mcumgr.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/applications/nrf_desktop/doc/dfu_mcumgr.rst b/applications/nrf_desktop/doc/dfu_mcumgr.rst index 06f3b679687f..4efed6c4f4f1 100644 --- a/applications/nrf_desktop/doc/dfu_mcumgr.rst +++ b/applications/nrf_desktop/doc/dfu_mcumgr.rst @@ -70,7 +70,8 @@ You cannot use this module with the :ref:`caf_ble_smp`. In other words, you cannot simultaneously enable the :option:`CONFIG_DESKTOP_DFU_MCUMGR_ENABLE` option and the :kconfig:option:`CONFIG_CAF_BLE_SMP` Kconfig option. .. note:: - B0 bootloader is not integrated with MCUmgr. + Currently, this module supports only one bootloader backend, the MCUboot bootloader backend. + B0 bootloader is not integrated with MCUmgr. .. _nrf_desktop_dfu_mcumgr_mcuboot: From de4522af1280cc933c7760a2519592676cd47bd3 Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Thu, 6 Nov 2025 14:06:12 +0100 Subject: [PATCH 023/155] applications: nrf_desktop: doc: dfu: align with IronSide SE Updated the DFU application module that is part of the nRF Desktop application to align with the IronSide SE architecture for the nRF54H20 SoC. Ref: NCSDK-35488 Signed-off-by: Kamil Piszczek --- applications/nrf_desktop/doc/dfu.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/applications/nrf_desktop/doc/dfu.rst b/applications/nrf_desktop/doc/dfu.rst index 91c1ced28274..d5a608c3b000 100644 --- a/applications/nrf_desktop/doc/dfu.rst +++ b/applications/nrf_desktop/doc/dfu.rst @@ -27,7 +27,7 @@ Configuration You can use this module for the following devices: -* nRF52, nRF53, and nRF54L Series - To perform the firmware upgrade, you must enable the bootloader. +* nRF52, nRF53, and nRF54 Series - To perform the firmware upgrade, you must enable the bootloader. You can use the DFU module with either MCUboot or B0 bootloader. For more information on how to enable and configure a bootloader, see the :ref:`nrf_desktop_bootloader` section. @@ -61,6 +61,16 @@ The :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP` Kconfig option i If the option is enabled, the DFU module reports the ``MCUBOOT+XIP`` bootloader name instead of ``MCUBOOT`` to indicate that the bootloader working in the direct-xip mode is used. See the :ref:`nrf_desktop_bootloader` section for more information on the MCUboot bootloader configuration. +Partitioning methods +==================== + +The DFU module stores the update image received over the configuration channel to a dedicated memory partition. +Due to this responsibility, it uses one of the supported partitioning methods to get the information about this partition location. + +The DFU module is compatible with the memory layout defined using the Partition Manager (PM). +It is also compatible with the memory layout defined using the Devicetree Source (DTS) when you use it with the MCUboot bootloader. +For more details about the memory layout methods, see the :ref:`nrf_desktop_memory_layout` documentation. + Device identification information ================================= @@ -134,16 +144,6 @@ fwinfo * Version and length of the image. * Partition ID of the currently booted image, used to specify the image placement. - Additionally, for the nRF54H Series, the following applies: - - * The reported image size is set to zero. - * The booted image version is indicated by: - - * Root manifest sequence number that is encoded in the build number field. - * Manifest semantic version, if supported by the SDFW (requires v0.6.2 or higher). - The semantic version is encoded in the major, minor and patch fields. - If semantic versioning is not supported, these fields are set to zero. - .. _dfu_devinfo: devinfo From 9d26afe4dc48e0d72321485c4a5f4e85b25549ba Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Mon, 1 Dec 2025 07:19:24 +0100 Subject: [PATCH 024/155] applications: Fixed usage fault on Matter bridge application There was a missing nullptr check that lead to usage fault on Matter bridge application. Signed-off-by: Kamil Kasperczyk --- .../src/ble/data_providers/ble_lbs_data_provider.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/applications/matter_bridge/src/ble/data_providers/ble_lbs_data_provider.cpp b/applications/matter_bridge/src/ble/data_providers/ble_lbs_data_provider.cpp index e84dda578370..356dcf63cb42 100644 --- a/applications/matter_bridge/src/ble/data_providers/ble_lbs_data_provider.cpp +++ b/applications/matter_bridge/src/ble/data_providers/ble_lbs_data_provider.cpp @@ -69,8 +69,13 @@ void ProcessCommand(const Binding::TableEntry &aBinding, OperationalDeviceProxy uint8_t BleLBSDataProvider::GattNotifyCallback(bt_conn *conn, bt_gatt_subscribe_params *params, const void *data, uint16_t length) { - BleLBSDataProvider *provider = static_cast( - BLEConnectivityManager::Instance().FindBLEProvider(*bt_conn_get_dst(conn))); + BleLBSDataProvider *provider = nullptr; + const bt_addr_le_t *btAddr = bt_conn_get_dst(conn); + + VerifyOrExit(conn && btAddr, ); + + provider = static_cast( + BLEConnectivityManager::Instance().FindBLEProvider(*btAddr)); VerifyOrExit(data, ); VerifyOrExit(provider, ); From 5d8d8a0f389874ab4590b27745f0e96f64932b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Mon, 24 Nov 2025 14:42:05 +0100 Subject: [PATCH 025/155] tests: drivers: audio: pdm_loopback: Check PDM state after stop start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add test that detects issue described in DLT-3748. Check that PDM configuration is not lost by stopping and then starting PDM interface. Signed-off-by: Sebastian Głąb --- tests/drivers/audio/pdm_loopback/src/main.c | 27 ++- .../audio/pdm_prescaler/CMakeLists.txt | 12 + tests/drivers/audio/pdm_prescaler/Kconfig | 28 +++ .../boards/nrf54l15dk_nrf54l15_cpuapp.overlay | 39 ++++ .../nrf54l15dk_nrf54l15_cpuapp_ns.overlay | 39 ++++ .../nrf54lm20dk_nrf54lm20a_cpuapp.overlay | 43 ++++ .../audio/pdm_prescaler/nrf54l_aclk.overlay | 9 + tests/drivers/audio/pdm_prescaler/prj.conf | 14 ++ tests/drivers/audio/pdm_prescaler/src/main.c | 217 ++++++++++++++++++ .../drivers/audio/pdm_prescaler/testcase.yaml | 65 ++++++ 10 files changed, 487 insertions(+), 6 deletions(-) create mode 100644 tests/drivers/audio/pdm_prescaler/CMakeLists.txt create mode 100644 tests/drivers/audio/pdm_prescaler/Kconfig create mode 100644 tests/drivers/audio/pdm_prescaler/boards/nrf54l15dk_nrf54l15_cpuapp.overlay create mode 100644 tests/drivers/audio/pdm_prescaler/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay create mode 100644 tests/drivers/audio/pdm_prescaler/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay create mode 100644 tests/drivers/audio/pdm_prescaler/nrf54l_aclk.overlay create mode 100644 tests/drivers/audio/pdm_prescaler/prj.conf create mode 100644 tests/drivers/audio/pdm_prescaler/src/main.c create mode 100644 tests/drivers/audio/pdm_prescaler/testcase.yaml diff --git a/tests/drivers/audio/pdm_loopback/src/main.c b/tests/drivers/audio/pdm_loopback/src/main.c index 83d5b3aca154..d89ceb0189f0 100644 --- a/tests/drivers/audio/pdm_loopback/src/main.c +++ b/tests/drivers/audio/pdm_loopback/src/main.c @@ -249,10 +249,10 @@ ZTEST(pdm_loopback, test_pdm_clk_frequency) { int ret; uint8_t gpiote_channel; - nrfx_gpiote_t *gpiote_instance = - &GPIOTE_NRFX_INST_BY_NODE(NRF_DT_GPIOTE_NODE(DT_NODELABEL(pulse_counter), gpios)); + nrfx_gpiote_t gpiote_instance = + GPIOTE_NRFX_INST_BY_NODE(NRF_DT_GPIOTE_NODE(DT_NODELABEL(pulse_counter), gpios)); - ret = nrfx_gpiote_channel_alloc(gpiote_instance, &gpiote_channel); + ret = nrfx_gpiote_channel_alloc(&gpiote_instance, &gpiote_channel); zassert_true(ret == 0, "GPIOTE channel allocation failed, return code = %d", ret); nrfx_gpiote_trigger_config_t trigger_cfg = { @@ -267,10 +267,10 @@ ZTEST(pdm_loopback, test_pdm_clk_frequency) .p_trigger_config = &trigger_cfg, }; - ret = nrfx_gpiote_input_configure(gpiote_instance, CLOCK_INPUT_PIN, &gpiote_cfg); + ret = nrfx_gpiote_input_configure(&gpiote_instance, CLOCK_INPUT_PIN, &gpiote_cfg); zassert_true(ret == 0, "GPIOTE input configuration failed, return code = %d", ret); - nrfx_gpiote_trigger_enable(gpiote_instance, CLOCK_INPUT_PIN, false); + nrfx_gpiote_trigger_enable(&gpiote_instance, CLOCK_INPUT_PIN, false); nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG( NRFX_TIMER_BASE_FREQUENCY_GET(&timer_instance)); @@ -284,7 +284,7 @@ ZTEST(pdm_loopback, test_pdm_clk_frequency) nrfx_timer_enable(&timer_instance); nrfx_gppi_handle_t gppi_handle; - uint32_t eep = nrfx_gpiote_in_event_address_get(gpiote_instance, CLOCK_INPUT_PIN); + uint32_t eep = nrfx_gpiote_in_event_address_get(&gpiote_instance, CLOCK_INPUT_PIN); uint32_t tep = nrfx_timer_task_address_get(&timer_instance, NRF_TIMER_TASK_COUNT); ret = nrfx_gppi_conn_alloc(eep, tep, &gppi_handle); @@ -300,6 +300,21 @@ ZTEST(pdm_loopback, test_pdm_clk_frequency) PDM_EXPECTED_FREQ * SAMPLING_RATIO / 30, "Captured incorrect frequency Hz. Captured pulses = %lu, expected = %lu", pulses, PDM_EXPECTED_FREQ * SAMPLING_RATIO); + + /* Remove GPPI configuration. */ + nrfx_gppi_conn_disable(gppi_handle); + nrfx_gppi_conn_free(eep, tep, gppi_handle); + + /* Remove GPIOTE configuration. */ + ret = nrfx_gpiote_pin_uninit(&gpiote_instance, CLOCK_INPUT_PIN); + zexpect_true(ret == 0, "nrfx_gpiote_pin_uninit() ret %d", ret); + nrfx_gpiote_trigger_disable(&gpiote_instance, CLOCK_INPUT_PIN); + ret = nrfx_gpiote_channel_free(&gpiote_instance, gpiote_channel); + zexpect_true(ret == 0, "nrfx_gpiote_channel_free() ret %d", ret); + + /* Remove NRFX Timer configuration. */ + nrfx_timer_disable(&timer_instance); + nrfx_timer_uninit(&timer_instance); } ZTEST_SUITE(pdm_loopback, NULL, device_setup, setup, teardown, NULL); diff --git a/tests/drivers/audio/pdm_prescaler/CMakeLists.txt b/tests/drivers/audio/pdm_prescaler/CMakeLists.txt new file mode 100644 index 000000000000..c51317a84832 --- /dev/null +++ b/tests/drivers/audio/pdm_prescaler/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(pdm_prescaler) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/drivers/audio/pdm_prescaler/Kconfig b/tests/drivers/audio/pdm_prescaler/Kconfig new file mode 100644 index 000000000000..10927e523d40 --- /dev/null +++ b/tests/drivers/audio/pdm_prescaler/Kconfig @@ -0,0 +1,28 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +source "Kconfig.zephyr" + +config TEST_PDM_SAMPLING_RATE + int "PDM sample rate in Hz" + default 10000 + help + The test will use it to define frequency of PDM sampling and + calculate the size of the buffer. + +config TEST_PDM_EXPECTED_FREQUENCY + int "Expected PDM_CLK frequency in Hz" + default 1000000 + help + The test will use it to confirm that the captured PDM_CLK + frequency in correct. + +config TEST_PDM_SAMPLING_TIME + int "PDM sampling time for one block in ms" + default 100 + help + The test will use it to calculate the size of data block and + determine the period of capturing timer. diff --git a/tests/drivers/audio/pdm_prescaler/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/audio/pdm_prescaler/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 000000000000..135e6c64fc35 --- /dev/null +++ b/tests/drivers/audio/pdm_prescaler/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + gpio_test { + compatible = "gpio-leds"; + + pulse_counter: pulse_counter { + gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&pinctrl { + pdm20_default_alt: pdm20_default_alt { + group1 { + psels = , + ; + }; + }; +}; + +pdm_dev: &pdm20 { + status = "okay"; + pinctrl-0 = <&pdm20_default_alt>; + pinctrl-names = "default"; + clock-source = "PCLK32M"; +}; + +&gpio1 { + status = "okay"; +}; + +&timer00 { + status = "okay"; +}; diff --git a/tests/drivers/audio/pdm_prescaler/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay b/tests/drivers/audio/pdm_prescaler/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay new file mode 100644 index 000000000000..135e6c64fc35 --- /dev/null +++ b/tests/drivers/audio/pdm_prescaler/boards/nrf54l15dk_nrf54l15_cpuapp_ns.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + gpio_test { + compatible = "gpio-leds"; + + pulse_counter: pulse_counter { + gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&pinctrl { + pdm20_default_alt: pdm20_default_alt { + group1 { + psels = , + ; + }; + }; +}; + +pdm_dev: &pdm20 { + status = "okay"; + pinctrl-0 = <&pdm20_default_alt>; + pinctrl-names = "default"; + clock-source = "PCLK32M"; +}; + +&gpio1 { + status = "okay"; +}; + +&timer00 { + status = "okay"; +}; diff --git a/tests/drivers/audio/pdm_prescaler/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/audio/pdm_prescaler/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 000000000000..e1e069693cdd --- /dev/null +++ b/tests/drivers/audio/pdm_prescaler/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Test requires loopback between P1.23 and P1.24. + * For best performance, PDM_CLK shall be on 'Clock pin'. + */ + +/ { + gpio_test { + compatible = "gpio-leds"; + + pulse_counter: pulse_counter { + gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&pinctrl { + pdm20_default_alt: pdm20_default_alt { + group1 { + psels = , + ; + }; + }; +}; + +pdm_dev: &pdm20 { + status = "okay"; + pinctrl-0 = <&pdm20_default_alt>; + pinctrl-names = "default"; + clock-source = "PCLK32M"; +}; + +&gpio1 { + status = "okay"; +}; + +&timer00 { + status = "okay"; +}; diff --git a/tests/drivers/audio/pdm_prescaler/nrf54l_aclk.overlay b/tests/drivers/audio/pdm_prescaler/nrf54l_aclk.overlay new file mode 100644 index 000000000000..63bdf726bf7a --- /dev/null +++ b/tests/drivers/audio/pdm_prescaler/nrf54l_aclk.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&pdm_dev { + clock-source = "ACLK"; +}; diff --git a/tests/drivers/audio/pdm_prescaler/prj.conf b/tests/drivers/audio/pdm_prescaler/prj.conf new file mode 100644 index 000000000000..53b60711d65c --- /dev/null +++ b/tests/drivers/audio/pdm_prescaler/prj.conf @@ -0,0 +1,14 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_ZTEST=y +CONFIG_TEST_USERSPACE=y + +CONFIG_AUDIO=y +CONFIG_AUDIO_DMIC=y +CONFIG_GPIO=y +CONFIG_NRFX_GPPI=y +CONFIG_NRFX_TIMER=y diff --git a/tests/drivers/audio/pdm_prescaler/src/main.c b/tests/drivers/audio/pdm_prescaler/src/main.c new file mode 100644 index 000000000000..c02ebd87e839 --- /dev/null +++ b/tests/drivers/audio/pdm_prescaler/src/main.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PDM_SAMPLING_RATE CONFIG_TEST_PDM_SAMPLING_RATE +#define PDM_EXPECTED_FREQ CONFIG_TEST_PDM_EXPECTED_FREQUENCY +#define PDM_SAMPLING_TIME CONFIG_TEST_PDM_SAMPLING_TIME +#define PDM_READ_TIMEOUT 1000 + +#define SAMPLE_BIT_WIDTH 16 +#define BYTES_PER_SAMPLE sizeof(int16_t) + +#define BLOCK_SIZE(_sample_rate, _number_of_channels) \ + (BYTES_PER_SAMPLE * (_sample_rate * PDM_SAMPLING_TIME / 1000) * _number_of_channels) + +#define MAX_BLOCK_SIZE BLOCK_SIZE(PDM_SAMPLING_RATE, 1) +#define BLOCK_COUNT 4 +#define SAMPLING_RATIO PDM_SAMPLING_TIME / 1000 * BLOCK_COUNT / 2 + +K_MEM_SLAB_DEFINE_STATIC(mem_slab, MAX_BLOCK_SIZE, BLOCK_COUNT, 4); + +#define CLOCK_INPUT_PIN NRF_DT_GPIOS_TO_PSEL(DT_NODELABEL(pulse_counter), gpios) + +volatile NRF_PDM_Type *p_reg = (NRF_PDM_Type *)DT_REG_ADDR(DT_NODELABEL(pdm_dev)); + +static const struct device *const pdm_dev = DEVICE_DT_GET(DT_NODELABEL(pdm_dev)); +static struct pcm_stream_cfg stream_config; +static struct dmic_cfg pdm_cfg; + +#if defined(NRF_TIMER00) +static nrfx_timer_t timer_instance = NRFX_TIMER_INSTANCE(NRF_TIMER00); +#elif defined(NRF_TIMER130) +static nrfx_timer_t timer_instance = NRFX_TIMER_INSTANCE(NRF_TIMER130); +#else +#error "No timer instance found" +#endif + +static bool pdm_enabled; + +static void *device_setup(void) +{ + int ret; + + ret = device_is_ready(pdm_dev); + zassert_true(ret, "PDM device is not ready, return code = %d", ret); + + return NULL; +} + +static void setup(void *unused) +{ + ARG_UNUSED(unused); + + stream_config.pcm_width = SAMPLE_BIT_WIDTH; + stream_config.pcm_rate = PDM_SAMPLING_RATE; + stream_config.mem_slab = &mem_slab; + stream_config.block_size = BLOCK_SIZE(PDM_SAMPLING_RATE, 1); + + pdm_cfg.io.min_pdm_clk_freq = 1000000; + pdm_cfg.io.max_pdm_clk_freq = 2000000; + pdm_cfg.io.min_pdm_clk_dc = 40; + pdm_cfg.io.max_pdm_clk_dc = 60; + pdm_cfg.streams = &stream_config, + pdm_cfg.channel.req_num_streams = 1; + pdm_cfg.channel.req_num_chan = 1; + pdm_cfg.channel.req_chan_map_lo = dmic_build_channel_map(0, 0, PDM_CHAN_LEFT); +} + +static void teardown(void *unused) +{ + ARG_UNUSED(unused); + + int ret; + + ret = dmic_trigger(pdm_dev, DMIC_TRIGGER_STOP); + zassert_true(ret >= 0, "dmic_trigger() failed, ret = %d", ret); +} + +static void capture_callback(struct k_timer *timer) +{ + ARG_UNUSED(timer); + nrfx_timer_capture(&timer_instance, NRF_TIMER_CC_CHANNEL0); + pdm_enabled = false; +} + +K_TIMER_DEFINE(capture_timer, capture_callback, NULL); + +ZTEST(pdm_prescaler, test_prescaler_not_affected_by_stop_start) +{ + int ret; + uint32_t prescaler_1; /* Prescaler value after applying test configuration. */ + uint32_t prescaler_temp; + const uint32_t ITERATIONS = 5; + + uint8_t gpiote_channel; + nrfx_gpiote_t gpiote_instance = + GPIOTE_NRFX_INST_BY_NODE(NRF_DT_GPIOTE_NODE(DT_NODELABEL(pulse_counter), gpios)); + + void *buffer; + uint32_t size; + + ret = nrfx_gpiote_channel_alloc(&gpiote_instance, &gpiote_channel); + zassert_true(ret == 0, "GPIOTE channel allocation failed, return code = %d", ret); + + nrfx_gpiote_trigger_config_t trigger_cfg = { + .p_in_channel = &gpiote_channel, + .trigger = NRFX_GPIOTE_TRIGGER_LOTOHI, + }; + + nrf_gpio_pin_pull_t pull_cfg = NRFX_GPIOTE_DEFAULT_PULL_CONFIG; + + nrfx_gpiote_input_pin_config_t gpiote_cfg = { + .p_pull_config = &pull_cfg, + .p_trigger_config = &trigger_cfg, + }; + + ret = nrfx_gpiote_input_configure(&gpiote_instance, CLOCK_INPUT_PIN, &gpiote_cfg); + zassert_true(ret == 0, "GPIOTE input configuration failed, return code = %d", ret); + + nrfx_gpiote_trigger_enable(&gpiote_instance, CLOCK_INPUT_PIN, false); + + nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG( + NRFX_TIMER_BASE_FREQUENCY_GET(&timer_instance)); + timer_config.bit_width = NRF_TIMER_BIT_WIDTH_32; + timer_config.mode = NRF_TIMER_MODE_COUNTER; + + ret = nrfx_timer_init(&timer_instance, &timer_config, NULL); + zassert_true(ret == 0, "nrfx_timer_init() failed, ret = 0x%08X", ret); + + nrfx_timer_enable(&timer_instance); + + nrfx_gppi_handle_t gppi_handle; + uint32_t eep = nrfx_gpiote_in_event_address_get(&gpiote_instance, CLOCK_INPUT_PIN); + uint32_t tep = nrfx_timer_task_address_get(&timer_instance, NRF_TIMER_TASK_COUNT); + + ret = nrfx_gppi_conn_alloc(eep, tep, &gppi_handle); + zassert_equal(ret, 0, "GPPI channel allocation failed, return code = %d", ret); + nrfx_gppi_conn_enable(gppi_handle); + + ret = dmic_configure(pdm_dev, &pdm_cfg); + zassert_true(ret >= 0, "dmic_configure() failed, ret = %d", ret); + + prescaler_1 = p_reg->PRESCALER; + TC_PRINT("Prescaler after device configuration: %u\n", prescaler_1); + zassert_not_equal(prescaler_1, PDM_PRESCALER_ResetValue, + "Selected configuration sets identical PRESCALER to the default value"); + + for (int i = 1; i <= ITERATIONS; i++) { + TC_PRINT("Iteration %u\n", i); + + /* Clear clock cycles counter */ + nrfx_timer_clear(&timer_instance); + + /* When kerel timer expires: + * - NRFX timer counter value is stored; + * - pdm_enabled is set to false. + */ + pdm_enabled = true; + k_timer_start(&capture_timer, K_SECONDS(1), K_NO_WAIT); + + ret = dmic_trigger(pdm_dev, DMIC_TRIGGER_START); + zassert_true(ret >= 0, "PDM start trigger failed, return code = %d", ret); + + while (pdm_enabled) { + ret = dmic_read(pdm_dev, 0, &buffer, &size, PDM_READ_TIMEOUT); + zassert_true(ret >= 0, "PDM read failed, return code = %d", ret); + + k_mem_slab_free(&mem_slab, buffer); + } + + ret = dmic_trigger(pdm_dev, DMIC_TRIGGER_STOP); + zassert_true(ret >= 0, "PDM stop trigger failed, return code = %d", ret); + + /* Get number of PDM_CLK edges. */ + uint32_t pulses = nrfx_timer_capture_get(&timer_instance, NRF_TIMER_CC_CHANNEL0); + + /* Assert that captured frequency is within 3% margin of expected one. */ + TC_PRINT("NRFX Timer counted to %u\n", pulses); + zassert_within(pulses, PDM_EXPECTED_FREQ, PDM_EXPECTED_FREQ / 30, + "Captured incorrect frequency Hz. Captured pulses = %lu, expected = %lu", + pulses, PDM_EXPECTED_FREQ); + + /* Check PRESCALER value */ + prescaler_temp = p_reg->PRESCALER; + TC_PRINT("Prescaler after transmission: %u\n", prescaler_temp); + zassert_equal(prescaler_1, prescaler_temp, "PRESCALER has changed"); + } + + /* Remove GPPI configuration. */ + nrfx_gppi_conn_disable(gppi_handle); + nrfx_gppi_conn_free(eep, tep, gppi_handle); + + /* Remove GPIOTE configuration. */ + ret = nrfx_gpiote_pin_uninit(&gpiote_instance, CLOCK_INPUT_PIN); + zexpect_true(ret == 0, "nrfx_gpiote_pin_uninit() ret %d", ret); + nrfx_gpiote_trigger_disable(&gpiote_instance, CLOCK_INPUT_PIN); + ret = nrfx_gpiote_channel_free(&gpiote_instance, gpiote_channel); + zexpect_true(ret == 0, "nrfx_gpiote_channel_free() ret %d", ret); + + /* Remove NRFX Timer configuration. */ + nrfx_timer_disable(&timer_instance); + nrfx_timer_uninit(&timer_instance); +} + +ZTEST_SUITE(pdm_prescaler, NULL, device_setup, setup, teardown, NULL); diff --git a/tests/drivers/audio/pdm_prescaler/testcase.yaml b/tests/drivers/audio/pdm_prescaler/testcase.yaml new file mode 100644 index 000000000000..0768d5c454b0 --- /dev/null +++ b/tests/drivers/audio/pdm_prescaler/testcase.yaml @@ -0,0 +1,65 @@ +common: + tags: + - drivers + - ci_tests_drivers_audio + harness: ztest + harness_config: + fixture: gpio_loopback + timeout: 20 + platform_exclude: + - nrf54h20dk/nrf54h20/cpuapp + # On nrf54H20 there is no PRESCALER register + +tests: + drivers.audio.pdm_prescaler.nrf54l.1000khz: + platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf54lm20dk/nrf54lm20a/cpuapp + drivers.audio.pdm_prescaler.nrf54lm20.1000khz: + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp + extra_args: + - CONFIG_TEST_PDM_SAMPLING_RATE=20000 + drivers.audio.pdm_prescaler.nrf54l.1280khz: + platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf54lm20dk/nrf54lm20a/cpuapp + extra_args: + - CONFIG_TEST_PDM_SAMPLING_RATE=16000 + - CONFIG_TEST_PDM_EXPECTED_FREQUENCY=1280000 + drivers.audio.pdm_prescaler.nrf54l.1600khz: + platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuapp/ns + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf54lm20dk/nrf54lm20a/cpuapp + extra_args: + - CONFIG_TEST_PDM_SAMPLING_RATE=32000 + - CONFIG_TEST_PDM_EXPECTED_FREQUENCY=1600000 + drivers.audio.pdm_prescaler.nrf54lm20.aclk.1000khz: + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp + extra_args: + - CONFIG_TEST_PDM_SAMPLING_RATE=20000 + - EXTRA_DTC_OVERLAY_FILE="nrf54l_aclk.overlay" + drivers.audio.pdm_prescaler.nrf54lm20.aclk.1280khz: + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp + extra_args: + - CONFIG_TEST_PDM_SAMPLING_RATE=16000 + - CONFIG_TEST_PDM_EXPECTED_FREQUENCY=1280000 + - EXTRA_DTC_OVERLAY_FILE="nrf54l_aclk.overlay" + drivers.audio.pdm_prescaler.nrf54lm20.aclk.1600khz: + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp + extra_args: + - CONFIG_TEST_PDM_SAMPLING_RATE=32000 + - CONFIG_TEST_PDM_EXPECTED_FREQUENCY=1600000 + - EXTRA_DTC_OVERLAY_FILE="nrf54l_aclk.overlay" From 99d27611911cc0332a6486f000d4ce748de2a30c Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Mon, 1 Dec 2025 11:41:59 +0100 Subject: [PATCH 026/155] samples: bluetooth: central and periph uart: align to nrfx 4.0 for lv10/ns No longer needed - CONFIG_NRFX_UARTE0=n. Signed-off-by: Piotr Kosycarz --- .../boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf | 8 -------- .../boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf | 8 -------- 2 files changed, 16 deletions(-) delete mode 100644 samples/bluetooth/central_uart/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf delete mode 100644 samples/bluetooth/peripheral_uart/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf diff --git a/samples/bluetooth/central_uart/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf b/samples/bluetooth/central_uart/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf deleted file mode 100644 index f5ed71dc1549..000000000000 --- a/samples/bluetooth/central_uart/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (c) 2025 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Disable the unspupported UART0 driver -CONFIG_NRFX_UARTE0=n diff --git a/samples/bluetooth/peripheral_uart/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf b/samples/bluetooth/peripheral_uart/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf deleted file mode 100644 index f5ed71dc1549..000000000000 --- a/samples/bluetooth/peripheral_uart/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (c) 2025 Nordic Semiconductor -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Disable the unspupported UART0 driver -CONFIG_NRFX_UARTE0=n From 5a6cce794278e4470608ca9f045686d1dafa4eba Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Wed, 26 Nov 2025 12:42:36 +0000 Subject: [PATCH 027/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3542 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index c392c13ab861..f971e9b8447d 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: 56fbb4f3c7bba12fb34a5cd111b4ea9f7ad52162 + revision: 034b7c87aab805c9df50c12c40733bae12ee7765 import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From ce9f387ca1d2c93c538a7d16fc7de9dc674d6547 Mon Sep 17 00:00:00 2001 From: Jorgen Kvalvaag Date: Fri, 28 Nov 2025 10:02:24 +0100 Subject: [PATCH 028/155] samples: memfault: Align nrf91xx board files Fixes test failures caused by missing CONFIG_MEMFAULT_NCS_DEVICE_ID_IMEI after pr-25313 was merged. Signed-off-by: Jorgen Kvalvaag --- samples/debug/memfault/boards/nrf9160dk_nrf9160_ns.conf | 2 ++ samples/debug/memfault/boards/nrf9161dk_nrf9161_ns.conf | 2 ++ samples/debug/memfault/boards/thingy91_nrf9160_ns.conf | 3 +++ 3 files changed, 7 insertions(+) diff --git a/samples/debug/memfault/boards/nrf9160dk_nrf9160_ns.conf b/samples/debug/memfault/boards/nrf9160dk_nrf9160_ns.conf index 53c1b66a3b7f..ac87bc9938b7 100644 --- a/samples/debug/memfault/boards/nrf9160dk_nrf9160_ns.conf +++ b/samples/debug/memfault/boards/nrf9160dk_nrf9160_ns.conf @@ -13,6 +13,8 @@ CONFIG_MEMFAULT_NCS_LTE_METRICS=y CONFIG_MEMFAULT_NCS_POST_COREDUMP_ON_NETWORK_CONNECTED=y CONFIG_LTE_LC_EDRX_MODULE=y CONFIG_LTE_LC_PSM_MODULE=y + +CONFIG_HW_ID_LIBRARY_SOURCE_IMEI=y CONFIG_MODEM_INFO=y # Certificate management diff --git a/samples/debug/memfault/boards/nrf9161dk_nrf9161_ns.conf b/samples/debug/memfault/boards/nrf9161dk_nrf9161_ns.conf index 53c1b66a3b7f..ac87bc9938b7 100644 --- a/samples/debug/memfault/boards/nrf9161dk_nrf9161_ns.conf +++ b/samples/debug/memfault/boards/nrf9161dk_nrf9161_ns.conf @@ -13,6 +13,8 @@ CONFIG_MEMFAULT_NCS_LTE_METRICS=y CONFIG_MEMFAULT_NCS_POST_COREDUMP_ON_NETWORK_CONNECTED=y CONFIG_LTE_LC_EDRX_MODULE=y CONFIG_LTE_LC_PSM_MODULE=y + +CONFIG_HW_ID_LIBRARY_SOURCE_IMEI=y CONFIG_MODEM_INFO=y # Certificate management diff --git a/samples/debug/memfault/boards/thingy91_nrf9160_ns.conf b/samples/debug/memfault/boards/thingy91_nrf9160_ns.conf index 195b4b6e80c0..ac87bc9938b7 100644 --- a/samples/debug/memfault/boards/thingy91_nrf9160_ns.conf +++ b/samples/debug/memfault/boards/thingy91_nrf9160_ns.conf @@ -14,6 +14,9 @@ CONFIG_MEMFAULT_NCS_POST_COREDUMP_ON_NETWORK_CONNECTED=y CONFIG_LTE_LC_EDRX_MODULE=y CONFIG_LTE_LC_PSM_MODULE=y +CONFIG_HW_ID_LIBRARY_SOURCE_IMEI=y +CONFIG_MODEM_INFO=y + # Certificate management CONFIG_MEMFAULT_ROOT_CERT_STORAGE_NRF9160_MODEM=y CONFIG_MODEM_KEY_MGMT=y From ba4af30bb8cf7df2aea56e2dd1eab832b30cd249 Mon Sep 17 00:00:00 2001 From: Tommi Kangas Date: Mon, 1 Dec 2025 12:47:23 +0200 Subject: [PATCH 029/155] samples: cellular: gnss: Update GNSS factory almanacs Updated GNSS factory almanacs. Signed-off-by: Tommi Kangas --- .../cellular/gnss/src/factory_almanac_v2.h | 68 +++++++-------- .../cellular/gnss/src/factory_almanac_v3.h | 82 +++++++++---------- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/samples/cellular/gnss/src/factory_almanac_v2.h b/samples/cellular/gnss/src/factory_almanac_v2.h index 1397bb25f2cf..5336d2a88657 100644 --- a/samples/cellular/gnss/src/factory_almanac_v2.h +++ b/samples/cellular/gnss/src/factory_almanac_v2.h @@ -7,46 +7,46 @@ #ifndef FACTORY_ALMANAC_V2_H_ #define FACTORY_ALMANAC_V2_H_ -/* Factory almanac generated on 2025-11-03 08:45:44. +/* Factory almanac generated on 2025-12-01 09:46:07. * * Note, that the almanac gets more inaccurate with time and it should be updated periodically. */ #define FACTORY_ALMANAC_DATA_V2 \ - "f0ea02003157090000000031f407395709840a32fd00c50ca10064a6d6ff40ca" \ - "fbffc564720073010000315089395709230e30fd00b60ca1008900d0ff700edb" \ - "ff558ca9ffdbff020031d6333957096c207cfd003a0da100bfb2feff0e193200" \ - "8fc91300aa02feff31931d395709581146fd00a50da100545e2a008f2487ff1e" \ - "1b95ff1700010031402d395709b71772fd00d20ca1001c54fcff6caf3a0057e6" \ - "a8ff16ff000031bd1d395709681d4bfd000b0da100857fd4ffd256e3ff302650" \ - "00b0fdfeff3168a33957092e0542fd00da0ca1002485530061bdadff06922700" \ - "95fffeff318d59395709d1011cfd00a80ca100ef04a7ff694013004b7e9cff26" \ - "02ffff31f91c395709820d44fd006e0ca100ebc82700712a5300a3cfb2ff1c03" \ - "0100313c5839570923207dfd00ea0ca1009b98feff3621a2ff5536eeffb8fdfe" \ - "ff31ad12395709500e37fd00910da100a85ed5ff5013a2ff662d7800b8fd0400" \ - "31d0483957097a0b60fd008d0ca100150881ff6a0d3e0000f70c0088fd000031" \ - "7950395709101547fd00e70ca100f6da2e00ad0d2900fe7890ffd90200003192" \ - "333957099b0052fd00c60ca10030e27e00fd4c8fffb6c10500ea02010031ab88" \ - "3957090dff31fd00ab0ca1007a0822001f553c00ece272007401010031d77839" \ - "5709f50a5efd006b0ca100feba81ffe0da24008ab3c3ff9200020031c26b3957" \ - "09050c29fd00d80da1008c36abff3751d0ff313f98ff2f00fcff31be2e395709" \ - "99133dfd00ed0ca1005f5cd4ff42218bffb6ad4600e8fd030031cd583957097a" \ - "0b24fd000d0da1006e01adffe6cb7500b7bde4ffc202010031d01d395709d60b" \ - "5ffd00940ca100a8b5f6ffd50fa8ffc04952007c01000031cf013957097a0c63" \ - "fd00430da1009218ffff1472efff0946060048010400314b67395709940a5ffd" \ - "00cc0ca10098dd81ff7f7fd6ff85d6b1ffabff0100312e30395709e51c78fd00" \ - "340da1000350fdff56fa8dff3d761c005302010031bd90395709a7fa2afd00bc" \ - "0ca1004b2f4f006a552d00589d4f00fbfe0400317967395709d40358fd00e00d" \ - "a100d0437d00d14c2e0087a70a00e601ffff31565739570945f748fd00e20ca1" \ - "002a527a00e0581b009384e7ffdffeffff316070395709bb0723fd00d50ca100" \ - "8248a8ff1edc2200fca59fffddffffff318103395709520c4bfd003b0da1006b" \ - "6a5200466e16008c93210067fd0100310e1b395709b80d27fd00270ca1009ee1" \ - "abff9d8d7100379798ff3dfe020031143f3957098cfb34fd003d0ca100903953" \ - "00a80ca0ff6a3e23000f000300316559395709ac0746fd00700da100897c5400" \ - "87cf2400dcd6feff3fff0000313848395709870f48fd00f30ca100ea752800ee" \ - "33acff8a1fbaffeefe0400000000000000000000000000000000000000000000" \ + "f0ea0200315b0900000000313509395b09560a28fd00b50ca1002935c2ff870b" \ + "fcff68399bff7201000031578a395b09f70d2cfd009e0ca1003c90bbff5cd7db" \ + "ff43ebd1fff1ff020031b833395b09952078fd001d0da1008250eaffa5d23100" \ + "07bd3c009702feff310b1e395b09cb1158fd00a50da10007f615005ecb87ff41" \ + "89bcff1e00010031972c395b09d61769fd00ef0ca100d3ede7fff9813a00c010" \ + "d2ff14ff000031a11e395b09381d40fd002a0da1006016c0ff6ff9e3ff1d3678" \ + "009dfdfeff31eea3395b090d0540fd00b90ca100b3173f0030f0adff07625000" \ + "87fffeff31175b395b09c70131fd00cd0ca100039392ffbd9f1300a03bc5ff1f" \ + "02ffff31a01c395b09f90d53fd005c0ca100da5e13008fbc5300daa2dbff2303" \ + "0100313c59395b094a2079fd00eb0ca1005c36eaff34b6a2ff54931600abfdff" \ + "ff31c612395b09210e2efd00a60da10025efc0ff556da3ffc8009fffdafd0400" \ + "318d49395b09390b62fd00660ca10048a06c00c82c3e007c48360086fd000031" \ + "b350395b097a155cfd00ef0ca100f8731a008d0829005153b9ffd7020000312c" \ + "34395b09530058fd00c30ca100b9756a006e458fff54ed2e00f2020100314e88" \ + "395b0989ff47fd00cd0ca100f1970d00af923c00b4b49bff7d010100310a7a39" \ + "5b09b30a62fd00800ca100ca526d004f20250087e4ecffa700020031286b395b" \ + "09fd0b3afd00030ea10077c896ff1bfad0ff416fbfff0e00fdff31ba2e395b09" \ + "6a1332fd00db0ca1000fefbfff269b8bffb31f6f0001fe0300312a59395b0972" \ + "0b35fd002b0da100da9298ff4f2c7600b10f0d00c702010031311e395b09e30b" \ + "55fd00bb0ca1008849e2ffc01daaffb77579007c01000031d302395b09a50c5c" \ + "fd00640da100b3adeaff8214ebffe12733006901030031e265395b09540a66fd" \ + "00c00ca10077756d00b6ecd6ffc58bdaffb3ff010031bd30395b09081d74fd00" \ + "3f0da1003dece8ff0de78eff4428440060020100317391395b0998fa2dfd00af" \ + "0ca10050bc3a007fac2d009b5b78001dff040031b768395b098a0359fd00bd0d" \ + "a1009dd86800d8802e002c803200e101ffff319d58395b09f5f64afd00f50ca1" \ + "0050e16500dbe41b0093f30f00d2fefeff31ad71395b09b30736fd00e20ca100" \ + "e6d893ffddf822000082c8ffd1ffffff317d03395b09330c48fd00590da10053" \ + "003e0084301600714c4a006efd010031171b395b09b10d38fd001b0ca1002874" \ + "97ff1a0071005eddc2ff4cfe020031643f395b096efb30fd00150ca100acc73e" \ + "00032fa0ff0bc74c002d000300317259395b09870743fd00760da1006b104000" \ + "275a2500549e260043ff0100314349395b09fc0f58fd00190da100db0c1400e8" \ + "86acff7a89e2ff15ff0400000000000000000000000000000000000000000000" \ "0000000000" #define FACTORY_ALMANAC_CHECKSUM_V2 \ - "5d83e6da802ca18689ec1f2375813cdd8f757d9a13d12c2cce7b44355dc8cf65" + "998f2ae578d8edc0b1831b9043d4a376e9fce0ee99895e1b607d1e845bc8f1b6" #endif /* FACTORY_ALMANAC_V2_H_ */ diff --git a/samples/cellular/gnss/src/factory_almanac_v3.h b/samples/cellular/gnss/src/factory_almanac_v3.h index 73bea14bfed9..4a201e4f941e 100644 --- a/samples/cellular/gnss/src/factory_almanac_v3.h +++ b/samples/cellular/gnss/src/factory_almanac_v3.h @@ -7,55 +7,55 @@ #ifndef FACTORY_ALMANAC_V3_H_ #define FACTORY_ALMANAC_V3_H_ -/* Factory almanac generated on 2025-11-01 19:19:46. +/* Factory almanac generated on 2025-12-01 08:32:26. * * Note, that the almanac gets more inaccurate with time and it should be updated periodically. */ #define FACTORY_ALMANAC_DATA_V3 \ - "f0ea03003157090000000031e907245709890a3cfd00c90ca100d2add6ffe1db" \ - "fbff0224730073010000314489245709270e3afd00ba0ca1000208d0ff9b09db" \ - "ff7961aaffdaff020031d833245709672076fd00360da10085b9fefff91d3200" \ - "af991400ab02feff31951d24570953113cfd00a40da100ac652a00b72487ff25" \ - "f495ff1600010031492d245709b3176dfd00cd0ca100045bfcff4cb33a0091b3" \ - "a9ff16ff000031b41d2457096d1d56fd000e0da100af86d4ff1357e3ff65f950" \ - "00b0fdfeff3161a3245709340545fd00e60ca100818c5300b0baadff89662800" \ - "96fffeff318459245709cf0116fd00a00ca100b40ca7ffe73c130047519dff26" \ - "02ffff31f91c2457097c0d38fd006c0ca10053d02700ba2e5300ec98b3ff1c03" \ - "0100312e582457091e2078fd00e50ca100629ffeff381ba2ff580eefffb9fdfe" \ - "ff31a912245709550e41fd00940da1000a66d5ff8c00a2ff96187900b6fd0400" \ - "31c9482457097a0b57fd008b0ca100300f81ffe10c3e0011c60d0088fd000031" \ - "72502457090d153ffd00e80ca10047e22e007e0f29005b4991ffd9020000318c" \ - "332457099b004afd00c30ca10070e97e009e4d8fffad910600ea02010031ab88" \ - "24570906ff25fd00a60ca100181022003c543c0088b373007401010031c87824" \ - "5709f40a56fd00660ca1001ec281ffecd82400aa82c4ff9200020031c76b2457" \ - "09030c23fd00d00da100333eabffd14bd0ff5d1f99ff3000fcff31be2e245709" \ - "9d1348fd00f10ca100b063d4ffca188bff8e884700e7fd030031c55824570979" \ - "0b20fd00050da1001909adff46c975009d93e5ffc102010031c81d245709d40b" \ - "5efd00910ca100c0bcf6ff18f9a7ff4c2f53007c01000031c401245709750c5d" \ - "fd003d0da100a91fffff00dfefff5eae060046010400315b67245709940a57fd" \ - "00c80ca100b8e481ff4a7ad6ff86acb2ffabff0100312730245709e11c72fd00" \ - "2f0da100d556fdff0dee8dff50571d005202010031b590245709aefa2efd00c6" \ - "0ca100e2364f00c9522d00a4705000fafe0400316b67245709d40351fd00df0d" \ - "a100024b7d00874b2e00f5830b00e601ffff31465724570947f742fd00e00ca1" \ - "008a597a0045531b00d55be8ffdffeffff315970245709b9071efd00cd0ca100" \ - "3350a8ffe3d922006079a0ffddffffff318003245709590c4efd00440da100ad" \ - "715200928f1600a247220067fd0100310a1b245709b60d23fd00210ca1003ce9" \ - "abffa1917100fd5d99ff3cfe020031123f24570993fb37fd00480ca100174153" \ - "004209a0ffc20d24000e000300316459245709b3074afd007a0da100d8835400" \ - "36cb240085b2ffff3eff0000313848245709820f3dfd00f00ca1004b7d280078" \ - "30acff79f5baffecfe0400000000000000000000000000000000000000000000" \ - "000000000000000000000000000031128515570903c5f8fe010de7ca004bc191" \ - "ffee6dbfff2fb011000000000031e47b155709d8c926ff0172ecca00c5dcd8ff" \ - "fb28c0fffc3bc9fffdff0000314479155709aaa4c7fe10aceaca0049791d00ab" \ - "99c0ffaf4e82fffeff0000000000000000000000000000000000000000000000" \ + "f0ea0300315b0900000000313509395b09560a28fd00b50ca1002935c2ff870b" \ + "fcff68399bff7201000031578a395b09f70d2cfd009e0ca1003c90bbff5cd7db" \ + "ff43ebd1fff1ff020031b833395b09952078fd001d0da1008250eaffa5d23100" \ + "07bd3c009702feff310b1e395b09cb1158fd00a50da10007f615005ecb87ff41" \ + "89bcff1e00010031972c395b09d61769fd00ef0ca100d3ede7fff9813a00c010" \ + "d2ff14ff000031a11e395b09381d40fd002a0da1006016c0ff6ff9e3ff1d3678" \ + "009dfdfeff31eea3395b090d0540fd00b90ca100b3173f0030f0adff07625000" \ + "87fffeff31175b395b09c70131fd00cd0ca100039392ffbd9f1300a03bc5ff1f" \ + "02ffff31a01c395b09f90d53fd005c0ca100da5e13008fbc5300daa2dbff2303" \ + "0100313c59395b094a2079fd00eb0ca1005c36eaff34b6a2ff54931600abfdff" \ + "ff31c612395b09210e2efd00a60da10025efc0ff556da3ffc8009fffdafd0400" \ + "318d49395b09390b62fd00660ca10048a06c00c82c3e007c48360086fd000031" \ + "b350395b097a155cfd00ef0ca100f8731a008d0829005153b9ffd7020000312c" \ + "34395b09530058fd00c30ca100b9756a006e458fff54ed2e00f2020100314e88" \ + "395b0989ff47fd00cd0ca100f1970d00af923c00b4b49bff7d010100310a7a39" \ + "5b09b30a62fd00800ca100ca526d004f20250087e4ecffa700020031286b395b" \ + "09fd0b3afd00030ea10077c896ff1bfad0ff416fbfff0e00fdff31ba2e395b09" \ + "6a1332fd00db0ca1000fefbfff269b8bffb31f6f0001fe0300312a59395b0972" \ + "0b35fd002b0da100da9298ff4f2c7600b10f0d00c702010031311e395b09e30b" \ + "55fd00bb0ca1008849e2ffc01daaffb77579007c01000031d302395b09a50c5c" \ + "fd00640da100b3adeaff8214ebffe12733006901030031e265395b09540a66fd" \ + "00c00ca10077756d00b6ecd6ffc58bdaffb3ff010031bd30395b09081d74fd00" \ + "3f0da1003dece8ff0de78eff4428440060020100317391395b0998fa2dfd00af" \ + "0ca10050bc3a007fac2d009b5b78001dff040031b768395b098a0359fd00bd0d" \ + "a1009dd86800d8802e002c803200e101ffff319d58395b09f5f64afd00f50ca1" \ + "0050e16500dbe41b0093f30f00d2fefeff31ad71395b09b30736fd00e20ca100" \ + "e6d893ffddf822000082c8ffd1ffffff317d03395b09330c48fd00590da10053" \ + "003e0084301600714c4a006efd010031171b395b09b10d38fd001b0ca1002874" \ + "97ff1a0071005eddc2ff4cfe020031643f395b096efb30fd00150ca100acc73e" \ + "00032fa0ff0bc74c002d000300317259395b09870743fd00760da1006b104000" \ + "275a2500549e260043ff0100314349395b09fc0f58fd00190da100db0c1400e8" \ + "86acff7a89e2ff15ff0400000000000000000000000000000000000000000000" \ + "000000000000000000000000000031f97e4c5b0985c44dff01dee8ca00ffd87d" \ + "002699bfff1ffcc3ff0000000031267f4c5b0983c91bff0101eeca0044f0c4ff" \ + "5bd4c0ffe79e7800fcff000031557a4c5b09dba522ff10b1ecca00308909006e" \ + "dcc0ffe7b43200feff0000000000000000000000000000000000000000000000" \ "0000000000000000000000000000000000000000000000000000000000000000" \ - "000000000000000000318d01155709b200610001feebca0094577000850f0b00" \ - "757bdeff000000003199011557096f005200105bebca00aa87efff516993ff11" \ - "02bdff0000000000000000000000000000000000000000000000000000000000" \ + "000000000000000000312d014c5b09d7004b001f85ecca0085011f0095ae6500" \ + "876c72000000000031e7014c5b0965005d0010a3ebca006317baff3b28d0ff99" \ + "0053000000000000000000000000000000000000000000000000000000000000" \ "0000000000000000000000000000000000000000000000000000000000000000" \ "00000000000000000000000000000000000000000000000000000000000000" #define FACTORY_ALMANAC_CHECKSUM_V3 \ - "ef6f0c079c3fdf5eca2dd00b344290b1924d8de63a8a54cc4c68e1beda9cb9d3" + "b9681a93075a743f7634abe279bd8e2074013216e554ad9a1778b0b7544725c2" #endif /* FACTORY_ALMANAC_V3_H_ */ From a40960d927004c69c4eeadcea3f6e34603193e4b Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Wed, 26 Nov 2025 12:58:31 +0000 Subject: [PATCH 030/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3543 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index f971e9b8447d..562c258ffe3b 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: 034b7c87aab805c9df50c12c40733bae12ee7765 + revision: d3409c65bf0bf3c207fea1d456041939126a5911 import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From 7fb28674520eb9b0910074f293927c16fea113c7 Mon Sep 17 00:00:00 2001 From: UMA PRASEEDA Date: Wed, 12 Nov 2025 12:44:25 +0100 Subject: [PATCH 031/155] doc: Update the Zoomin tags file Update the Zoomin tags file with nRF54LV10A Signed-off-by: UMA PRASEEDA --- doc/_zoomin/ncs.tags.yml | 183 ++++++++++++++++++++------------------- 1 file changed, 93 insertions(+), 90 deletions(-) diff --git a/doc/_zoomin/ncs.tags.yml b/doc/_zoomin/ncs.tags.yml index c2d626e2bf3e..d8f5e8799e84 100644 --- a/doc/_zoomin/ncs.tags.yml +++ b/doc/_zoomin/ncs.tags.yml @@ -11,60 +11,60 @@ mapping_topics: - nrf/index.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", - "nrf54lm20a", "nrf5340", "thingy53", "nrf52840", "nrf52833", "nrf52832", - "nrf52820", "nrf52811", "nrf52810", "nrf52805", "nrf21540", "npm1100", - "npm1300", "npm2100", "npm6001"] + "nrf54lm20a", "nrf54lv10a", "nrf5340", "thingy53", "nrf52840", "nrf52833", + "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", "nrf21540", + "npm1100", "npm1300", "npm2100", "npm6001"] - nrf/gsg_guides.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", - "nrf54l05", "nrf54l10", "nrf54lm20a", "nrf5340", "thingy53", "nrf52840", - "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", - "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001", + "nrf54l05", "nrf54l10", "nrf54lm20a", "nrf54lv10a", "nrf5340", "thingy53", + "nrf52840", "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", + "nrf52805", "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001", "development-kits", "prototyping-platforms", "evaluation-kits", "pmic"] - nrf/installation.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", - "nrf54l05", "nrf54l10", "nrf54lm20a", "nrf5340", "thingy53", "nrf52840", - "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", - "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001"] + "nrf54l05", "nrf54l10", "nrf54lm20a", "nrf54lv10a", "nrf5340", + "thingy53", "nrf52840", "nrf52833", "nrf52832", "nrf52820", "nrf52811", + "nrf52810", "nrf52805", "nrf21540", "npm1100", "npm1300", "npm2100", + "npm6001"] - nrf/installation/*.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", - "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", "nrf5340", - "thingy53", "nrf52840", "nrf52833", "nrf52832", "nrf52820", + "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", "nrf54lv10a", + "nrf5340", "thingy53", "nrf52840", "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001"] - nrf/app_dev.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", - "nrf54l05", "nrf54l10", "nrf54lm20a", "nrf5340", "thingy53", "nrf52840", - "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", - "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001"] + "nrf54l05", "nrf54l10", "nrf54lm20a", "nrf54lv10a", "nrf5340", "thingy53", + "nrf52840", "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", + "nrf52805", "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001"] - nrf/app_dev/create_application.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", - "nrf54l10", "nrf54lm20a", "nrf5340", "thingy53", - "nrf52840", "nrf52833", "nrf52832", "nrf52820", - "nrf52811", "nrf52810", "nrf52805", "nrf21540", "npm1100", - "npm1300", "npm2100", "npm6001", "applications", - "nrf-connect-vsc"] - - nrf/app_dev/board_names.html: ["nrf91-series", "nrf70-series", "nrf54-series", - "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", - "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", - "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", - "nrf54l10", "nrf54lm20a", "nrf5340", "thingy53", "nrf52840", - "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", - "nrf52805", "nrf21540", "npm1100", "npm1300", "npm2100", - "npm6001"] + "nrf54l10", "nrf54lm20a", "nrf54lv10a", "nrf5340", + "thingy53", "nrf52840", "nrf52833", "nrf52832", + "nrf52820", "nrf52811", "nrf52810", "nrf52805", + "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001", + "applications", "nrf-connect-vsc"] + - nrf/app_dev/board_names.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", + "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", + "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", + "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", + "nrf54lv10a", "nrf5340", "thingy53", "nrf52840", "nrf52833", + "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", + "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001"] - nrf/app_dev/config_and_build/*.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", - "nrf54l10", "nrf54lm20a", "nrf5340", "thingy53", - "nrf52840", "nrf52833", "nrf52832", "nrf52820", - "nrf52811", "nrf52810", "nrf52805", "nrf21540", "npm1100", - "npm1300", "npm2100", "npm6001"] + "nrf54l10", "nrf54lm20a", "nrf54lv10a", "nrf5340", + "thingy53", "nrf52840", "nrf52833", "nrf52832", + "nrf52820", "nrf52811", "nrf52810", "nrf52805", + "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001"] - nrf/app_dev/config_and_build/config_and_build_system.html: ["applications", "samples", "kconfig"] - nrf/app_dev/config_and_build/cmake/index.html: ["applications", "samples", "kconfig", @@ -87,42 +87,43 @@ mapping_topics: "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nnrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", - "nrf5340", "thingy53", "nrf52840", "nrf52833", "nrf52832", - "nrf52820", "nrf52811", "nrf52810", "nrf52805", "nrf21540", - "npm1100", "npm1300", "npm2100", "npm6001", "applications", - "samples", "development-kits", "evaluation-kits", + "nrf54lv10a", "nrf5340", "thingy53", "nrf52840", "nrf52833", + "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", + "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001", + "applications", "samples", "development-kits", "evaluation-kits", "prototyping-platforms"] - nrf/app_dev/companion_components.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nnrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", - "nrf5340", "thingy53", "nrf52840", "nrf52833", - "nrf52832", "nrf52820", "nrf52811", "nrf52810", - "nrf52805", "nrf21540", "npm1100", "npm1300", "npm2100", - "npm6001", "applications", "samples", - "development-kits", "evaluation-kits", + "nrf54lv10a", "nrf5340", "thingy53", "nrf52840", + "nrf52833", "nrf52832", "nrf52820", "nrf52811", + "nrf52810", "nrf52805", "nrf21540", "npm1100", + "npm1300", "npm2100", "npm6001", "applications", + "samples", "development-kits", "evaluation-kits", "prototyping-platforms"] - nrf/app_dev/bootloaders_dfu/index.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", - "nrf5340", "thingy53", "nrf52840", "nrf52833", - "nrf52832", "nrf52820", "nrf52811", "nrf52810", - "nrf52805", "nrf21540", "npm1100", "npm1300", - "npm2100", "npm6001"] + "nrf54lv10a", "nrf5340", "thingy53", "nrf52840", + "nrf52833", "nrf52832", "nrf52820", "nrf52811", + "nrf52810", "nrf52805", "nrf21540", "npm1100", + "npm1300", "npm2100", "npm6001"] - nrf/app_dev/bootloaders_dfu/mcuboot_nsib/*.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", - "nrf54lm20a", "nrf5340", "thingy53", - "nrf52840", "nrf52833", "nrf52832", - "nrf52820", "nrf52811", "nrf52810", - "nrf52805", "nrf21540", "npm1100", "npm1300", - "npm2100", "npm6001", "applications"] + "nrf54lm20a", "nrf54lv10a", "nrf5340", + "thingy53", "nrf52840", "nrf52833", + "nrf52832", "nrf52820", "nrf52811", + "nrf52810", "nrf52805", "nrf21540", "npm1100", + "npm1300", "npm2100", "npm6001", + "applications"] - nrf/app_dev/bootloaders_dfu/mcuboot_nsib/bootloader_config.html: ["kconfig"] - nrf/app_dev/bootloaders_dfu/qspi_xip_split_image.html: ["nrf52840", "thingy53", "nrf5340"] - nrf/app_dev/bootloaders_dfu/dfu_tools_mcumgr_cli.html: ["nrf91-series", "nrf70-series", @@ -132,11 +133,11 @@ mapping_topics: "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", - "nrf5340", "thingy53", "nrf52840", - "nrf52833", "nrf52832", "nrf52820", - "nrf52811", "nrf52810", "nrf52805", - "nrf21540", "npm1100", "npm1300", - "npm2100", "npm6001"] + "nrf54lv10a", "nrf5340", "thingy53", + "nrf52840", "nrf52833", "nrf52832", + "nrf52820", "nrf52811", "nrf52810", + "nrf52805", "nrf21540", "npm1100", + "npm1300", "npm2100", "npm6001"] - nrf/app_dev/bootloaders_dfu/mcuboot_image_compression.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", @@ -144,12 +145,12 @@ mapping_topics: "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", - "nrf54lm20a", "nrf5340", - "thingy53", "nrf52840", "nrf52833", - "nrf52832", "nrf52820", "nrf52811", - "nrf52810", "nrf52805", "nrf21540", - "npm1100", "npm1300", "npm2100", - "npm6001"] + "nrf54lm20a", "nrf54lv10a", + "nrf5340", "thingy53", "nrf52840", + "nrf52833", "nrf52832", "nrf52820", + "nrf52811", "nrf52810", "nrf52805", + "nrf21540", "npm1100", "npm1300", + "npm2100", "npm6001"] - nrf/app_dev/bootloaders_dfu/sysbuild_image_ids.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", @@ -157,11 +158,11 @@ mapping_topics: "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", - "nrf5340", "thingy53", "nrf52840", - "nrf52833", "nrf52832", "nrf52820", - "nrf52811", "nrf52810", "nrf52805", - "nrf21540", "npm1100", "npm1300", - "npm2100", "npm6001"] + "nrf54lv10a", "nrf5340", "thingy53", + "nrf52840", "nrf52833", "nrf52832", + "nrf52820", "nrf52811", "nrf52810", + "nrf52805", "nrf21540", "npm1100", + "npm1300", "npm2100", "npm6001"] - nrf/app_dev/device_guides/nrf91/index.html: ["nrf9160", "nrf9161", "thingy91", "thingy91x", "nrf9151", "nrf9131", "development-kits", "dect-nr+", "prototyping-platforms"] @@ -206,7 +207,7 @@ mapping_topics: - nrf/app_dev/device_guides/nrf70/nrf7002ek_dev_guide.html: ["evaluation-kits"] - nrf/app_dev/device_guides/nrf70/constrained.html: ["kconfig"] - nrf/app_dev/device_guides/nrf54l/*.html: ["nrf54-series", "nrf54l15", "nrf54l10", "nrf54lm20a", - "nrf54l05", "development-kits"] + "nrf54lv10a", "nrf54l05", "development-kits"] - nrf/app_dev/device_guides/nrf54h/*.html: ["nrf54-series", "nrf54h20", "development-kits"] - nrf/app_dev/device_guides/nrf53/index.html: ["nrf5340", "thingy53", "development-kits", "prototyping-platforms"] @@ -242,17 +243,17 @@ mapping_topics: "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", - "nrf5340", "thingy53", "nrf52840", "nrf52833", "nrf52832", - "nrf52820", "nrf52811", "nrf52810", "nrf52805", "nrf21540", - "npm1100", "npm1300", "npm2100", "npm6001", "applications", - "samples"] + "nrf54lv10a", "nrf5340", "thingy53", "nrf52840", "nrf52833", + "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", + "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001", + "applications", "samples"] - nrf/test_and_optimize/*.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", - "nrf5340", "thingy53", "nrf52840", "nrf52833", "nrf52832", - "nrf52820", "nrf52811", "nrf52810", "nrf52805", "nrf21540", - "npm1100", "npm1300", "npm2100", "npm6001"] + "nrf54lv10a", "nrf5340", "thingy53", "nrf52840", "nrf52833", + "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", + "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001"] - nrf/test_and_optimize/optimizing/*.html: ["applications", "protocols"] - nrf/test_and_optimize/optimizing/memory.html: ["kconfig", "ble", "blemesh", "gazell", "matter", "nfc", "thread", "zigbee", @@ -263,8 +264,8 @@ mapping_topics: "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf54l15", "nrf54l05", - "nrf54l10", "nrf54lm20a", "nrf5340", - "thingy53", "nrf52840", "nrf52833", + "nrf54l10", "nrf54lm20a", "nrf54lv10a", + "nrf5340", "thingy53", "nrf52840", "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", "nrf9160", "matter", "thread", "lte", "wifi"] @@ -272,12 +273,13 @@ mapping_topics: - nrf/security/*.html: ["kconfig"] - nrf/security/crypto/*.html: ["nrf91-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf9160", "nrf9161", "nrf9151", "nrf9131", - "nrf54h20", "nrf54l15", "nrf54l10", "nrf54lm20a", "nrf54l05", - "nrf5340", "nrf52840", "nrf52833", "nrf52832", "kconfig"] + "nrf54h20", "nrf54l15", "nrf54l10", "nrf54lm20a", "nrf54lv10a", + "nrf54l05", "nrf5340", "nrf52840", "nrf52833", "nrf52832", + "kconfig"] - nrf/security/tfm/*.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf9160", "nrf9161", "nrf9151", "nrf9131", "nrf7002", - "nrf54l15", "nrf54l10", "nrf54lm20a", "nrf5340", "thingy91", - "thingy91x", "thingy53", "kconfig"] + "nrf54l15", "nrf54l10", "nrf54lm20a", "nrf54lv10a", "nrf5340", + "thingy91", "thingy91x", "thingy53", "kconfig"] - nrf/security/ap_protect.html: ["nrf91-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf9160", "nrf9161", "nrf9151", "nrf9131", "nrf54h20", "nrf54l15", "nrf5340", "nrf52840", "nrf52833", @@ -285,8 +287,8 @@ mapping_topics: "kconfig"] - nrf/security/secure_storage.html: ["nrf91-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf9160", "nrf9161", "nrf9151", "nrf9131", - "nrf54l15", "nrf54l10", "nrf54lm20a", "nrf5340", "nrf52840", - "nrf52833", "nrf52832", "kconfig"] + "nrf54l15", "nrf54l10", "nrf54lm20a", "nrf54lv10a", + "nrf5340", "nrf52840", "nrf52833", "nrf52832", "kconfig"] - nrf/protocols/*.html: ["protocols"] - nrf/protocols.html: ["sidewalk", "ble", "blemesh", "esb", "gazell", "matter", "multiprotocol", "nfc", "thread", "zigbee", "wifi", "dect-nr+", "protocols"] @@ -328,10 +330,10 @@ mapping_topics: - nrf/applications.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf54h20", "nrf54l15", "nrf54l05", - "nrf54l10", "nrf54lm20a", "nrf5340", "thingy53", "nrf52840", "nrf52833", - "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", "nrf21540", - "npm1100", "npm1300", "npm2100", "npm6001", "kconfig", - "development-kits", "prototyping-platforms"] + "nrf54l10", "nrf54lm20a", "nrf54lv10a", "nrf5340", "thingy53", + "nrf52840", "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", + "nrf52805", "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001", + "kconfig", "development-kits", "prototyping-platforms"] - nrf/applications/*.html: ["applications", "kconfig"] - nrf/applications/connectivity_bridge/README.html: ["lte"] - nrf/applications/matter_bridge/*.html: ["matter", "wifi"] @@ -342,9 +344,9 @@ mapping_topics: - nrf/samples.html: ["nrf91-series", "nrf70-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf7002", "nrf7001", "nrf7000", "nrf9160", "thingy91", "thingy91x", "nrf9161", "nrf9151", "nrf54h20", "nrf54l15", "nrf54l05", - "nrf54l10", "nrf54lm20a", "nrf5340", "thingy53", "nrf52840", "nrf52833", - "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", "nrf21540", - "npm1100", "npm1300", "npm2100", "npm6001", "development-kits", + "nrf54l10", "nrf54lm20a", "nrf54lv10a", "nrf5340", "thingy53", "nrf52840", + "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", + "nrf21540", "npm1100", "npm1300", "npm2100", "npm6001", "development-kits", "prototyping-platforms", "kconfig"] - nrf/samples/*.html: ["samples", "kconfig"] - nrf/samples/amazon_sidewalk.html: ["sidewalk"] @@ -385,7 +387,7 @@ mapping_topics: - nrf/libraries/bluetooth/*.html: ["ble", "nrf52-series", "nrf52840", "nrf52833", "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", "nrf54-series", "nrf54h20", "nrf54l15", "nrf54l05", "nrf54l10", "nrf54lm20a", - "development-kits"] + "nrf54lv10a", "development-kits"] - nrf/libraries/bluetooth/mesh.html: ["blemesh"] - nrf/libraries/bluetooth/mesh/*.html: ["blemesh"] - nrf/libraries/gazell/*.html: ["gazell"] @@ -437,7 +439,8 @@ mapping_topics: - nrfxlib/nrf_modem/*.html: ["nrf91-series", "nrf9160", "nrf9161", "nrf9151", "lte", "dect-nr+"] - nrfxlib/nrf_modem/doc/at_interface.html: ["at-commands"] - nrfxlib/nrf_802154/README.html: ["nrf52-series", "nrf54-series", "nrf54l15", "nrf54l05", - "nrf54l10", "nrf54lm20a", "nrf52840", "nrf52833", "nrf5340"] + "nrf54l10", "nrf54lm20a", "nrf52840", "nrf52833", + "nrf5340"] - nrfxlib/nrf_802154/*.html: ["multiprotocol"] - nrfxlib/nrf_fuel_gauge/*.html: ["pmic", "npm1100", "npm1300", "npm2100", "npm6001", "evaluation-kits"] From b08560b4559b7b5cc75687dc7a420bce3aa8621c Mon Sep 17 00:00:00 2001 From: Alexander Svensen Date: Mon, 1 Dec 2025 09:01:56 +0100 Subject: [PATCH 032/155] applications: nrf5340_audio: Increase rx configs for bidirectional - Fixes bug where debug log for rx direction was not initialized - Even though max decode is set to 2, only one streams is actually decoded, same as before. - OCT-3456 Signed-off-by: Alexander Svensen --- .../nrf5340_audio/unicast_client/overlay-unicast_client.conf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/applications/nrf5340_audio/unicast_client/overlay-unicast_client.conf b/applications/nrf5340_audio/unicast_client/overlay-unicast_client.conf index f9087c70505f..e107cc11606f 100644 --- a/applications/nrf5340_audio/unicast_client/overlay-unicast_client.conf +++ b/applications/nrf5340_audio/unicast_client/overlay-unicast_client.conf @@ -32,7 +32,9 @@ CONFIG_UTF8=y CONFIG_BT_CONTENT_CTRL_MEDIA=y CONFIG_LC3_ENC_CHAN_MAX=2 -CONFIG_LC3_DEC_CHAN_MAX=1 +CONFIG_LC3_DEC_CHAN_MAX=2 CONFIG_AUDIO_ENCODE_CHANNELS_MAX=2 CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=2048 +CONFIG_BT_AUDIO_CONCURRENT_RX_STREAMS_MAX=2 +CONFIG_AUDIO_DECODE_CHANNELS_MAX=2 From 13d36dacd4c141030a1a13e9f0d97f3bb2d3ae76 Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Mon, 1 Dec 2025 10:58:28 +0100 Subject: [PATCH 033/155] applications: nrf_desktop: doc: update nRF54H20 DK board configuration Updated the nRF54H20 DK entry in board configuration documentation of the nRF Desktop application to align the description with the recent migration to the IronSide SE architecture. Ref: NCSDK-35488 Signed-off-by: Kamil Piszczek --- applications/nrf_desktop/board_configuration.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/applications/nrf_desktop/board_configuration.rst b/applications/nrf_desktop/board_configuration.rst index cf2d79ec2f81..33f97c84782b 100644 --- a/applications/nrf_desktop/board_configuration.rst +++ b/applications/nrf_desktop/board_configuration.rst @@ -196,11 +196,12 @@ Sample mouse or dongle (``nrf54h20dk/nrf54h20/cpuapp``) The :option:`CONFIG_DESKTOP_BLE_ADV_CTRL_ENABLE` and :option:`CONFIG_DESKTOP_BLE_ADV_CTRL_SUSPEND_ON_USB` Kconfig options are enabled in mouse configurations to improve the USB High-Speed report rate. * In ``debug`` configurations, logs are provided through the UART. For detailed information on working with the nRF54H20 DK, see the :ref:`ug_nrf54h20_gs` documentation. - * The configurations use the Software Updates for Internet of Things (SUIT) and support firmware updates using the :ref:`nrf_desktop_dfu`. + * The configurations use the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``) and support firmware updates using the :ref:`nrf_desktop_dfu`. Configurations acting as HID peripherals also support firmware updates using the :ref:`nrf_desktop_dfu_mcumgr`. + For more details on MCUboot, see :ref:`nrf_desktop_bootloader`. - .. note:: - The nRF Desktop application does not build or run for the ``nrf54h20dk/nrf54h20/cpuapp`` board target due to the IronSide SE migration. - See the ``NCSDK-34299`` in the :ref:`known_issues` page for more information. - The :ref:`nrf_desktop` documentation may still refer to concepts that were valid before the IronSide SE migration (for example, to the SUIT solution). - The codebase and documentation will be updated in the future releases to address this issue. + All configurations enable hardware cryptography for the MCUboot bootloader. + The MCUboot bootloader uses the :ref:`ug_crypto_architecture_implementation_standards_ironside` for hardware cryptography. + The application image is verified using a pure ED25519 signature. + In all configurations, the MCUboot bootloader uses a merged image slot that combines both application and radio core images. + For more details on nRF54H Series DFU, see :ref:`ug_nrf54h20_mcuboot_dfu`. From eef0a7e5ff56007f3ebffe7011b2714adcda2c84 Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Fri, 28 Nov 2025 07:36:59 +0100 Subject: [PATCH 034/155] applications: nrf_desktop: Update HID state documentation Change updates documentation of the HID state module to inform about selective HID report subscription handling. Jira: NCSDK-35718 Signed-off-by: Marek Pieta Signed-off-by: Divya Pillai Signed-off-by: Pekka Niskanen --- applications/nrf_desktop/doc/hid_state.rst | 46 +++++++++++++++------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/applications/nrf_desktop/doc/hid_state.rst b/applications/nrf_desktop/doc/hid_state.rst index 9579c5c41189..0f408156728c 100644 --- a/applications/nrf_desktop/doc/hid_state.rst +++ b/applications/nrf_desktop/doc/hid_state.rst @@ -12,8 +12,8 @@ It is responsible for the following operations: * Tracking the state of HID subscribers and HID input report subscriptions. The module can simultaneously handle HID input report subscriptions of multiple HID subscribers. - The module provides HID input reports only to one subscriber (*active subscriber*). -* Providing HID input reports to the active HID subscriber. + The module provides HID input reports only to subscribers with the highest priority (*active subscribers*). +* Providing HID input reports to the active HID subscribers. The module relies on HID report providers to aggregate the user input, form HID input reports, and submit a :c:struct:`hid_report_event`. The HID input reports can be formatted according to either HID report protocol or HID boot protocol. * Handling HID output reports. @@ -40,18 +40,37 @@ For details related to HID configuration in the nRF Desktop, see the :ref:`nrf_d Number of supported HID subscribers =================================== +A HID transport (for example, :ref:`nrf_desktop_hids` or :ref:`nrf_desktop_usb_state`) is a module that forwards HID reports to a HID host and forwards HID input report subscriptions of the HID host. +In most cases, a HID transport registers a single HID subscriber that handles all HID input reports. If your application configuration supports more than one HID subscriber, you must align the maximum number of HID subscribers that can be handled simultaneously (:option:`CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT`). -For example, to use a configuration that allows to simultaneously subscribe to HID reports from HID over GATT (Bluetooth LE) and a single USB HID instance, set the value of this Kconfig option to ``2``. +For example, to use a configuration that allows to simultaneously subscribe to HID input reports from HID over GATT (Bluetooth LE) and a single USB HID instance, set the value of this Kconfig option to ``2``. -If multiple HID subscribers are simultaneously connected, the |hid_state| selects the one with the highest priority as the active subscriber. -The |hid_state| provides HID input reports only to the active subscriber. -The |hid_state| displays the HID keyboard LED state associated with the active subscriber. +Selective HID input report subscription +--------------------------------------- -By default, the subscriber that is associated with USB has priority over a subscriber associated with Bluetooth LE. -As a result, if a HID host connects through the USB while another HID host is connected over the Bluetooth LE, the HID reports will be routed to the USB. +In some cases, a single HID transport can register multiple HID subscribers. +Every HID subscriber handles a subset of HID input reports. + +For example, an nRF Desktop peripheral might use the USB selective HID report subscription feature to split HID input reports among multiple HID-class USB instances (every HID-class USB instance handles a predefined subset of HID input report IDs). +For more details regarding the feature, see the :ref:`nrf_desktop_usb_state_hid_class_instance` documentation section of the USB state module. + +Using selective HID input report subscription requires increasing the value of the :option:`CONFIG_DESKTOP_HID_STATE_SUBSCRIBER_COUNT` Kconfig option. +For example, if a configuration allows simultaneously subscribing to HID input reports from HID over GATT (Bluetooth LE) and two USB HID instances, increase the value of the Kconfig option to ``3``. + +HID subscriber priority +----------------------- + +If multiple HID subscribers are simultaneously connected, the |hid_state| selects the ones with the highest priority as the active subscribers. +The |hid_state| provides HID input reports only to the active subscribers. +The |hid_state| displays the HID keyboard LED state associated with the active subscriber of the HID keyboard input report. +HID subscribers with the same priority cannot simultaneously subscribe to the same HID input report. + +If a HID transport uses a selective HID input report subscription, all subscribers registered by the transport must share the same priority. +Otherwise, subscribers with lower priority would not receive HID input reports from the HID state. .. note:: - The subscriber priority must be unique, which means that two or more subscribers cannot share the same priority value. + By default, a subscriber that is associated with USB has priority over a subscriber associated with Bluetooth LE. + If a HID host connects through the USB while another HID host is connected over the Bluetooth LE, the HID reports will be routed to the USB. HID keyboard LEDs ================= @@ -108,14 +127,13 @@ This section describes implementation details related to responsibilities of the Tracking state of HID subscribers ================================= -A HID transport (for example :ref:`nrf_desktop_hids` or :ref:`nrf_desktop_usb_state`) is a module that forwards HID reports to a HID host and forwards HID subscriptions of the HID host. A HID transport reports the state of a HID subscriber using the :c:struct:`hid_report_subscriber_event`. When the connection to the HID host is indicated by this event, the |hid_state| will create an associated subscriber. The |hid_state| tracks the state of the HID subscribers. As part of the :c:struct:`hid_report_subscriber_event`, the subscriber provides the following parameters: -* Subscriber priority - The |hid_state| provides HID input reports only to the subscriber with the highest priority (active subscriber). +* Subscriber priority - The |hid_state| provides HID input reports only to subscribers with the highest priority (active subscribers). * Pipeline size - The |hid_state| forwards this information to the HID report providers. The information can be used, for example, to synchronize sensor sampling with sending the HID input reports to the HID host. See the :ref:`nrf_desktop_hid_mouse_report_handling` section for information how the pipeline size is used for HID mouse reports. @@ -125,7 +143,7 @@ Tracking state of HID report subscriptions ------------------------------------------ For each subscriber, the |hid_state| tracks the state of HID input report subscriptions. -The HID input reports are only provided after the active subscriber enables the subscription. +The HID input reports are only provided after one of the active subscribers enables the subscription. The subscriber updates its HID report subscriptions using a :c:struct:`hid_report_subscription_event`. The HID report subscriptions are tracked in the subscriber's structure :c:struct:`subscriber`. @@ -213,5 +231,5 @@ HID output reports When the |hid_state| receives a :c:struct:`hid_report_event` that contains a HID output report, it updates the stored information about the state of the HID output report of the appropriate subscriber. By default, nRF Desktop supports only HID keyboard LED output report. -The nRF Desktop peripheral displays the state of the keyboard LEDs that was specified by the active HID subscriber. -When the active subscriber is changed or it updates the state of the keyboard LEDs, the |hid_state| sends :c:struct:`leds_event` to update the state of the hardware LEDs. +The nRF Desktop peripheral displays the state of the keyboard LEDs that was specified by the active HID subscriber of a HID keyboard input report. +When the subscriber changes or updates the state of the keyboard LEDs, the |hid_state| sends a :c:struct:`leds_event` to update the state of the hardware LEDs. From 9af3a16a335c37cd04ea18ef4edf3157d27a49df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Mon, 24 Nov 2025 13:33:56 +0100 Subject: [PATCH 035/155] doc: ironside: Expand on IronSide SE docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add documentation for BOOTMODE.DEBUGWAIT. Add documentation for BOOTMODE.SECONDARYMODE. Add documentation for BOOTSTATUS.SECONDARYMODE. Expand on how to configure a secondary firmware. Remove existing UICR secondary firmware docs as they were describing the UICR interface instead of the Kconfig interface. Signed-off-by: Sebastian Bøe --- .../nrf54h/ug_nrf54h20_ironside.rst | 142 +++++++++--------- 1 file changed, 68 insertions(+), 74 deletions(-) diff --git a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst index 147e358a36e3..7206b1e70a16 100644 --- a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst +++ b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst @@ -735,58 +735,6 @@ UICR.SECURESTORAGE.ITS UICR.SECURESTORAGE.ITS.RADIOCORESIZE1KB Sets the size of the ``RADIOCORE`` domain partition for ITS, specified in 1 kiB blocks. -UICR.SECONDARY -============== - -:kconfig:option:`CONFIG_GEN_UICR_SECONDARY` configures the secondary firmware boot system, which allows |ISE| to boot alternative firmware in response to specific conditions or triggers. -This feature enables a recovery firmware setup through a dual-firmware configuration that includes both main and recovery firmware. - -The UICR.SECONDARY configuration consists of multiple sub-registers organized into functional groups: - -UICR.SECONDARY.ENABLE - Controls whether the secondary firmware boot feature is enabled. - -UICR.SECONDARY.PROCESSOR - Specifies which processor should be used to boot the secondary firmware. - Valid values are: - - * ``APPLICATION`` - Boot secondary firmware on the application domain CPU. - * ``RADIOCORE`` - Boot secondary firmware on the radio core CPU. - -UICR.SECONDARY.ADDRESS - Sets the start address of the secondary firmware. - This value is used as the initial value of the secure Vector Table Offset Register (VTOR) after CPU reset. - The address must be aligned to a 4 KiB boundary. - Bits [11:0] are ignored. - -UICR.SECONDARY.TRIGGER - Configures automatic triggers that cause |ISE| to boot the secondary firmware instead of the primary firmware. - - UICR.SECONDARY.TRIGGER.ENABLE - Controls whether automatic triggers are enabled to boot the secondary firmware. - - UICR.SECONDARY.TRIGGER.RESETREAS - Specifies which reset reasons will trigger an automatic boot into the secondary firmware. - Multiple triggers can be enabled simultaneously by setting the corresponding bits: - - * ``APPLICATIONWDT0`` - Application domain watchdog 0 reset - * ``APPLICATIONWDT1`` - Application domain watchdog 1 reset - * ``APPLICATIONLOCKUP`` - Application domain CPU lockup reset - * ``RADIOCOREWDT0`` - Radio core watchdog 0 reset - * ``RADIOCOREWDT1`` - Radio core watchdog 1 reset - * ``RADIOCORELOCKUP`` - Radio core CPU lockup reset - -UICR.SECONDARY.PROTECTEDMEM - Identical to :kconfig:option:`CONFIG_GEN_UICR_PROTECTEDMEM`, but applies to the secondary firmware. - -UICR.SECONDARY.WDTSTART - Identical to :kconfig:option:`CONFIG_GEN_UICR_WDTSTART`, but applies to the secondary firmware boot process. - Note that if RADIOCORE is specified in ``UICR.SECONDARY.PROCESSOR``, the WDT instances used are the ones in the radio core. - -UICR.SECONDARY.PERIPHCONF - Identical to UICR.PERIPHCONF, but applies to the secondary firmware boot process. - - .. _ug_nrf54h20_ironside_se_debug: Debugging @@ -953,9 +901,9 @@ To enable secondary firmware support, you must complete the following steps: CONFIG_GEN_UICR_SECONDARY=y -2. Create a separate Zephyr application for your secondary firmware (for example in a :file:`secondary/` directory). +#. Create a separate Zephyr application for your secondary firmware (for example in a :file:`secondary/` directory). -3. Include the secondary image as an external project in :file:`sysbuild.cmake`: +#. Include this Zephyr application as an external project in :file:`sysbuild.cmake`: .. code-block:: cmake @@ -964,14 +912,27 @@ To enable secondary firmware support, you must complete the following steps: SOURCE_DIR ${APP_DIR}/secondary ) -4. **Configure secondary firmware**: The secondary firmware image itself must enable the appropriate Kconfig option to indicate it is a secondary firmware. +#. *Configure secondary firmware Kconfig*: The secondary firmware image itself must enable the appropriate Kconfig option to indicate it is a secondary firmware. Add the following to your secondary firmware's :file:`prj.conf`: .. code-block:: kconfig CONFIG_IS_IRONSIDE_SE_SECONDARY_IMAGE=y -5. **Optional: Configure automatic triggers**: If you want automatic triggering based on reset reasons, add trigger options to your :file:`sysbuild/uicr.conf`: +#. *Configure secondary firmware placement*: The secondary firmware image must be placed in the DT partition named ``secondary_partition``. + Add the following to your secondary firmware's :file:`app.overlay`: + + .. code-block:: devicetree + + / { + chosen { + zephyr,code-partition = &secondary_partition; + }; + }; + +#. *Optional: Configure secondary firmware features*: Additional features can be configured by adding more options to your :file:`sysbuild/uicr.conf`: + + For instance, if you want automatic triggering based on reset reasons, add trigger options: .. code-block:: kconfig @@ -994,9 +955,27 @@ Setting bit 5 in ``CTRLAP.BOOTMODE`` will also trigger secondary firmware. * The integrity check of the memory specified in :kconfig:option:`CONFIG_GEN_UICR_PROTECTEDMEM` fails. * Any boot failure occurs, such as missing primary firmware or failure to apply ``UICR.PERIPHCONF`` configurations. -* A local domain is reset with a reason configured to trigger the secondary firmware. -* If one of the triggers configured in :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_TRIGGER` and related options occurs. +* If :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_TRIGGER` is enabled, and a UICR-configurable trigger occurs. + See the following table for UICR-configurable triggers. +.. list-table:: Secondary firmware trigger Kconfig options + :header-rows: 1 + :widths: auto + + * - Kconfig option + - Description + * - :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_TRIGGER_APPLICATIONWDT0` + - Trigger on Application domain watchdog 0 reset + * - :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_TRIGGER_APPLICATIONWDT1` + - Trigger on Application domain watchdog 1 reset + * - :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_TRIGGER_APPLICATIONLOCKUP` + - Trigger on Application domain CPU lockup reset + * - :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_TRIGGER_RADIOCOREWDT0` + - Trigger on Radio core watchdog 0 reset + * - :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_TRIGGER_RADIOCOREWDT1` + - Trigger on Radio core watchdog 1 reset + * - :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_TRIGGER_RADIOCORELOCKUP` + - Trigger on Radio core CPU lockup reset Protection ========== @@ -1014,7 +993,17 @@ As with the primary firmware, |ISE| does not facilitate updating the secondary f The secondary image can be updated by other components as long as :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_PROTECTEDMEM` is not set. Using the secondary firmware as a bootloader capable of validating and updating a second image enables updating firmware in the secondary boot flow while having secure boot enabled through :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_PROTECTEDMEM`. +Secondary processor +=================== + +By default, the secondary firmware uses the application processor. +The radio core can be used instead by enabling the :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_PROCESSOR_RADIOCORE` option. +Changing the secondary firmware location +======================================== + +You can customize the location of the secondary firmware by modifying the ``secondary_partition`` DT partition in both the UICR image and the secondary firmware image. +This is typically done by editing the relevant devicetree source files (such as ``nrf54h20dk_nrf54h20_common.dts`` or board-specific overlay files) in your application and UICR image projects. .. _ug_nrf54h20_ironside_se_cpuconf_service: @@ -1137,11 +1126,11 @@ CTRLAP.BOOTMODE register format The format of the CTRLAP.MAILBOX.BOOTMODE register is described in the following table. -+------------------+--------+------------------+-----+----------------+--------+------------+ -| Bit numbers | 31-8 | 7 | 6-5 | 4 | 3-1 | 0 | -+------------------+--------+------------------+-----+----------------+--------+------------+ -| Field | N/A | Reserved | RFU | SAFEMODE (ROM) | OPCODE | MODE (ROM) | -+------------------+--------+------------------+-----+----------------+--------+------------+ ++------------------+--------+------------+-----+----------------+----------------+--------+------------+ +| Bit numbers | 31-8 | 7 | 6 | 5 | 4 | 3-1 | 0 | ++------------------+--------+------------+-----+----------------+----------------+--------+------------+ +| Field | N/A | DEBUGWAIT | RFU | SECONDARYMODE | SAFEMODE (ROM) | OPCODE | MODE (ROM) | ++------------------+--------+------------+-----+----------------+----------------+--------+------------+ .. _ug_nrf54h20_ironside_se_bootstatus_register_format: @@ -1161,11 +1150,11 @@ The BOOTSTAGE field indicates which component in the boot sequence encountered a If ``BOOTSTAGE`` is set to ``0xC`` or ``0xD``, the register has the following format: -+------------------+-------+-----------+-------+-----------+-----------+-----------+-----+-------------+ -| Bit numbers | 31-28 | 27-24 | 23-22 | 21-15 | 14-12 | 11-9 | 8 | 7-0 | -+------------------+-------+-----------+-------+-----------+-----------+-----------+-----+-------------+ -| Field | RFU | BOOTSTAGE | RFU | FWVERSION | CMDOPCODE | CMDERROR | RFU | BOOTERROR | -+------------------+-------+-----------+-------+-----------+-----------+-----------+-----+-------------+ ++------------------+-------+-----------+-------+-----------+-----------+-----------+----------------+-------------+ +| Bit numbers | 31-28 | 27-24 | 23-22 | 21-15 | 14-12 | 11-9 | 8 | 7-0 | ++------------------+-------+-----------+-------+-----------+-----------+-----------+----------------+-------------+ +| Field | RFU | BOOTSTAGE | RFU | FWVERSION | CMDOPCODE | CMDERROR | SECONDARYMODE | BOOTERROR | ++------------------+-------+-----------+-------+-----------+-----------+-----------+----------------+-------------+ This field can have one of the following values: @@ -1186,10 +1175,11 @@ This field can have one of the following values: +--------------------+--------------------------------------------------------------+ .. note:: - The value ``0xB`` indicates a boot status error reported by the Secure Domain running a version earlier than version 20. + The value ``0xB`` indicates a boot status error reported by the Secure Domain running a firmware version earlier than 20. + See :ref:`abi_compatibility` for more information. The register is written by |ISE| at the end of every cold boot sequence. -A value of 0 indicates that |ISE| did not complete the boot process. +A value of ``0`` indicates that |ISE| did not complete the boot process. The following fields are reported by |ISE|: @@ -1200,20 +1190,24 @@ FWVERSION CMDOPCODE The opcode of the boot command issued to |ISE| in the CTRLAP.MAILBOX.BOOTMODE register. - A value of 0 indicates that no boot command has been issued. + A value of ``0`` indicates that no boot command has been issued. CMDERROR A code indicating the execution status of the boot command specified in CMDOPCODE: - * A status value of 0 indicates that the command was executed successfully. + * A status value of ``0`` indicates that the command was executed successfully. * A non-zero value indicates that an error condition occurred during execution of the command. - The error code 0x7 means that an unexpected condition happened that might have prevented the command from executing. + The error code ``0x7`` means that an unexpected condition happened that might have prevented the command from executing. Other error codes must be interpreted based on the boot command in CMDOPCODE. +SECONDARYMODE + Indicates whether the secondary firmware was booted. + A value of ``1`` indicates that the secondary firmware was booted, while a value of ``0`` indicates that the primary firmware was booted. + BOOTERROR A code indicating the status of the application domain boot sequence: - * A status value of 0 indicates that the CPU was started normally. + * A status value of ``0`` indicates that the CPU was started normally. * A non-zero value indicates that an error condition occurred, preventing the CPU from starting. Detailed information about the issue can be found in the boot report. From 7f7a152f8cb10a7a70f349ffa4accff51a740863 Mon Sep 17 00:00:00 2001 From: Georgios Vasilakis Date: Thu, 6 Nov 2025 12:55:41 +0100 Subject: [PATCH 036/155] nrf_security: Add key policy for the Cracen builtin keys Add logic which allows to specifically define who can use the builtin keys (IKG and KMU one) for Cracen when used with TF-M. This includes a list of specifically allowed users for the builtin keys and any other access is denied. This is only relevant for a TF-M enabled application since that is currently the only way to encode ownership in the key attributes. Ref: NCSDK-35736 Signed-off-by: Georgios Vasilakis --- .../drivers/cracen/cracenpsa/cracenpsa.cmake | 6 + .../include/cracen_psa_builtin_key_policy.h | 45 ++++++ .../cracen/cracenpsa/src/builtin_key_policy.c | 129 ++++++++++++++++++ .../cracen/cracenpsa/src/key_management.c | 34 +++++ 4 files changed, 214 insertions(+) create mode 100644 subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_builtin_key_policy.h create mode 100644 subsys/nrf_security/src/drivers/cracen/cracenpsa/src/builtin_key_policy.c diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake b/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake index 94853658d21d..a3b5f1988511 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake @@ -23,6 +23,12 @@ list(APPEND cracen_driver_sources ${CMAKE_CURRENT_LIST_DIR}/src/prng_pool.c ) +if(BUILD_INSIDE_TFM) + list(APPEND cracen_driver_sources + ${CMAKE_CURRENT_LIST_DIR}/src/builtin_key_policy.c + ) +endif() + # Include hardware cipher implementation for all devices except nRF54LM20A # nRF54LM20A uses only cracen_sw if(NOT CONFIG_PSA_NEED_CRACEN_MULTIPART_WORKAROUNDS) diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_builtin_key_policy.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_builtin_key_policy.h new file mode 100644 index 000000000000..8dbb368bcd03 --- /dev/null +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_builtin_key_policy.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef CRACEN_PSA_BUILTIN_KEY_POLICY_H +#define CRACEN_PSA_BUILTIN_KEY_POLICY_H + +#include +#include + +#if defined(__NRF_TFM__) + +typedef struct { + mbedtls_key_owner_id_t owner; + psa_drv_slot_number_t key_slot; +} cracen_builtin_ikg_key_policy_t; + +typedef enum { + KMU_ENTRY_SLOT_SINGLE, + KMU_ENTRY_SLOT_RANGE, +} cracen_kmu_entry_type_t; + +/* When defining a range of KMU slots both the start and end slot numbers are inclusive. */ +typedef struct { + mbedtls_key_owner_id_t owner; + psa_drv_slot_number_t key_slot_start; + psa_drv_slot_number_t key_slot_end; + cracen_kmu_entry_type_t kmu_entry_type; +} cracen_builtin_kmu_key_policy_t; + +bool cracen_builtin_key_user_allowed(const psa_key_attributes_t *attributes); + +#else + +static inline bool cracen_builtin_key_user_allowed(const psa_key_attributes_t *attributes) +{ + (void)attributes; + return true; +} + +#endif /* __NRF_TFM__ */ + +#endif /* CRACEN_PSA_BUILTIN_KEY_POLICY_H */ diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/builtin_key_policy.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/builtin_key_policy.c new file mode 100644 index 000000000000..b5e548c413a0 --- /dev/null +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/builtin_key_policy.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "common.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define MAPPED_TZ_NS_AGENT_DEFAULT_CLIENT_ID (-0x3c000000) + +static const cracen_builtin_ikg_key_policy_t g_builtin_ikg_policy[] = { +#ifdef TFM_SP_ITS + {.owner = TFM_SP_ITS, .key_slot = TFM_BUILTIN_KEY_ID_HUK}, +#endif /* TFM_SP_ITS */ +#ifdef TFM_SP_PS + {.owner = TFM_SP_PS, .key_slot = TFM_BUILTIN_KEY_ID_HUK}, +#endif /* TFM_SP_PS */ +#ifdef TFM_SP_INITIAL_ATTESTATION + {.owner = TFM_SP_INITIAL_ATTESTATION, .key_slot = TFM_BUILTIN_KEY_ID_IAK} +#endif /* TFM_SP_INITIAL_ATTESTATION */ +}; + +#ifdef PSA_NEED_CRACEN_KMU_DRIVER + +static const cracen_builtin_kmu_key_policy_t g_builtin_kmu_policy[] = { + /* 0x0 is used by libraries like the hw_unique_key library when manually generating psa + * key_ids. Allow access to all slots for these libraries since they don't have the logic to + * have an owner id and reside inside TF-M. + */ + {.owner = 0x0, + .key_slot_start = 0, + .key_slot_end = 255, + .kmu_entry_type = KMU_ENTRY_SLOT_RANGE}, +#ifdef TFM_SP_ITS + {.owner = TFM_SP_ITS, + .key_slot_start = 0, + .key_slot_end = 255, + .kmu_entry_type = KMU_ENTRY_SLOT_RANGE}, +#endif /* TFM_SP_ITS */ +#ifdef TFM_SP_CRYPTO + {.owner = TFM_SP_CRYPTO, + .key_slot_start = 0, + .key_slot_end = 255, + .kmu_entry_type = KMU_ENTRY_SLOT_RANGE}, +#endif /* TFM_SP_CRYPTO */ + /* The docs have KMU slots >= 180 reserved so don't allow NS users to access them */ + {.owner = MAPPED_TZ_NS_AGENT_DEFAULT_CLIENT_ID, + .key_slot_start = 0, + .key_slot_end = 179, + .kmu_entry_type = KMU_ENTRY_SLOT_RANGE}}; + +static bool cracen_builtin_kmu_user_allowed(mbedtls_key_owner_id_t owner, + psa_drv_slot_number_t slot_number, + const psa_key_attributes_t *attributes) +{ + for (uint32_t i = 0; i < NRFX_ARRAY_SIZE(g_builtin_kmu_policy); i++) { + + switch (g_builtin_kmu_policy[i].kmu_entry_type) { + case KMU_ENTRY_SLOT_SINGLE: + if (g_builtin_kmu_policy[i].owner == owner && + g_builtin_kmu_policy[i].key_slot_start == slot_number) { + return true; + } + break; + case KMU_ENTRY_SLOT_RANGE: + if (g_builtin_kmu_policy[i].owner == owner && + (slot_number >= g_builtin_kmu_policy[i].key_slot_start && + slot_number <= g_builtin_kmu_policy[i].key_slot_end)) { + return true; + } + break; + default: + break; + } + } + + return false; +} +#endif /* PSA_NEED_CRACEN_KMU_DRIVER */ + +static bool cracen_builtin_ikg_user_allowed(mbedtls_key_owner_id_t owner, + psa_drv_slot_number_t slot_number, + const psa_key_attributes_t *attributes) +{ + for (uint32_t i = 0; i < NRFX_ARRAY_SIZE(g_builtin_ikg_policy); i++) { + if (g_builtin_ikg_policy[i].owner == owner && + g_builtin_ikg_policy[i].key_slot == slot_number) { + return true; + } + } + + return false; +} + +bool cracen_builtin_key_user_allowed(const psa_key_attributes_t *attributes) +{ + mbedtls_key_owner_id_t owner = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(psa_get_key_id(attributes)); + psa_drv_slot_number_t slot_id; + + if (PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)) == + PSA_KEY_LOCATION_CRACEN) { + + slot_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(attributes)); + return cracen_builtin_ikg_user_allowed(owner, slot_id, attributes); + } + +#ifdef PSA_NEED_CRACEN_KMU_DRIVER + if (PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)) == + PSA_KEY_LOCATION_CRACEN_KMU) { + + slot_id = CRACEN_PSA_GET_KMU_SLOT( + MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(attributes))); + return cracen_builtin_kmu_user_allowed(owner, slot_id, attributes); + } +#endif /* PSA_NEED_CRACEN_KMU_DRIVER */ + + return true; +} diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c index 345a35b1902b..b40df4efbec9 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "ecc.h" #include @@ -894,6 +895,10 @@ psa_status_t cracen_export_public_key(const psa_key_attributes_t *attributes, return PSA_ERROR_INVALID_ARGUMENT; } + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + if (IS_ENABLED(PSA_NEED_CRACEN_KEY_TYPE_ECC_KEY_PAIR_EXPORT)) { if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) { return export_ecc_public_key_from_keypair(attributes, key_buffer, @@ -945,6 +950,10 @@ psa_status_t cracen_import_key(const psa_key_attributes_t *attributes, const uin return PSA_ERROR_INVALID_ARGUMENT; } + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); #ifdef PSA_NEED_CRACEN_KMU_DRIVER @@ -1205,6 +1214,10 @@ psa_status_t cracen_generate_key(const psa_key_attributes_t *attributes, uint8_t psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + #ifdef PSA_NEED_CRACEN_KMU_DRIVER if (location == PSA_KEY_LOCATION_CRACEN_KMU) { return generate_key_for_kmu(attributes, key_buffer, key_buffer_size, @@ -1337,6 +1350,11 @@ psa_status_t cracen_get_builtin_key(psa_drv_slot_number_t slot_number, * and the `lifetime` field of the attribute struct. We will fill all the other * attributes, and update the `lifetime` field to be more specific. */ + + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + switch (slot_number) { case CRACEN_BUILTIN_IDENTITY_KEY_ID: case CRACEN_BUILTIN_MKEK_ID: @@ -1394,6 +1412,10 @@ psa_status_t cracen_export_key(const psa_key_attributes_t *attributes, const uin psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + if (location == PSA_KEY_LOCATION_CRACEN_KMU) { /* The keys will already be in the key buffer as they got loaded their by a previous * call to cracen_get_builtin_key or cached in the memory. @@ -1442,6 +1464,10 @@ psa_status_t cracen_copy_key(psa_key_attributes_t *attributes, const uint8_t *so size_t target_key_buffer_size, size_t *target_key_buffer_length) { #ifdef PSA_NEED_CRACEN_KMU_DRIVER + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); @@ -1496,6 +1522,10 @@ psa_status_t cracen_copy_key(psa_key_attributes_t *attributes, const uint8_t *so psa_status_t cracen_destroy_key(const psa_key_attributes_t *attributes) { #ifdef PSA_NEED_CRACEN_KMU_DRIVER + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + return cracen_kmu_destroy_key(attributes); #endif @@ -1508,6 +1538,10 @@ psa_status_t cracen_derive_key(const psa_key_attributes_t *attributes, const uin { psa_key_type_t key_type = psa_get_key_type(attributes); + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + if (PSA_KEY_TYPE_IS_SPAKE2P_KEY_PAIR(key_type) && IS_ENABLED(PSA_NEED_CRACEN_SPAKE2P)) { return cracen_derive_spake2p_key(attributes, input, input_length, key, key_size, key_length); From 670c06ab09dd72ac9588dac11ca59a7dfce07371 Mon Sep 17 00:00:00 2001 From: Georgios Vasilakis Date: Thu, 6 Nov 2025 13:18:28 +0100 Subject: [PATCH 037/155] nrf_security: Avoid including tfm_builtin_key_loader.h The tfm_builtin_key_loader.h defines the symbol: TFM_BUILTIN_KEY_LOADER_KEY_LOCATION which is also defined in the tfm_builtin_key_ids.h when Cracen is enabled. To avoid this remove including the default key loader and only keep the Cracen one. Signed-off-by: Georgios Vasilakis --- .../src/drivers/cracen/cracenpsa/include/cracen_psa.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h index fff3e1dc1c19..e68d849bfd0f 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h @@ -18,10 +18,6 @@ #include "cracen_psa_key_ids.h" #include "sxsymcrypt/keyref.h" -#ifdef __NRF_TFM__ -#include -#endif - /** * See "PSA Cryptography API" for documentation. */ From 0bbceddb13b2008c3bfb4fdea0fb529b9456d44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Mon, 24 Nov 2025 10:38:19 +0100 Subject: [PATCH 038/155] samples: nrf54h20: Explicitly enable CONFIG_IS_GEN_UICR_IMAGE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CONFIG_IS_GEN_UICR_IMAGE was accidentally not enabled by default upstream requiring us to explicitly enable it. Signed-off-by: Sebastian Bøe --- samples/crypto/persistent_key_usage/sysbuild/uicr/prj.conf | 1 + samples/ironside_se/protectedmem_periphconf/sysbuild/uicr.conf | 2 ++ samples/ironside_se/secondary_boot_gen_uicr/sysbuild/uicr.conf | 2 ++ .../secondary_boot_trigger_lockup/sysbuild/uicr.conf | 2 ++ tests/drivers/watchdog/uicr_wdtstart/sysbuild/uicr.conf | 2 ++ 5 files changed, 9 insertions(+) diff --git a/samples/crypto/persistent_key_usage/sysbuild/uicr/prj.conf b/samples/crypto/persistent_key_usage/sysbuild/uicr/prj.conf index f32d32389395..173568a67283 100644 --- a/samples/crypto/persistent_key_usage/sysbuild/uicr/prj.conf +++ b/samples/crypto/persistent_key_usage/sysbuild/uicr/prj.conf @@ -2,3 +2,4 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # Intentionally left blank +CONFIG_IS_GEN_UICR_IMAGE=y diff --git a/samples/ironside_se/protectedmem_periphconf/sysbuild/uicr.conf b/samples/ironside_se/protectedmem_periphconf/sysbuild/uicr.conf index 2c072f1db0a8..886a0eacf8cf 100644 --- a/samples/ironside_se/protectedmem_periphconf/sysbuild/uicr.conf +++ b/samples/ironside_se/protectedmem_periphconf/sysbuild/uicr.conf @@ -3,6 +3,8 @@ # # Configuration overlay for uicr image +CONFIG_IS_GEN_UICR_IMAGE=y + # Enable PROTECTEDMEM CONFIG_GEN_UICR_PROTECTEDMEM=y diff --git a/samples/ironside_se/secondary_boot_gen_uicr/sysbuild/uicr.conf b/samples/ironside_se/secondary_boot_gen_uicr/sysbuild/uicr.conf index e31cfbe35997..99aa57c0fb93 100644 --- a/samples/ironside_se/secondary_boot_gen_uicr/sysbuild/uicr.conf +++ b/samples/ironside_se/secondary_boot_gen_uicr/sysbuild/uicr.conf @@ -1,6 +1,8 @@ # Copyright (c) 2025 Nordic Semiconductor ASA # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +CONFIG_IS_GEN_UICR_IMAGE=y + # Configuration overlay for uicr image # Enable UICR.SECONDARY.ENABLE CONFIG_GEN_UICR_SECONDARY=y diff --git a/samples/ironside_se/secondary_boot_trigger_lockup/sysbuild/uicr.conf b/samples/ironside_se/secondary_boot_trigger_lockup/sysbuild/uicr.conf index 929e422b1c96..a66d61d79b29 100644 --- a/samples/ironside_se/secondary_boot_trigger_lockup/sysbuild/uicr.conf +++ b/samples/ironside_se/secondary_boot_trigger_lockup/sysbuild/uicr.conf @@ -1,6 +1,8 @@ # Copyright (c) 2025 Nordic Semiconductor ASA # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +CONFIG_IS_GEN_UICR_IMAGE=y + # Configuration overlay for uicr image # Enable UICR.SECONDARY with automatic trigger on APPLICATIONLOCKUP CONFIG_GEN_UICR_SECONDARY=y diff --git a/tests/drivers/watchdog/uicr_wdtstart/sysbuild/uicr.conf b/tests/drivers/watchdog/uicr_wdtstart/sysbuild/uicr.conf index 2c8705776e1d..1474f4d72718 100644 --- a/tests/drivers/watchdog/uicr_wdtstart/sysbuild/uicr.conf +++ b/tests/drivers/watchdog/uicr_wdtstart/sysbuild/uicr.conf @@ -1,6 +1,8 @@ # Copyright (c) 2025 Nordic Semiconductor ASA # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +CONFIG_IS_GEN_UICR_IMAGE=y + # Allow Ironside to configure and start WDT CONFIG_GEN_UICR_WDTSTART=y From e44f6e0c15a3841d6fc8062cdaf3c5781e24f184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn-Inge=20Kleppe?= Date: Mon, 17 Nov 2025 14:35:53 +0000 Subject: [PATCH 039/155] manifest: Update sdk-nrfxlib revision and align to nrfxlib MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-nrfxlib/pull/1924 Now Soft Peripherals are selected by SOC series, not individual SOC. Updated include path to the sQSPI in nrfxlib to reflect changes in folder structure. Signed-off-by: Bjørn-Inge Kleppe --- drivers/mspi/CMakeLists.txt | 12 ++++++------ west.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mspi/CMakeLists.txt b/drivers/mspi/CMakeLists.txt index 67d109ad46f1..5f3f6bf7e185 100644 --- a/drivers/mspi/CMakeLists.txt +++ b/drivers/mspi/CMakeLists.txt @@ -8,8 +8,8 @@ zephyr_library_amend() zephyr_library_sources_ifdef(CONFIG_MSPI_HPF mspi_hpf.c) if(CONFIG_MSPI_NRF_SQSPI) - set(SP_DIR ${ZEPHYR_NRFXLIB_MODULE_DIR}/softperipheral) - set(SQSPI_DIR ${SP_DIR}/sQSPI) + set(sp_dir ${ZEPHYR_NRFXLIB_MODULE_DIR}/softperipheral) + set(sqspi_dir ${sp_dir}/sQSPI) dt_comp_path(sqspi_path COMPATIBLE "nordic,nrf-sqspi" IDX 0) dt_reg_addr(sqspi_addr PATH ${sqspi_path}) @@ -21,12 +21,12 @@ if(CONFIG_MSPI_NRF_SQSPI) NRF_SQSPI_SP_FIRMWARE_ADDR=${sqspi_sp_firmware_addr} ) zephyr_library_include_directories( - ${SP_DIR}/include - ${SQSPI_DIR}/include - ${SQSPI_DIR}/include/${CONFIG_SOC} + ${sp_dir}/include + ${sqspi_dir}/include + ${sqspi_dir}/include/${CONFIG_SOC_SERIES} ) zephyr_library_sources( - ${SQSPI_DIR}/src/nrf_sqspi.c + ${sqspi_dir}/src/nrf_sqspi.c mspi_sqspi.c ) endif() diff --git a/west.yml b/west.yml index 562c258ffe3b..b648536a57c2 100644 --- a/west.yml +++ b/west.yml @@ -143,7 +143,7 @@ manifest: - name: nrfxlib repo-path: sdk-nrfxlib path: nrfxlib - revision: 5b0b19946f2bb47cfa4aa358322146edee38cbd5 + revision: 82c041e33c40820c4694995c869bfd5eedefe68a - name: trusted-firmware-m repo-path: sdk-trusted-firmware-m path: modules/tee/tf-m/trusted-firmware-m From afd502684994be053d4339b786943b4c435c1a31 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Mon, 1 Dec 2025 12:25:37 +0000 Subject: [PATCH 040/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3562 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index b648536a57c2..6da75b5f244e 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: d3409c65bf0bf3c207fea1d456041939126a5911 + revision: 0783923a766da87024851b71030e1f70dd404b60 import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From 7c50719f9d74c832662a3a7869be9cec9f9c9f56 Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Fri, 28 Nov 2025 09:56:21 +0100 Subject: [PATCH 041/155] nrf_rpc: unify nRF RPC initialization Currently, almost each component implementing RPC function encoders and decoders, provides an option to automatically start nRF RPC during the system startup. Reduce the code duplication by introducing CONFIG_NRF_RPC_INIT that handles starting nRF RPC regardless of the enabled RPC serialization libraries. Signed-off-by: Damian Krolik --- .../client/snippets/ble/ble.conf | 2 +- .../server/snippets/ble/ble.conf | 2 +- subsys/bluetooth/rpc/Kconfig | 8 +--- subsys/bluetooth/rpc/common/bt_rpc_common.c | 28 -------------- subsys/net/openthread/rpc/Kconfig | 7 ---- .../net/openthread/rpc/common/ot_rpc_group.c | 22 ----------- subsys/nfc/rpc/common/nfc_rpc_group.c | 22 ----------- subsys/nrf_rpc/CMakeLists.txt | 2 + subsys/nrf_rpc/Kconfig | 26 +++++++++---- subsys/nrf_rpc/nrf_rpc_init.c | 37 +++++++++++++++++++ 10 files changed, 61 insertions(+), 95 deletions(-) create mode 100644 subsys/nrf_rpc/nrf_rpc_init.c diff --git a/samples/nrf_rpc/protocols_serialization/client/snippets/ble/ble.conf b/samples/nrf_rpc/protocols_serialization/client/snippets/ble/ble.conf index 8789616d2993..961fc57dca88 100644 --- a/samples/nrf_rpc/protocols_serialization/client/snippets/ble/ble.conf +++ b/samples/nrf_rpc/protocols_serialization/client/snippets/ble/ble.conf @@ -9,7 +9,7 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2144 # Enable and configure Bluetooth LE CONFIG_BT=y CONFIG_BT_RPC_STACK=y -CONFIG_BT_RPC_INITIALIZE_NRF_RPC=n +CONFIG_NRF_RPC_INIT=n CONFIG_BT_RPC_GATT_SRV_MAX=4 CONFIG_BT_PERIPHERAL=y CONFIG_BT_MAX_CONN=1 diff --git a/samples/nrf_rpc/protocols_serialization/server/snippets/ble/ble.conf b/samples/nrf_rpc/protocols_serialization/server/snippets/ble/ble.conf index 4bbff24d886c..4a2b3d80753e 100644 --- a/samples/nrf_rpc/protocols_serialization/server/snippets/ble/ble.conf +++ b/samples/nrf_rpc/protocols_serialization/server/snippets/ble/ble.conf @@ -8,7 +8,7 @@ CONFIG_BT=y CONFIG_BT_RPC=y CONFIG_BT_RPC_HOST=y -CONFIG_BT_RPC_INITIALIZE_NRF_RPC=n +CONFIG_NRF_RPC_INIT=n CONFIG_BT_PERIPHERAL=y CONFIG_BT_MAX_CONN=1 diff --git a/subsys/bluetooth/rpc/Kconfig b/subsys/bluetooth/rpc/Kconfig index 9b78ec81b4b3..0df3f2295f8b 100644 --- a/subsys/bluetooth/rpc/Kconfig +++ b/subsys/bluetooth/rpc/Kconfig @@ -9,6 +9,7 @@ config BT_RPC default y if BT_RPC_STACK select NRF_RPC select NRF_RPC_CBOR + imply NRF_RPC_INIT select EXPERIMENTAL depends on BT depends on !BT_ISO_UNICAST @@ -48,13 +49,6 @@ config BT_RPC_HOST endchoice -config BT_RPC_INITIALIZE_NRF_RPC - bool "Automatically initialize nRF RPC library" - default y - help - Initialize nRF RPC library during the system startup. Disabling this - option allow user to initialize it in a different way. - config BT_RPC_GATT_SRV_MAX int "Maximum number of GATT services" default 4 diff --git a/subsys/bluetooth/rpc/common/bt_rpc_common.c b/subsys/bluetooth/rpc/common/bt_rpc_common.c index 6af499ac6590..b8ba85fff07a 100644 --- a/subsys/bluetooth/rpc/common/bt_rpc_common.c +++ b/subsys/bluetooth/rpc/common/bt_rpc_common.c @@ -28,34 +28,6 @@ NRF_RPC_IPC_TRANSPORT(bt_rpc_tr, DEVICE_DT_GET(DT_NODELABEL(ipc0)), "bt_rpc_ept" #endif NRF_RPC_GROUP_DEFINE(bt_rpc_grp, "bt_rpc", &bt_rpc_tr, NULL, NULL, NULL); -#if CONFIG_BT_RPC_INITIALIZE_NRF_RPC -static void err_handler(const struct nrf_rpc_err_report *report) -{ - LOG_ERR("nRF RPC error %d ocurred. See nRF RPC logs for more details.", - report->code); - k_oops(); -} - -static int serialization_init(void) -{ - - int err; - - LOG_DBG("Init begin"); - - err = nrf_rpc_init(err_handler); - if (err) { - return -EINVAL; - } - - LOG_DBG("Init done\n"); - - return 0; -} - -SYS_INIT(serialization_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); -#endif /* CONFIG_BT_RPC_INITIALIZE_NRF_RPC */ - enum { CHECK_ENTRY_FLAGS, CHECK_ENTRY_UINT, diff --git a/subsys/net/openthread/rpc/Kconfig b/subsys/net/openthread/rpc/Kconfig index d493a7c5817a..9532b6dc5add 100644 --- a/subsys/net/openthread/rpc/Kconfig +++ b/subsys/net/openthread/rpc/Kconfig @@ -96,11 +96,4 @@ config OPENTHREAD_RPC_ERASE_SETTINGS endmenu # "OpenThread over RPC server configuration" -config OPENTHREAD_RPC_INITIALIZE_NRF_RPC - bool "Automatically initialize nRF RPC library" - default n - help - Initialize nRF RPC library during the system startup. Disabling this - option allow user to initialize it in a different way. - endif # OPENTHREAD_RPC diff --git a/subsys/net/openthread/rpc/common/ot_rpc_group.c b/subsys/net/openthread/rpc/common/ot_rpc_group.c index 1151163e7619..6b90673a54c0 100644 --- a/subsys/net/openthread/rpc/common/ot_rpc_group.c +++ b/subsys/net/openthread/rpc/common/ot_rpc_group.c @@ -24,25 +24,3 @@ NRF_RPC_IPC_TRANSPORT(ot_rpc_tr, DEVICE_DT_GET(DT_NODELABEL(ipc0)), "ot_rpc_ept" #endif NRF_RPC_GROUP_DEFINE(ot_group, "ot", &ot_rpc_tr, NULL, NULL, NULL); LOG_MODULE_REGISTER(ot_rpc, LOG_LEVEL_DBG); - -#ifdef CONFIG_OPENTHREAD_RPC_INITIALIZE_NRF_RPC -static void err_handler(const struct nrf_rpc_err_report *report) -{ - LOG_ERR("nRF RPC error %d ocurred. See nRF RPC logs for more details", report->code); - k_oops(); -} - -static int serialization_init(void) -{ - int err; - - err = nrf_rpc_init(err_handler); - if (err) { - return -EINVAL; - } - - return 0; -} - -SYS_INIT(serialization_init, POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY); -#endif /* CONFIG_OPENTHREAD_RPC_INITIALIZE_NRF_RPC */ diff --git a/subsys/nfc/rpc/common/nfc_rpc_group.c b/subsys/nfc/rpc/common/nfc_rpc_group.c index 4ef393812d14..23cd5c385909 100644 --- a/subsys/nfc/rpc/common/nfc_rpc_group.c +++ b/subsys/nfc/rpc/common/nfc_rpc_group.c @@ -25,25 +25,3 @@ NRF_RPC_IPC_TRANSPORT(nfc_rpc_tr, DEVICE_DT_GET(DT_NODELABEL(ipc0)), "nfc_rpc_ep #endif NRF_RPC_GROUP_DEFINE(nfc_group, "nfc", &nfc_rpc_tr, NULL, NULL, NULL); LOG_MODULE_REGISTER(nfc_rpc, LOG_LEVEL_DBG); - -#ifdef CONFIG_NFC_RPC_INITIALIZE_NRF_RPC -static void err_handler(const struct nrf_rpc_err_report *report) -{ - LOG_ERR("nRF RPC error %d ocurred. See nRF RPC logs for more details", report->code); - k_oops(); -} - -static int serialization_init(void) -{ - int err; - - err = nrf_rpc_init(err_handler); - if (err) { - return -EINVAL; - } - - return 0; -} - -SYS_INIT(serialization_init, POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY); -#endif /* CONFIG_NFC_RPC_INITIALIZE_NRF_RPC */ diff --git a/subsys/nrf_rpc/CMakeLists.txt b/subsys/nrf_rpc/CMakeLists.txt index 844bdbb78091..246d3ff9bec9 100644 --- a/subsys/nrf_rpc/CMakeLists.txt +++ b/subsys/nrf_rpc/CMakeLists.txt @@ -18,4 +18,6 @@ zephyr_library_sources_ifdef(CONFIG_NRF_RPC_CALLBACK_PROXY nrf_rpc_cbkproxy.c) zephyr_library_sources_ifdef(CONFIG_NRF_RPC_UART_TRANSPORT nrf_rpc_uart.c) +zephyr_library_sources_ifdef(CONFIG_NRF_RPC_INIT nrf_rpc_init.c) + add_subdirectory_ifdef(CONFIG_NRF_RPC_UTILS rpc_utils) diff --git a/subsys/nrf_rpc/Kconfig b/subsys/nrf_rpc/Kconfig index ed6f68d5aae1..c8db971cc1f7 100644 --- a/subsys/nrf_rpc/Kconfig +++ b/subsys/nrf_rpc/Kconfig @@ -15,6 +15,12 @@ config _NRF_RPC_DUMMY_SELECT default y select THREAD_CUSTOM_DATA +config NRF_RPC_CBOR + select ZCBOR + select ZCBOR_STOP_ON_ERROR + +# End of Zephyr port dependencies selection + choice NRF_RPC_TRANSPORT prompt "NRF RPC transport" default NRF_RPC_IPC_SERVICE @@ -109,13 +115,6 @@ endif # NRF_RPC_UART_RELIABLE endmenu # "nRF RPC over UART configuration" -config NRF_RPC_CBOR - bool - select ZCBOR - select ZCBOR_STOP_ON_ERROR - -# End of Zephyr port dependencies selection - config NRF_RPC_THREAD_STACK_SIZE int "Stack size of thread from thread pool" default 1024 @@ -174,6 +173,11 @@ config NRF_RPC_CBKPROXY_IN_SLOTS endif # NRF_RPC_CALLBACK_PROXY +config NRF_RPC_INIT + bool "Automatically initialize nRF RPC library" + help + Initialize nRF RPC library during the system startup. + module = NRF_RPC module-str = NRF_RPC source "$(ZEPHYR_BASE)/subsys/logging/Kconfig.template.log_config" @@ -194,6 +198,14 @@ source "$(ZEPHYR_BASE)/subsys/logging/Kconfig.template.log_config" endif # NRF_RPC_CBOR +if NRF_RPC_INIT + +module = NRF_RPC_INIT +module-str = NRF_RPC_INIT +source "$(ZEPHYR_BASE)/subsys/logging/Kconfig.template.log_config" + +endif # NRF_RPC_INIT + rsource "rpc_utils/Kconfig" endif # NRF_RPC diff --git a/subsys/nrf_rpc/nrf_rpc_init.c b/subsys/nrf_rpc/nrf_rpc_init.c new file mode 100644 index 000000000000..dae4b54ab4e5 --- /dev/null +++ b/subsys/nrf_rpc/nrf_rpc_init.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#define NRF_RPC_LOG_MODULE NRF_RPC_INIT +#include + +#include + +#include + +static void err_handler(const struct nrf_rpc_err_report *report) +{ + LOG_ERR("nRF RPC error %d ocurred. See nRF RPC logs for more details", + report->code); + k_oops(); +} + +static int nrf_rpc_sys_init(void) +{ + int err; + + LOG_DBG("RPC init begin"); + + err = nrf_rpc_init(err_handler); + if (err) { + return -EINVAL; + } + + LOG_DBG("RPC init done"); + + return 0; +} + +SYS_INIT(nrf_rpc_sys_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); From d576cafff4dc4ac7c24769aa8d747218bcbc21dd Mon Sep 17 00:00:00 2001 From: Triveni Danda Date: Sun, 30 Nov 2025 14:37:25 +0530 Subject: [PATCH 042/155] samples: wifi: promiscuous: Increase RX data pool size Increase RX data pool to fix data buffer allocation failures. Fixes SHEL-3917. Signed-off-by: Triveni Danda --- samples/wifi/promiscuous/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/wifi/promiscuous/prj.conf b/samples/wifi/promiscuous/prj.conf index 2dfa2d02b46e..3365d815b49d 100644 --- a/samples/wifi/promiscuous/prj.conf +++ b/samples/wifi/promiscuous/prj.conf @@ -58,6 +58,7 @@ CONFIG_NET_SOCKETS_POLL_MAX=10 CONFIG_MAIN_STACK_SIZE=5200 CONFIG_NET_TX_STACK_SIZE=4096 CONFIG_NET_RX_STACK_SIZE=4096 +CONFIG_NET_PKT_BUF_RX_DATA_POOL_SIZE=20000 # Debugging CONFIG_STACK_SENTINEL=y From e2099c008a0294f9f964977769890e16486d67b1 Mon Sep 17 00:00:00 2001 From: Triveni Danda Date: Mon, 1 Dec 2025 22:11:04 +0530 Subject: [PATCH 043/155] modules: wfa-qt: Set PMF to optional Make PMF optional by default instead of forcing it disabled when not configured. Signed-off-by: Triveni Danda --- modules/wfa-qt/src/indigo_api_callback_dut.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/wfa-qt/src/indigo_api_callback_dut.c b/modules/wfa-qt/src/indigo_api_callback_dut.c index e297e7acc55d..46e8a5518acf 100644 --- a/modules/wfa-qt/src/indigo_api_callback_dut.c +++ b/modules/wfa-qt/src/indigo_api_callback_dut.c @@ -1883,7 +1883,7 @@ static int configure_sta_handler(struct packet_wrapper *req, struct packet_wrapp ret = run_qt_command(buffer); CHECK_RET(); } else { - ret = run_qt_command("SET_NETWORK 0 ieee80211w 0"); + ret = run_qt_command("SET_NETWORK 0 ieee80211w 1"); CHECK_RET(); } } else if (strstr(tlv->value, "SAE")) { From 77fbeeb5a04279f4d17f52a099b2019cc8ce78dd Mon Sep 17 00:00:00 2001 From: Triveni Danda Date: Mon, 1 Dec 2025 22:23:37 +0530 Subject: [PATCH 044/155] modules: wfa-qt: Enable scan_ssid for proper connection Without scan_ssid, the STA sends a broadcast probe and relies on filter_ssid to match results. Since filter_ssid is not used, scan_ssid must be enabled to explicitly scan for the configured SSID. Signed-off-by: Triveni Danda --- modules/wfa-qt/src/indigo_api_callback_dut.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/wfa-qt/src/indigo_api_callback_dut.c b/modules/wfa-qt/src/indigo_api_callback_dut.c index 46e8a5518acf..e27a4080f723 100644 --- a/modules/wfa-qt/src/indigo_api_callback_dut.c +++ b/modules/wfa-qt/src/indigo_api_callback_dut.c @@ -2002,6 +2002,9 @@ static int configure_sta_handler(struct packet_wrapper *req, struct packet_wrapp ret = run_qt_command(buffer); CHECK_RET(); } + + ret = run_qt_command("SET_NETWORK 0 scan_ssid 1"); + CHECK_RET(); done: fill_wrapper_message_hdr(resp, API_CMD_RESPONSE, req->hdr.seq); fill_wrapper_tlv_byte(resp, TLV_STATUS, status); From d1409eef660d61754d8aae1331b1f3a370b44e54 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Mon, 1 Dec 2025 15:51:23 +0100 Subject: [PATCH 045/155] mpsl: pin_debug: Fix MPSL_PIN_DEBUG for 54L series This commit fixes issues introduced by a8f694765e0c1602d5f2c84c233b5d719721dab2 - `passing argument 1 of 'nrfx_gppi_domain_id_get' makes integer from pointer without a cast` - Accessing wrong member of rad_resource - Wrong argument order calling nrfx_gppi_ep_attach() Fix was verified on a 54l15dk. Signed-off-by: Rubin Gerritsen --- subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c b/subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c index f8ac2915e8fa..825bb7128b5d 100644 --- a/subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c +++ b/subsys/mpsl/pin_debug/mpsl_pin_debug_nrf54.c @@ -22,8 +22,8 @@ LOG_MODULE_REGISTER(mpsl_radio_pin_debug, CONFIG_MPSL_LOG_LEVEL); static int m_ppi_config(void) { nrfx_gpiote_t *gpiote = &GPIOTE_NRFX_INST_BY_NODE(GPIOTE_NODE); - uint32_t rad_domain = nrfx_gppi_domain_id_get(NRF_DPPIC10); - uint32_t dst_domain = nrfx_gppi_domain_id_get(gpiote->p_reg); + uint32_t rad_domain = nrfx_gppi_domain_id_get((uint32_t)NRF_DPPIC10); + uint32_t dst_domain = nrfx_gppi_domain_id_get((uint32_t)gpiote->p_reg); nrfx_gppi_resource_t rad_resource; nrfx_gppi_handle_t handle; uint32_t tep[4]; @@ -43,7 +43,7 @@ static int m_ppi_config(void) CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN); tep[3] = nrfx_gpiote_clr_task_address_get(gpiote, CONFIG_MPSL_PIN_DEBUG_RADIO_ADDRESS_AND_END_PIN); - rad_resource.rad_domain = nrfx_gppi_domain_id_get(NRF_DPPIC10); + rad_resource.domain_id = nrfx_gppi_domain_id_get((uint32_t)NRF_DPPIC10); for (size_t i = 0; i < ARRAY_SIZE(pub_ch); i++) { rad_resource.channel = pub_ch[i]; @@ -51,7 +51,7 @@ static int m_ppi_config(void) if (err < 0) { return err; } - nrfx_gppi_ep_attach(handle, tep[i]); + nrfx_gppi_ep_attach(tep[i], handle); /* Channel in radio domain is not enabled by this function. */ nrfx_gppi_conn_enable(handle); } From 576c54af9328497524c6232f425830c5c24dddd9 Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Fri, 28 Nov 2025 08:41:15 +0100 Subject: [PATCH 046/155] doc: Improved the documentation related to Matter code-gen. The way of handling data model related code changed in Matter a lot. Added advanced migration guide and updated the instruction for creating cluster extension. Signed-off-by: Kamil Kasperczyk --- doc/nrf/links.txt | 1 + .../getting_started/custom_clusters.rst | 152 +++++++++++++++++- .../migration/migration_guide_3.2.rst | 71 +++++++- .../releases/release-notes-changelog.rst | 3 +- 4 files changed, 215 insertions(+), 12 deletions(-) diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index 0beefedab75c..bae10620a66b 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -194,6 +194,7 @@ .. _`Generate partition script`: https://github.com/nrfconnect/sdk-connectedhomeip/blob/bf45da8a28/scripts/tools/nrfconnect/nrfconnect_generate_partition.py .. _`Matter nRF Connect scripts`: https://github.com/nrfconnect/sdk-connectedhomeip/tree/bf45da8a28/scripts/tools/nrfconnect .. _`Matter nRF Connect Kconfig`: https://github.com/nrfconnect/sdk-connectedhomeip/blob/bf45da8a28/config/nrfconnect/chip-module/Kconfig +.. _`Matter Clusters Code-Driven support`: https://github.com/nrfconnect/sdk-connectedhomeip/blob/bf45da8a28/src/app/common/templates/config-data.yaml .. _`bt_nus_service.cpp`: https://github.com/nrfconnect/sdk-nrf/blob/main/samples/matter/common/src/bt_nus/bt_nus_service.cpp .. _`bt_nus_service.h`: https://github.com/nrfconnect/sdk-nrf/blob/main/samples/matter/common/src/bt_nus/bt_nus_service.h diff --git a/doc/nrf/protocols/matter/getting_started/custom_clusters.rst b/doc/nrf/protocols/matter/getting_started/custom_clusters.rst index f0abcc2a6eb9..f0d0b558260c 100644 --- a/doc/nrf/protocols/matter/getting_started/custom_clusters.rst +++ b/doc/nrf/protocols/matter/getting_started/custom_clusters.rst @@ -798,19 +798,159 @@ Then, you need to implement the following command in the application code: // TODO: Implement the plugin server init callback. } -The same applies to the extended commands. +Implement the extension handling in the application code +******************************************************** -.. note:: +The way you handle cluster extensions depends on whether the cluster that you want to extend is implemented using the code-driven approach or with ZAP-generated code. + +If the cluster is implemented using the code-driven approach, you must inherit from this cluster delegate class and implement the methods to handle the customized part. +Then, you must unregister the original cluster delegate and register the customized one. +For example, if you want to extend the ``BasicInformation`` cluster, you need to implement it in the application code as follows: + +* Inherit from the ``BasicInformationCluster`` class and override the methods to handle the customized part. + + .. code-block:: C++ + + #include + #include + #include + + class BasicInformationExtension : public chip::app::Clusters::BasicInformationCluster { + public: + BasicInformationExtension() {} + + /* Overrides the default BasicInformationCluster implementation. */ + chip::app::DataModel::ActionReturnStatus + ReadAttribute(const chip::app::DataModel::ReadAttributeRequest &request, + chip::app::AttributeValueEncoder &encoder) override; + + CHIP_ERROR Attributes(const chip::app::ConcreteClusterPath &path, + chip::ReadOnlyBufferBuilder &builder) override; + + CHIP_ERROR AcceptedCommands(const chip::app::ConcreteClusterPath &path, + chip::ReadOnlyBufferBuilder &builder) override; + + CHIP_ERROR GeneratedCommands(const chip::app::ConcreteClusterPath &path, + chip::ReadOnlyBufferBuilder &builder) override; + + CHIP_ERROR Attributes(const chip::app::ConcreteClusterPath &path, + chip::ReadOnlyBufferBuilder &builder) override; + + chip::app::DataModel::ActionReturnStatus SetExtendedAttribute(bool newExtendedAttribute); + + private: + bool mExtendedAttribute; + }; + +* Implement the body of overridden methods to handle the custom attributes, commands and events. + + .. code-block:: C++ + + #include + #include + #include + + using namespace chip; + using namespace chip::app; + + constexpr AttributeId kExtendedAttributeId = 0x17; + + constexpr DataModel::AttributeEntry kExtraAttributeMetadata[] = { + { kExtendedAttributeId, + {} /* qualities */, + Access::Privilege::kView /* readPriv */, + std::nullopt /* writePriv */ }, + }; + + DataModel::ActionReturnStatus BasicInformationExtension::SetExtendedAttribute(bool newExtendedAttribute) + { + mExtendedAttribute = newExtendedAttribute; + return CHIP_NO_ERROR; + } + + DataModel::ActionReturnStatus BasicInformationExtension::ReadAttribute(const DataModel::ReadAttributeRequest &request, + AttributeValueEncoder &encoder) + { + switch (request.path.mAttributeId) { + case kExtendedAttributeId: + return encoder.Encode(mExtendedAttribute); + default: + return chip::app::Clusters::BasicInformationCluster::ReadAttribute(request, encoder); + } + } + + DataModel::ActionReturnStatus BasicInformationExtension::WriteAttribute(const DataModel::WriteAttributeRequest &request, + AttributeValueDecoder &decoder) + { + switch (request.path.mAttributeId) { + case kExtendedAttributeId: + bool newExtendedAttribute; + ReturnErrorOnFailure(decoder.Decode(newExtendedAttribute)); + return NotifyAttributeChangedIfSuccess(request.path.mAttributeId, SetExtendedAttribute(newExtendedAttribute)); + default: + return chip::app::Clusters::BasicInformationCluster::WriteAttribute(request, decoder); + } + } + + CHIP_ERROR BasicInformationExtension::Attributes(const ConcreteClusterPath &path, + ReadOnlyBufferBuilder &builder) + { + ReturnErrorOnFailure(builder.ReferenceExisting(kExtraAttributeMetadata)); + + return chip::app::Clusters::BasicInformationCluster::Attributes(path, builder); + } - Before the |NCS| v3.2.0, the extended commands callback were handled by the ``emberAf...`` functions. - - For example, if you want to extend the ``BasicInformation`` cluster with the ``ExtendedCommand`` command, you need to implement it in the application code as follows: + CHIP_ERROR BasicInformationExtension::AcceptedCommands(const ConcreteClusterPath &path, + ReadOnlyBufferBuilder &builder) + { + /* The BasicInformationCluster does not have any commands, so it is not necessary to call the implementation of the base class. */ + static constexpr DataModel::AcceptedCommandEntry kAcceptedCommands[] = { + Clusters::BasicInformation::Commands::ExtendedCommand::kMetadataEntry + }; + return builder.ReferenceExisting(kAcceptedCommands); + } + + std::optional + BasicInformationExtension::InvokeCommand(const DataModel::InvokeRequest &request, chip::TLV::TLVReader &input_arguments, + CommandHandler *handler) + { + switch (request.path.mCommandId) { + case Clusters::BasicInformation::Commands::ExtendedCommand::Id: { + /* Implement the command handling logic here */ + } + default: + /* The BasicInformationCluster does not have any commands, so it is not necessary to call the implementation of the base class. */ + return Protocols::InteractionModel::Status::UnsupportedCommand; + } + } + +* Unregister the original cluster delegate and register the customized one. + + .. code-block:: C++ + + #include + + /* Replaces the registered BasicInformation cluster with a customized one that adds random number handling. */ + auto ®istry = chip::app::CodegenDataModelProvider::Instance().Registry(); + + ServerClusterInterface *interface = + registry.Get({ kRootEndpointId, chip::app::Clusters::BasicInformation::Id }); + + VerifyOrDie(interface != nullptr); + + registry.Unregister(interface); + static RegisteredServerCluster sBasicInformationExtension; + + VerifyOrDie(registry.Register(sBasicInformationExtension.Registration()) == CHIP_NO_ERROR); + +If the cluster is implemented with ZAP-generated code, you must implement the required extension callbacks by defining the appropriate ``emberAf...Callback`` functions, as described in the code examples and in the cluster XML. +For example, if you want to extend the ``LevelControl`` cluster with the ``ExtendedCommand`` command, you need to implement it in the application code as follows: .. code-block:: c #include - bool emberAfBasicInformationClusterBasicInformationExtendedCommandCallback(chip::app::CommandHandler *commandObj, const chip::app::ConcreteCommandPath &commandPath, + bool emberAfLevelControlClusterExtendedCommandCallback(chip::app::CommandHandler *commandObj, const chip::app::ConcreteCommandPath &commandPath, const chip::app::Clusters::BasicInformation::Commands::ExtendedCommand::DecodableType &commandData) { // TODO: Implement the command. diff --git a/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst b/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst index 78f53aedacab..94dbfb8d7c81 100644 --- a/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst +++ b/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst @@ -104,11 +104,72 @@ Matter To build your custom board with Wi-Fi support, set both the :kconfig:option:`CONFIG_CHIP_WIFI` and :kconfig:option:`CONFIG_WIFI_NRF70` Kconfig options to ``y``. - * The :file:`zap-generated` directory now includes the :file:`CodeDrivenCallback.h` and :file:`CodeDrivenInitShutdown.cpp` files. - The Matter build system gradually moves to the new approach of data model handling and does not auto-generate some bits of a code responsible for command handling anymore. - Invoking the ``west zap-generate`` command removes command handler implementations from the existing :file:`IMClusterCommandHandler.cpp` file. - To fix this, you must now manually create the :file:`CodeDrivenCallback.h` and :file:`CodeDrivenInitShutdown.cpp` files, and implement the ``MatterClusterServerInitCallback`` and ``MatterClusterServerShutdownCallback`` callbacks to handle server initialization, shutdown, and Matter cluster commands. - Ensure that these callbacks contain your application's command handling logic as required. + * The Matter build system is transitioning to a code-driven approach for Data Model and Cluster configuration handling. + This approach assumes gradual replacement of the configuration based on the ZAP files and the ZAP-generated code, and handling the configuration in the source code. + This change has the following impacts: + + * The :file:`zap-generated` directory now includes the :file:`CodeDrivenCallback.h` and :file:`CodeDrivenInitShutdown.cpp` files. + Invoking the ``west zap-generate`` command removes command handler implementations from the existing :file:`IMClusterCommandHandler.cpp` file. + To fix this, you must now manually create the :file:`CodeDrivenCallback.h` and :file:`CodeDrivenInitShutdown.cpp` files, and implement the ``MatterClusterServerInitCallback`` and ``MatterClusterServerShutdownCallback`` callbacks to handle server initialization, shutdown, and Matter cluster commands. + Ensure that these callbacks contain your application's command handling logic. + * The code-driven approach is not yet fully implemented for all available clusters, but the coverage will be increasing and it is used for the newly created clusters. + The following clusters are already ported using the code-driven approach: + + * Access Control + * Administrator Commissioning + * Basic Information + * Binding + * Boolean State + * Descriptor + * Diagnostic Logs + * Ethernet Network Diagnostics + * Fixed Label + * General Commissioning + * General Diagnostics + * Group Key Management + * Groupcast + * Identify + * Localization Configuration + * OTA Software Update Provider + * Operational Credentials + * Push AV Stream Transport + * Software Diagnostics + * Time Format Localization + * User Label + * Wi-Fi Network Diagnostics + + For the full list of clusters and their migration status, see the `Matter Clusters Code-Driven support`_ file. + + * By default, all the mandatory attributes are enabled for the cluster. + To enable an optional attribute or set an optional feature in the feature map, you must do that in the source code by calling dedicated methods. + For example, to enable the Positioning feature and the ``CountdownTime`` optional attribute for the Closure Control cluster, perform the following operations: + + * Implement a delegate class for the Closure Control cluster. + See the :file:`samples/matter/closure/src/closure_control_endpoint.h` file for an example. + * Enable the attribute and set the feature on cluster initialization. + See the ``ClosureControlEndpoint::Init`` function in the :file:`samples/matter/closure/src/closure_control_endpoint.cpp` file for an example. + + * To enable an optional cluster, you must register it in the source code by calling a dedicated method. + For example, to enable the Identify cluster, implement the following code: + + .. code-block:: C++ + + #include + #include + + chip::app::RegisteredServerCluster mIdentifyCluster; + chip::app::CodegenDataModelProvider::Instance().Registry().Register(mIdentifyCluster.Registration()); + + * To enable a cluster extension for the cluster that is already implemented using the code-driven approach, you must inherit from this cluster delegate class and implement the methods to handle the customized part. + You also have to unregister the original cluster delegate and register the customized one. + For example, to enable a cluster extension for the Basic Information cluster, perform the following operations: + + * Inherit from the ``BasicInformationCluster`` class and override the methods to handle the customized part. + See the :file:`samples/matter/manufacturer_specific/src/basic_information_extension.h` file for an example. + * Implement the body of overridden methods to handle the custom attributes, commands, and events. + See the :file:`samples/matter/manufacturer_specific/src/basic_information_extension.cpp` file for an example. + * Unregister the original cluster delegate and register the customized one. + See the ``AppTask::StartApp`` function in the :file:`samples/matter/manufacturer_specific/src/app_task.cpp` file for an example. * :ref:`matter_lock_sample` sample: diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index b332588b1842..574f0b479715 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -259,6 +259,7 @@ The Matter fork in the |NCS| (``sdk-connectedhomeip``) contains all commits from * Added: * Support for the following new device types: + * Irrigation System * Soil Sensor * Closure @@ -284,10 +285,10 @@ The Matter fork in the |NCS| (``sdk-connectedhomeip``) contains all commits from For example, to enable a specific cluster or its attribute, the new model requires calling a dedicated delegate and registering the cluster in a source code. The code-driven approach is not yet fully implemented for all the available clusters, but the coverage will be increasing and it is used for the newly created clusters. The new model is meant to be backward compatible with the previous configuration based on the ZAP files and the ZAP-generated code, until the code-driven approach is fully implemented for all the available clusters. + See the `Migration guide for nRF Connect SDK v3.2.0`_ for more information. * The :ref:`ug_matter_gs_tools_matter_west_commands_sync` command to synchronize the ZAP and :file:`zcl.json` files after updating the ZAP tool version. * The check to all :ref:`ug_matter_gs_tools_matter_west_commands_zap_tool` commands that verify whether ZAP tool sandbox permissions are correctly set. In case of detecting incorrect permissions, the command will prompt the user to accept automatically updating the permissions to required ones. - * Updated: * The :ref:`ug_matter_gs_tools_matter_west_commands_append` command to accept ``--clusters`` argument instead of ``new_clusters`` argument. From a45a698584247af3da936a481a5d4ae56bbd1d81 Mon Sep 17 00:00:00 2001 From: Grzegorz Ferenc Date: Thu, 27 Nov 2025 11:19:00 +0100 Subject: [PATCH 047/155] doc: security: update for v3.2.0 Updated security component versions for v3.2.0. Updated other security pages with information for v3.2.0. Signed-off-by: Grzegorz Ferenc --- doc/_zoomin/ncs.tags.yml | 6 +- .../device_guides/nrf54l/cryptography.rst | 3 +- doc/nrf/links.txt | 7 +- doc/nrf/security.rst | 10 +- doc/nrf/security/ap_protect.rst | 10 + .../crypto/crypto_supported_features.rst | 173 +++++++++--------- .../security/psa_certified_api_overview.rst | 7 +- 7 files changed, 114 insertions(+), 102 deletions(-) diff --git a/doc/_zoomin/ncs.tags.yml b/doc/_zoomin/ncs.tags.yml index d8f5e8799e84..92b300eb326f 100644 --- a/doc/_zoomin/ncs.tags.yml +++ b/doc/_zoomin/ncs.tags.yml @@ -282,9 +282,9 @@ mapping_topics: "thingy91", "thingy91x", "thingy53", "kconfig"] - nrf/security/ap_protect.html: ["nrf91-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf9160", "nrf9161", "nrf9151", "nrf9131", - "nrf54h20", "nrf54l15", "nrf5340", "nrf52840", "nrf52833", - "nrf52832", "nrf52820", "nrf52811", "nrf52810", "nrf52805", - "kconfig"] + "nrf54h20", "nrf54l15", "nrf54lm20a", "nrf54lv10a", "nrf5340", + "nrf52840", "nrf52833", "nrf52832", "nrf52820", "nrf52811", + "nrf52810", "nrf52805", "kconfig"] - nrf/security/secure_storage.html: ["nrf91-series", "nrf54-series", "nrf53-series", "nrf52-series", "nrf9160", "nrf9161", "nrf9151", "nrf9131", "nrf54l15", "nrf54l10", "nrf54lm20a", "nrf54lv10a", diff --git a/doc/nrf/app_dev/device_guides/nrf54l/cryptography.rst b/doc/nrf/app_dev/device_guides/nrf54l/cryptography.rst index ecedbbcfaf31..b0b205bf5f33 100644 --- a/doc/nrf/app_dev/device_guides/nrf54l/cryptography.rst +++ b/doc/nrf/app_dev/device_guides/nrf54l/cryptography.rst @@ -287,7 +287,7 @@ For each key type, the table lists the supported algorithms and indicates which - No - Yes - Yes - * - ECC secp256r1 key pair (ECDSA and ECDH usage) [4]_ + * - ECC secp256r1 key pair (ECDSA and ECDH usage) - | ``key_type``: ``PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)`` | | ``key_bits``: 256 @@ -346,7 +346,6 @@ For each key type, the table lists the supported algorithms and indicates which .. [1] Store each key with only one algorithm to follow PSA Crypto best practices. .. [2] Keys with the Encrypted usage scheme (``CRACEN_KMU_KEY_USAGE_SCHEME_ENCRYPTED``) will require two additional KMU slots to store the nonce and the authentication tag. .. [3] 192-bit key size is not supported on nRF54LM20A. -.. [4] ECDH not supported for key derivation. .. _ug_nrf54l_crypto_kmu_storing_keys: diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index bae10620a66b..6e1921a2829a 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -276,12 +276,11 @@ .. _`Key identifiers`: https://arm-software.github.io/psa-api/crypto/1.1/api/keys/ids.html#key-identifiers .. _`Key management functions`: https://arm-software.github.io/psa-api/crypto/1.1/api/keys/management.html .. _`Keystore interface`: https://arm-software.github.io/psa-api/crypto/1.1/overview/goals.html#a-keystore-interface -.. _`PSA Cryptography API 1.0.1`: https://armmbed.github.io/mbed-crypto/1.0.1/html/index.html -.. _`PSA Certified Crypto API 1.0.0`: https://arm-software.github.io/psa-api/crypto/1.0/IHI0086-PSA_Cryptography_API-1.0.0.pdf -.. _`PSA Certified Crypto API 1.3.1`: https://arm-software.github.io/psa-api/crypto/1.3/ .. _`PSA functions for key management`: https://arm-software.github.io/psa-api/crypto/1.1/api/keys/management.html .. _`PSA_KEY_USAGE_EXPORT policy`: https://arm-software.github.io/psa-api/crypto/1.3/api/keys/policy.html#c.PSA_KEY_USAGE_EXPORT +.. _`PSA Certified Crypto API 1.3.1`: https://arm-software.github.io/psa-api/crypto/1.3/ + .. _`PSA Certified Secure Storage API`: https://arm-software.github.io/psa-api/storage/ .. _`PSA Certified Secure Storage API 1.0`: https://arm-software.github.io/psa-api/storage/1.0/ @@ -956,6 +955,8 @@ .. _`AP-Protect for nRF9151`: https://docs.nordicsemi.com/bundle/ps_nrf9151/page/dif.html#ariaid-title3 .. _`AP-Protect for nRF9161`: https://docs.nordicsemi.com/bundle/ps_nrf9161/page/dif.html#ariaid-title3 .. _`Debugger access protection for nRF9160`: https://docs.nordicsemi.com/bundle/ps_nrf9160/page/dif.html#ariaid-title2 +.. _`AP-Protect for nRF54LV10A`: https://docs.nordicsemi.com/bundle/ps_nrf54LV10A/page/ctrl-ap.html +.. _`AP-Protect for nRF54LM20A`: https://docs.nordicsemi.com/bundle/ps_nrf54LM20A/page/ctrl-ap.html .. _`AP-Protect for nRF54L15`: https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/ctrl-ap.html .. _`AP-Protect for nRF5340`: https://docs.nordicsemi.com/bundle/ps_nrf5340/page/debugandtrace.html#ariaid-title9 .. _`AP-Protect for nRF52840`: diff --git a/doc/nrf/security.rst b/doc/nrf/security.rst index 65a4779c5e9f..fd446a8180a1 100644 --- a/doc/nrf/security.rst +++ b/doc/nrf/security.rst @@ -20,9 +20,9 @@ The |NCS| |release| allows you to develop applications with the following versio - IronSide Secure Element version - Mbed TLS version * - |release| - - v2.1.2 + - v2.2.0 - v23.0.2+17 - - 3.6.4 + - 3.6.5 .. security_components_ver_table_end @@ -49,7 +49,11 @@ Expand the following section to see the table listing versions of different secu * - Upcoming release (currently on the ``main`` branch of `sdk-nrf`_) - v2.2.0 - v23.0.2+17 - - 3.6.4 + - 3.6.5 + * - v3.2.0 + - v2.2.0 + - v23.0.2+17 + - 3.6.5 * - v3.1.0, v3.1.1 - v2.1.2 - v20.0.0+1 diff --git a/doc/nrf/security/ap_protect.rst b/doc/nrf/security/ap_protect.rst index c8c383b029a6..522f62813a41 100644 --- a/doc/nrf/security/ap_protect.rst +++ b/doc/nrf/security/ap_protect.rst @@ -90,6 +90,16 @@ See the related hardware documentation for more information about which implemen - n/a - n/a - See :ref:`UICR.APPROTECT `. + * - nRF54LV10A + - n/a + - ✔ + - `AP-Protect for nRF54LV10A`_ + - Also :ref:`supports Secure AP-Protect ` + * - nRF54LM20A + - n/a + - ✔ + - `AP-Protect for nRF54LM20A`_ + - Also :ref:`supports Secure AP-Protect ` * - nRF54L15 - n/a - ✔ diff --git a/doc/nrf/security/crypto/crypto_supported_features.rst b/doc/nrf/security/crypto/crypto_supported_features.rst index dd73509d6afd..4ec2bfaa0cf2 100644 --- a/doc/nrf/security/crypto/crypto_supported_features.rst +++ b/doc/nrf/security/crypto/crypto_supported_features.rst @@ -737,8 +737,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - AES - :kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_AES` - Supported @@ -989,8 +989,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - AES - :kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_AES` - Supported @@ -2174,8 +2174,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - ECB no padding - :kconfig:option:`CONFIG_PSA_WANT_ALG_ECB_NO_PADDING` - Supported @@ -2188,14 +2188,14 @@ The options are grouped by Series and drivers available for the device Series, a - Supported - Supported - Supported - - Experimental (with exceptions, see note) + - Experimental - Experimental * - CBC PKCS#7 padding - :kconfig:option:`CONFIG_PSA_WANT_ALG_CBC_PKCS7` - Supported - Supported - Supported - - Experimental (with exceptions, see note) + - Experimental - Experimental * - CTR - :kconfig:option:`CONFIG_PSA_WANT_ALG_CTR` @@ -2221,15 +2221,11 @@ The options are grouped by Series and drivers available for the device Series, a .. note:: - The following limitations apply for nRF54LM20 when using the CRACEN driver: + The following limitations apply for nRF54LM20A and nRF54LV10A when using the CRACEN driver: * 192-bit keys are not supported. See also :ref:`ug_crypto_supported_features_aes_key_sizes`. - * For CBC no padding and CBC PKCS#7 padding cipher modes: - - * Multi-part encrypt and decrypt APIs are not supported. - .. tab:: nrf_oberon .. list-table:: Cipher mode support per device (nrf_oberon driver) - nRF54L Series @@ -2241,8 +2237,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - ECB no padding - :kconfig:option:`CONFIG_PSA_WANT_ALG_ECB_NO_PADDING` - Supported @@ -2670,8 +2666,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - ECDH - :kconfig:option:`CONFIG_PSA_WANT_ALG_ECDH` - Supported @@ -2691,8 +2687,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - ECDH - :kconfig:option:`CONFIG_PSA_WANT_ALG_ECDH` - Supported @@ -2934,8 +2930,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - ML-KEM - :kconfig:option:`CONFIG_PSA_WANT_ALG_ML_KEM` - Experimental @@ -3240,8 +3236,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - HKDF - :kconfig:option:`CONFIG_PSA_WANT_ALG_HKDF` - Supported @@ -3324,8 +3320,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - HKDF - :kconfig:option:`CONFIG_PSA_WANT_ALG_HKDF` - Supported @@ -3762,15 +3758,15 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - CMAC - :kconfig:option:`CONFIG_PSA_WANT_ALG_CMAC` - Supported - Supported - Supported - Experimental (with exceptions, see note) - - Experimental + - Experimental (with exceptions, see note) * - HMAC - :kconfig:option:`CONFIG_PSA_WANT_ALG_HMAC` - Supported @@ -3781,7 +3777,7 @@ The options are grouped by Series and drivers available for the device Series, a .. note:: - The following limitations apply for nRF54LM20 when using the CRACEN driver: + The following limitations apply for nRF54LM20A and nRF54LV10A when using the CRACEN driver: * 192-bit keys are not supported. See also :ref:`ug_crypto_supported_features_aes_key_sizes`. @@ -3797,8 +3793,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - CMAC - :kconfig:option:`CONFIG_PSA_WANT_ALG_CMAC` - Supported @@ -3958,7 +3954,7 @@ Based on this setting, Oberon PSA Crypto selects the most appropriate driver for * - Kconfig option - Supported MAC algorithms * - :kconfig:option:`CONFIG_PSA_USE_CRACEN_MAC_DRIVER` - - | :kconfig:option:`CONFIG_PSA_WANT_ALG_CMAC` + - | :kconfig:option:`CONFIG_PSA_WANT_ALG_CMAC` (all AES key sizes except the 192-bit key size on nRF54LM20A and nRF54LV10A) | :kconfig:option:`CONFIG_PSA_WANT_ALG_HMAC` .. tab:: nrf_oberon @@ -4185,8 +4181,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - CCM - :kconfig:option:`CONFIG_PSA_WANT_ALG_CCM` - Supported @@ -4219,7 +4215,7 @@ The options are grouped by Series and drivers available for the device Series, a .. note:: * CRACEN only supports a 96-bit IV for AES GCM. - * The following limitations apply for nRF54LM20 when using the CRACEN driver: + * The following limitations apply for nRF54LM20A when using the CRACEN driver: * 192-bit keys are not supported. See also :ref:`ug_crypto_supported_features_aes_key_sizes`. @@ -4232,7 +4228,10 @@ The options are grouped by Series and drivers available for the device Series, a * Multi-part encrypt and decrypt APIs are not supported. - * The following limitations apply for nRF54LV10 when using the CRACEN driver: + * The following limitations apply for nRF54LV10A when using the CRACEN driver: + + * 192-bit keys are not supported. + See also :ref:`ug_crypto_supported_features_aes_key_sizes`. * CCM cipher mode: @@ -4249,8 +4248,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - CCM - :kconfig:option:`CONFIG_PSA_WANT_ALG_CCM` - Supported @@ -4450,7 +4449,7 @@ Based on this setting, Oberon PSA Crypto selects the most appropriate driver for - Supported AEAD algorithms * - :kconfig:option:`CONFIG_PSA_USE_CRACEN_AEAD_DRIVER` - | :kconfig:option:`CONFIG_PSA_WANT_ALG_CCM` - | :kconfig:option:`CONFIG_PSA_WANT_ALG_GCM` + | :kconfig:option:`CONFIG_PSA_WANT_ALG_GCM` (all AES key sizes except the 192-bit key size on nRF54LM20A and nRF54LV10A) | :kconfig:option:`CONFIG_PSA_WANT_ALG_CHACHA20_POLY1305` .. tab:: nrf_oberon @@ -4851,8 +4850,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - ECDSA - :kconfig:option:`CONFIG_PSA_WANT_ALG_ECDSA` - Supported @@ -4963,8 +4962,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - ECDSA - :kconfig:option:`CONFIG_PSA_WANT_ALG_ECDSA` - Supported @@ -5593,8 +5592,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - RSA OAEP - :kconfig:option:`CONFIG_PSA_WANT_ALG_RSA_OAEP` - Supported @@ -5621,8 +5620,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - RSA OAEP - :kconfig:option:`CONFIG_PSA_WANT_ALG_RSA_OAEP` - Supported @@ -6193,8 +6192,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - BrainpoolP224r1 - :kconfig:option:`CONFIG_PSA_WANT_ECC_BRAINPOOL_P_R1_224` - Supported @@ -6312,8 +6311,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - BrainpoolP224r1 - :kconfig:option:`CONFIG_PSA_WANT_ECC_BRAINPOOL_P_R1_224` - -- @@ -6985,8 +6984,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - RNG support - :kconfig:option:`CONFIG_PSA_WANT_GENERATE_RANDOM` - Supported @@ -7020,8 +7019,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - RNG support - :kconfig:option:`CONFIG_PSA_WANT_GENERATE_RANDOM` - Supported @@ -7594,8 +7593,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - SHA-1 (weak) - :kconfig:option:`CONFIG_PSA_WANT_ALG_SHA_1` - Supported @@ -7706,8 +7705,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - SHA-1 (weak) - :kconfig:option:`CONFIG_PSA_WANT_ALG_SHA_1` - Supported @@ -8329,8 +8328,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - EC J-PAKE - :kconfig:option:`CONFIG_PSA_WANT_ALG_JPAKE` - Supported @@ -8385,8 +8384,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - EC J-PAKE - :kconfig:option:`CONFIG_PSA_WANT_ALG_JPAKE` - Supported @@ -8742,8 +8741,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - Import - :kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT` - Supported @@ -8784,8 +8783,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - Import - :kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT` - Supported @@ -8988,8 +8987,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - Import - :kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_SRP_KEY_PAIR_IMPORT` - Supported @@ -9030,8 +9029,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - Import - :kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_SRP_KEY_PAIR_IMPORT` - Supported @@ -9232,8 +9231,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - Import - :kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_SPAKE2P_KEY_PAIR_IMPORT` - Supported @@ -9274,8 +9273,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - Import - :kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_SPAKE2P_KEY_PAIR_IMPORT` - Supported @@ -9520,8 +9519,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - Generate - :kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE` - Supported @@ -9562,8 +9561,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - Generate - :kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE` - Supported @@ -9839,8 +9838,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - 128 bits - :kconfig:option:`CONFIG_PSA_WANT_AES_KEY_SIZE_128` - Supported @@ -9874,8 +9873,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - 128 bits - :kconfig:option:`CONFIG_PSA_WANT_AES_KEY_SIZE_128` - Supported @@ -10147,8 +10146,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - 1024 bits - :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_1024` - -- @@ -10210,8 +10209,8 @@ The options are grouped by Series and drivers available for the device Series, a - nRF54L05 - nRF54L10 - nRF54L15 - - nRF54LM20 - - nRF54LV10 + - nRF54LM20A + - nRF54LV10A * - 1024 bits - :kconfig:option:`CONFIG_PSA_WANT_RSA_KEY_SIZE_1024` - Supported diff --git a/doc/nrf/security/psa_certified_api_overview.rst b/doc/nrf/security/psa_certified_api_overview.rst index 77fa5571c2c9..18a0f5ecad2c 100644 --- a/doc/nrf/security/psa_certified_api_overview.rst +++ b/doc/nrf/security/psa_certified_api_overview.rst @@ -62,8 +62,7 @@ The following table provides an overview of the PSA Certified APIs support statu * - `PSA Certified Crypto API`_ - Supported - | `PSA Certified Crypto API 1.3.1`_ for IronSide Secure Element firmware for nRF54H20 - | `PSA Certified Crypto API 1.3.1`_ for :ref:`nRF54L cryptography ` and PSA Crypto API builds without TF-M - | `PSA Certified Crypto API 1.0.0`_ for builds with TF-M + | `PSA Certified Crypto API 1.3.1`_ for :ref:`nRF54L cryptography ` and PSA Crypto API builds with and without TF-M * - `PSA Certified Attestation API`_ - Supported - `PSA Certified Attestation API 1.0`_ (not supported for IronSide Secure Element firmware for nRF54H20) @@ -116,7 +115,7 @@ The PSA Crypto API has the following implementations in the |NCS|: * :ref:`TF-M Crypto Service `- which provides PSA Crypto API access through TF-M for applications that require enhanced security. * :ref:`IronSide Secure Element ` - which provides PSA Crypto API interface for the :ref:`Secure Domain of nRF54H20 `. -Depending on the implementation you are using, the |NCS| build system uses different versions of the PSA Crypto API. +Depending on the implementation you are using, the |NCS| build system can use different versions of the PSA Crypto API. .. psa_crypto_support_tfm_build_start @@ -129,7 +128,7 @@ Depending on the implementation you are using, the |NCS| build system uses diffe * - :ref:`Oberon PSA Crypto ` - `v1.3.1 `_ * - :ref:`TF-M Crypto Service ` - - `v1.0.0 `_ + - `v1.3.1 `_ * - :ref:`IronSide Secure Element ` - `v1.3.1 `_ From 8f724358ef9b88ec8386d13757bf980b2e8be957 Mon Sep 17 00:00:00 2001 From: Bartlomiej Buczek Date: Tue, 18 Nov 2025 23:00:56 +0100 Subject: [PATCH 048/155] tests: benchmarks: Run idle_adc tests on nrf54h ppr. Adapt idle_adc test to be run on nrf54h20 cpuppr target. Signed-off-by: Bartlomiej Buczek --- .../multicore/idle_adc/CMakeLists.txt | 5 ++ tests/benchmarks/multicore/idle_adc/Kconfig | 10 +++ .../multicore/idle_adc/Kconfig.sysbuild | 6 ++ .../boards/nrf54h20dk_nrf54h20_cpuppr.conf | 2 + .../boards/nrf54h20dk_nrf54h20_cpuppr.overlay | 78 +++++++++++++++++++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 21 +++++ .../idle_adc/sysbuild/vpr_launcher/prj.conf | 14 ++++ .../multicore/idle_adc/testcase.yaml | 15 ++++ 8 files changed, 151 insertions(+) create mode 100644 tests/benchmarks/multicore/idle_adc/Kconfig create mode 100644 tests/benchmarks/multicore/idle_adc/boards/nrf54h20dk_nrf54h20_cpuppr.conf create mode 100644 tests/benchmarks/multicore/idle_adc/boards/nrf54h20dk_nrf54h20_cpuppr.overlay create mode 100644 tests/benchmarks/multicore/idle_adc/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/benchmarks/multicore/idle_adc/sysbuild/vpr_launcher/prj.conf diff --git a/tests/benchmarks/multicore/idle_adc/CMakeLists.txt b/tests/benchmarks/multicore/idle_adc/CMakeLists.txt index 0100ac93f32f..d15347259150 100644 --- a/tests/benchmarks/multicore/idle_adc/CMakeLists.txt +++ b/tests/benchmarks/multicore/idle_adc/CMakeLists.txt @@ -17,3 +17,8 @@ endif() project(idle_adc) target_sources(app PRIVATE src/main.c) + +if(CONFIG_SOC_NRF54H20_CPUPPR) + message(DEBUG "Power Mode handler for RISC V is included.") + target_sources(app PRIVATE ${ZEPHYR_NRF_MODULE_DIR}/tests/benchmarks/multicore/common/power_off.c) +endif() diff --git a/tests/benchmarks/multicore/idle_adc/Kconfig b/tests/benchmarks/multicore/idle_adc/Kconfig new file mode 100644 index 000000000000..19cf124251ce --- /dev/null +++ b/tests/benchmarks/multicore/idle_adc/Kconfig @@ -0,0 +1,10 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +config SOC_NRF54H20_CPUPPR + select HAS_PM + select HAS_POWEROFF + +source "Kconfig.zephyr" diff --git a/tests/benchmarks/multicore/idle_adc/Kconfig.sysbuild b/tests/benchmarks/multicore/idle_adc/Kconfig.sysbuild index 7bddf157b0dc..582707d921cd 100644 --- a/tests/benchmarks/multicore/idle_adc/Kconfig.sysbuild +++ b/tests/benchmarks/multicore/idle_adc/Kconfig.sysbuild @@ -19,3 +19,9 @@ config NETCORE_IMAGE_NAME config NETCORE_IMAGE_PATH default "${ZEPHYR_NRF_MODULE_DIR}/tests/benchmarks/power_consumption/common/remote_sleep_forever" if NETCORE_REMOTE_SLEEP_FOREVER + +config SUPPORT_NETCORE + default y if (SOC_NRF54H20_CPUPPR || SOC_NRF54H20_CPUAPP) + +config NETCORE_REMOTE_BOARD_TARGET_CPUCLUSTER + default "cpurad" if (SOC_NRF54H20_CPUPPR || SOC_NRF54H20_CPUAPP) diff --git a/tests/benchmarks/multicore/idle_adc/boards/nrf54h20dk_nrf54h20_cpuppr.conf b/tests/benchmarks/multicore/idle_adc/boards/nrf54h20dk_nrf54h20_cpuppr.conf new file mode 100644 index 000000000000..9083e9e65197 --- /dev/null +++ b/tests/benchmarks/multicore/idle_adc/boards/nrf54h20dk_nrf54h20_cpuppr.conf @@ -0,0 +1,2 @@ +CONFIG_NCS_BOOT_BANNER=n +CONFIG_EARLY_CONSOLE=n diff --git a/tests/benchmarks/multicore/idle_adc/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/tests/benchmarks/multicore/idle_adc/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 000000000000..5cc381c06cb9 --- /dev/null +++ b/tests/benchmarks/multicore/idle_adc/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Required GPIO loopback: P1.02 - P1.03 */ +/ { + aliases { + adc0 = &adc; + sw = &loopback; + led = &led0; + }; + + buttons { + compatible = "gpio-keys"; + + loopback: loopback { + gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led0: led_0 { + gpios = < &gpio9 0x0 0x0 >; + }; + }; + + cpus { + power-states { + wait: wait { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + substate-id = <0>; + min-residency-us = <20000>; + }; + + hibernate: hibernate { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + substate-id = <0>; + min-residency-us = <400000>; + }; + }; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + }; +}; + +&cpu { + cpu-power-states = <&wait &hibernate>; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio9 { + status = "okay"; +}; + +&gpiote130 { + status = "okay"; +}; diff --git a/tests/benchmarks/multicore/idle_adc/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/benchmarks/multicore/idle_adc/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..eb215286fc3a --- /dev/null +++ b/tests/benchmarks/multicore/idle_adc/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + aliases { + /delete-property/ led0; + /delete-property/ led1; + /delete-property/ mcuboot-led0; + }; +}; + +/delete-node/ &led0; +/delete-node/ &led1; + +&adc { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; diff --git a/tests/benchmarks/multicore/idle_adc/sysbuild/vpr_launcher/prj.conf b/tests/benchmarks/multicore/idle_adc/sysbuild/vpr_launcher/prj.conf new file mode 100644 index 000000000000..d9385ec50a42 --- /dev/null +++ b/tests/benchmarks/multicore/idle_adc/sysbuild/vpr_launcher/prj.conf @@ -0,0 +1,14 @@ +CONFIG_PM=y +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y +CONFIG_POWEROFF=y + +CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y + +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_PRINTK=n +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_SERIAL=n diff --git a/tests/benchmarks/multicore/idle_adc/testcase.yaml b/tests/benchmarks/multicore/idle_adc/testcase.yaml index 0ae7b3e2638c..c1165fb32844 100644 --- a/tests/benchmarks/multicore/idle_adc/testcase.yaml +++ b/tests/benchmarks/multicore/idle_adc/testcase.yaml @@ -21,6 +21,21 @@ tests: pytest_root: - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_power_consumption_adc" + benchmarks.multicore.idle_adc.nrf54h20dk_cpuppr.s2ram: + tags: + - ci_build + - ci_tests_benchmarks_multicore + - ppk_power_measure + harness: pytest + platform_allow: + - nrf54h20dk/nrf54h20/cpuppr + integration_platforms: + - nrf54h20dk/nrf54h20/cpuppr + harness_config: + fixture: gpio_loopback + pytest_root: + - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_power_consumption_adc_ppr" + benchmarks.multicore.idle_adc.nrf54h20dk_cpuapp_cpurad.s2ram.mcuboot: tags: - ci_build From e0ae956debae115849e557c15d74990f59121d95 Mon Sep 17 00:00:00 2001 From: Bartosz Miller Date: Mon, 1 Dec 2025 15:41:32 +0100 Subject: [PATCH 049/155] tests: drivers: spi: Add test case for MLTPAN-57 workaround The MLTPAN-57 test case workaround uses fast SPIM (SPIM00) Signed-off-by: Bartosz Miller --- .../boards/nrf54lxx_cpuapp_fast.overlay | 57 +++++++++++ tests/drivers/spi/spim_pan/src/main.c | 95 ++++++++++++++++++- tests/drivers/spi/spim_pan/testcase.yaml | 33 ++++--- 3 files changed, 173 insertions(+), 12 deletions(-) create mode 100644 tests/drivers/spi/spim_pan/boards/nrf54lxx_cpuapp_fast.overlay diff --git a/tests/drivers/spi/spim_pan/boards/nrf54lxx_cpuapp_fast.overlay b/tests/drivers/spi/spim_pan/boards/nrf54lxx_cpuapp_fast.overlay new file mode 100644 index 000000000000..c7451a416ee0 --- /dev/null +++ b/tests/drivers/spi/spim_pan/boards/nrf54lxx_cpuapp_fast.overlay @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&pinctrl { + dut_spi_default: dut_spi_default { + group1 { + psels = , + , + ; + }; + }; + + dut_spi_sleep: dut_spi_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; + +dut_spi_fast: &spi00 { + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&dut_spi_default>; + pinctrl-1 = <&dut_spi_sleep>; + pinctrl-names = "default", "sleep"; + overrun-character = <0x00>; + zephyr,pm-device-runtime-auto; + cs-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = ; + }; +}; + +&gpio2 { + status = "okay"; +}; + +tst_timer: &timer20 { + status = "okay"; +}; + +&dppic20 { + status = "okay"; +}; + +&mx25r64 { + status = "disabled"; +}; diff --git a/tests/drivers/spi/spim_pan/src/main.c b/tests/drivers/spi/spim_pan/src/main.c index 5b042c2a093b..a6653ca71231 100644 --- a/tests/drivers/spi/spim_pan/src/main.c +++ b/tests/drivers/spi/spim_pan/src/main.c @@ -16,10 +16,23 @@ /* SPI MODE 0 */ #define SPI_MODE (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB) + +#if DT_NODE_EXISTS(DT_NODELABEL(dut_spi_fast)) +#define DUT_SPI_NODE DT_NODELABEL(dut_spi_fast) +#define DUT_SPI_FAST 1 +#define TEST_BUFFER_SIZE 4 +#define MX25R64_RDID 0x9F +#define MX25R64_MFG_ID 0xC2 +#define MX25R64_MEM_TYPE 0x28 +#define MX25R64_MEM_DENSITY 0x17 +#define MAX_READ_REPEATS 10 +#else +#define DUT_SPI_NODE DT_NODELABEL(dut_spi) #define TEST_BUFFER_SIZE 64 +#endif static struct spi_dt_spec spim_spec = SPI_DT_SPEC_GET(DT_NODELABEL(dut_spi_dt), SPI_MODE, 0); -NRF_SPIM_Type *spim_reg = (NRF_SPIM_Type *)DT_REG_ADDR(DT_NODELABEL(dut_spi)); +NRF_SPIM_Type *spim_reg = (NRF_SPIM_Type *)DT_REG_ADDR(DUT_SPI_NODE); static nrfx_timer_t test_timer = NRFX_TIMER_INSTANCE(DT_REG_ADDR(DT_NODELABEL(tst_timer))); @@ -71,6 +84,8 @@ static uint32_t configure_test_timer(nrfx_timer_t *timer) ZTEST(spim_pan, test_spim_mltpan_8_workaround) { + Z_TEST_SKIP_IFDEF(DUT_SPI_FAST); + int err; struct spi_buf tx_spi_buf = {.buf = tx_buffer, .len = TEST_BUFFER_SIZE}; @@ -99,6 +114,8 @@ ZTEST(spim_pan, test_spim_mltpan_8_workaround) ZTEST(spim_pan, test_spim_mltpan_55_workaround) { + Z_TEST_SKIP_IFDEF(DUT_SPI_FAST); + int err; uint8_t ppi_channel; @@ -132,6 +149,7 @@ ZTEST(spim_pan, test_spim_mltpan_55_workaround) timer_cc_before = nrfx_timer_capture(&test_timer, NRF_TIMER_CC_CHANNEL0); err = spi_transceive_dt(&spim_spec, &tx_spi_buf_set, &rx_spi_buf_set); + zassert_ok(err, "SPI transceive failed: %d\n", err); timer_cc_after = nrfx_timer_capture(&test_timer, NRF_TIMER_CC_CHANNEL0); TC_PRINT("Timer count before: %u, timer count after: %u\n", timer_cc_before, @@ -142,4 +160,79 @@ ZTEST(spim_pan, test_spim_mltpan_55_workaround) zassert_mem_equal(tx_buffer, rx_buffer, TEST_BUFFER_SIZE - 1, "TX buffer != RX buffer\n"); } +/* + * Reference: MLTPAN-57 + * SPIM00 does not operate as expected + * SPIM00 is the fast SPIM instance + * Requires workaround + */ + +ZTEST(spim_pan, test_spim_mltpan_57_workaround) +{ + Z_TEST_SKIP_IFNDEF(DUT_SPI_FAST); +#if defined(DUT_SPI_FAST) + int err; + + uint8_t ppi_channel; + + uint32_t domain_id; + nrfx_gppi_handle_t gppi_handle; + + uint32_t timer_cc_before, timer_cc_after, tx_amount; + + uint32_t timer_task; + uint32_t spim_event; + + memset(tx_buffer, 0xFF, TEST_BUFFER_SIZE); + tx_buffer[0] = MX25R64_RDID; + + domain_id = nrfx_gppi_domain_id_get((uint32_t)test_timer.p_reg); + ppi_channel = nrfx_gppi_channel_alloc(domain_id); + zassert_true(ppi_channel > 0, "Failed to allocate GPPI channel"); + + timer_task = configure_test_timer(&test_timer); + spim_event = nrf_spim_event_address_get(spim_reg, NRF_SPIM_EVENT_END); + + zassert_ok(nrfx_gppi_conn_alloc(spim_event, timer_task, &gppi_handle), + "Failed to allocate DPPI connection\n"); + nrfx_gppi_conn_enable(gppi_handle); + + struct spi_buf tx_spi_buf = {.buf = tx_buffer, .len = TEST_BUFFER_SIZE}; + struct spi_buf_set tx_spi_buf_set = {.buffers = &tx_spi_buf, .count = 1}; + + struct spi_buf rx_spi_buf = {.buf = rx_buffer, .len = TEST_BUFFER_SIZE}; + struct spi_buf_set rx_spi_buf_set = {.buffers = &rx_spi_buf, .count = 1}; + + for (int i = 0; i < MAX_READ_REPEATS; i++) { + TC_PRINT("RDID attempt %u\n", i + 1); + + timer_cc_before = nrfx_timer_capture(&test_timer, NRF_TIMER_CC_CHANNEL0); + err = spi_transceive_dt(&spim_spec, &tx_spi_buf_set, &rx_spi_buf_set); + timer_cc_after = nrfx_timer_capture(&test_timer, NRF_TIMER_CC_CHANNEL0); + TC_PRINT("SPIM prescaler: %u\n", spim_reg->PRESCALER); + zassert_ok(err, "SPI transceive failed: %d\n", err); + + tx_amount = nrf_spim_tx_amount_get(spim_reg); + TC_PRINT("END events count: %u\n", timer_cc_after - timer_cc_before); + TC_PRINT("TX.AMOUNT: %u\n", tx_amount); + + zassert_equal(timer_cc_after - timer_cc_before, 1, + "END event has not been generated\n"); + zassert_equal(tx_amount, ARRAY_SIZE(tx_buffer), "TX.AMOUNT != TX Buffer size\n"); + + for (int i = 0; i < ARRAY_SIZE(rx_buffer); i++) { + TC_PRINT("rx_buffer[%d] = 0x%x\n", i, rx_buffer[i]); + } + + /* First RX byte is dummy */ + zassert_equal(rx_buffer[1], MX25R64_MFG_ID, + "Read MX25R64 device ID is different than expected\n"); + zassert_equal(rx_buffer[2], MX25R64_MEM_TYPE, + "Read MX25R64 memory type is different than expected\n"); + zassert_equal(rx_buffer[3], MX25R64_MEM_DENSITY, + "Read MX25R64 memory density is different than expected\n"); + } +#endif +} + ZTEST_SUITE(spim_pan, NULL, test_setup, NULL, NULL, NULL); diff --git a/tests/drivers/spi/spim_pan/testcase.yaml b/tests/drivers/spi/spim_pan/testcase.yaml index 19fcb33900f7..453800519a3c 100644 --- a/tests/drivers/spi/spim_pan/testcase.yaml +++ b/tests/drivers/spi/spim_pan/testcase.yaml @@ -2,20 +2,31 @@ common: sysbuild: true depends_on: gpio harness: ztest - harness_config: - fixture: gpio_loopback tags: - drivers - spim - ci_tests_drivers_spi - platform_allow: - - nrf54h20dk/nrf54h20/cpuapp - - nrf54l15dk/nrf54l15/cpuapp - - nrf54lm20dk/nrf54lm20a/cpuapp - - nrf54ls05dk/nrf54ls05b/cpuapp - - nrf54lv10dk/nrf54lv10a/cpuapp - integration_platforms: - - nrf54l15dk/nrf54l15/cpuapp tests: - drivers.spim_pan: {} + drivers.spim_pan: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54ls05dk/nrf54ls05b/cpuapp + - nrf54lv10dk/nrf54lv10a/cpuapp + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp + harness_config: + fixture: gpio_loopback + + drivers.spim_pan.fast: + platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf54lm20dk/nrf54lm20a/cpuapp + extra_args: + - DTC_OVERLAY_FILE='boards/nrf54lxx_cpuapp_fast.overlay' + harness_config: + fixture: external_flash From 589733f663a376018ef75b35259b0d946b727ae3 Mon Sep 17 00:00:00 2001 From: Anna Wojdylo Date: Mon, 1 Dec 2025 14:47:14 +0100 Subject: [PATCH 050/155] doc: add lv10 links adds hardware documentation links Signed-off-by: Anna Wojdylo --- doc/nrf/app_dev/device_guides/nrf54l/index.rst | 8 ++++++-- doc/nrf/links.txt | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/nrf/app_dev/device_guides/nrf54l/index.rst b/doc/nrf/app_dev/device_guides/nrf54l/index.rst index a96baae279b1..70e7b27d3208 100644 --- a/doc/nrf/app_dev/device_guides/nrf54l/index.rst +++ b/doc/nrf/app_dev/device_guides/nrf54l/index.rst @@ -64,8 +64,12 @@ Refer to the following information for the list of supported development kits (D | ``nrf54lv10dk/nrf54lv10a/cpuapp/ns`` (:ref:`TF-M `) | ``nrf54lv10dk/nrf54lv10a/cpuflpr`` | ``nrf54lv10dk/nrf54lv10a/cpuflpr/xip`` - - *Documentation not yet available* - - *Product pages not yet available* + - | `Datasheet `_ + | `Quick Start app`_ + | `User Guide `_ + | `nRF54LV10 Compatibility Matrix`_ + - | `nRF54LV10 DK product page `_ + | `nRF54LV10 System-on-Chip (SoC) `_ For the full list of supported protocols, see the :ref:`software maturity documentation`. diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index 6e1921a2829a..8eadadc31918 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -341,6 +341,9 @@ .. _`nRF54L05`: https://www.nordicsemi.com/Products/nRF54L05 .. _`nRF54L10`: https://www.nordicsemi.com/Products/nRF54L10 +.. _`nRF54LV10 DK`: https://www.nordicsemi.com/Products/Development-hardware/nRF54LV10-DK +.. _`nRF54LV10A System-on-Chip`: https://www.nordicsemi.com/Products/nRF54LV10A + .. _`nRF54LM20A System-on-Chip`: https://www.nordicsemi.com/Products/nRF54LM20A .. _`nRF54LM20 DK`: https://www.nordicsemi.com/Products/Development-hardware/nRF54LM20-DK @@ -848,6 +851,10 @@ .. _`nRF54LM20 DK User Guide`: https://docs.nordicsemi.com/bundle/ug_nrf54lm20_dk/page/UG/nRF54LM20_DK/intro/intro.html .. _`nRF54LM20A Compatibility Matrix`: https://docs.nordicsemi.com/bundle/comp_matrix_nrf54lm20a/page/COMP/nrf54lm20a/nrf54lm20a_comp_matrix.html +.. _`nRF54LV10A Datasheet`: https://docs.nordicsemi.com/bundle/ps_nrf54LV10A/page/keyfeatures_html5.html +.. _`nRF54LV10 DK User Guide`: https://docs.nordicsemi.com/bundle/ug_nrf54lv10_dk/page/UG/nRF54LV10_DK/intro/intro.html +.. _`nRF54LV10 Compatibility Matrix`: https://docs.nordicsemi.com/bundle/comp_matrix_nrf54lv10a/page/COMP/nrf54lv10a/nrf54lv10a_comp_matrix.html + .. _`nRF53 Series`: https://docs.nordicsemi.com/category/nrf-53-series .. _`nRF5340 Product Specification`: https://docs.nordicsemi.com/bundle/ps_nrf5340/page/keyfeatures_html5.html From 7eabde29f6890eb60606e053bc186c8d2f269fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Thu, 27 Nov 2025 14:30:41 +0100 Subject: [PATCH 051/155] tests: benchmarks: multicore: idle_wdt: Add test on APP core only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add test configuration where WDT is tested on APP core only. Allow comparison of current consumption in low power states when WDT is running in APP domain only or in both APP and Radio domains. Define sysbuild Kconfig that controls core synchronization in both sub-images. Signed-off-by: Sebastian Głąb --- tests/benchmarks/multicore/idle_wdt/Kconfig | 5 +++ .../multicore/idle_wdt/Kconfig.sysbuild | 33 ++++++++++++++--- .../boards/nrf54h20dk_nrf54h20_cpuapp.conf | 7 ++++ .../multicore/idle_wdt/enable_logs.conf | 15 ++++++++ tests/benchmarks/multicore/idle_wdt/prj.conf | 21 ++++++++--- .../multicore/idle_wdt/prj_s2ram.conf | 17 --------- .../multicore/idle_wdt/remote/Kconfig | 5 +++ .../multicore/idle_wdt/remote/prj.conf | 20 ++++++++--- .../multicore/idle_wdt/remote/prj_s2ram.conf | 11 ------ .../benchmarks/multicore/idle_wdt/src/main.c | 10 +++--- .../multicore/idle_wdt/sysbuild.cmake | 19 +++++----- .../multicore/idle_wdt/testcase.yaml | 36 ++++++++++++++----- 12 files changed, 136 insertions(+), 63 deletions(-) create mode 100644 tests/benchmarks/multicore/idle_wdt/boards/nrf54h20dk_nrf54h20_cpuapp.conf create mode 100644 tests/benchmarks/multicore/idle_wdt/enable_logs.conf delete mode 100644 tests/benchmarks/multicore/idle_wdt/prj_s2ram.conf delete mode 100644 tests/benchmarks/multicore/idle_wdt/remote/prj_s2ram.conf diff --git a/tests/benchmarks/multicore/idle_wdt/Kconfig b/tests/benchmarks/multicore/idle_wdt/Kconfig index c007d899b124..2a74d48573ef 100644 --- a/tests/benchmarks/multicore/idle_wdt/Kconfig +++ b/tests/benchmarks/multicore/idle_wdt/Kconfig @@ -12,4 +12,9 @@ config TEST_SLEEP_DURATION_MS Based on the value of 'min-residency-us' specified for each power state defined in the DTS, core enters the lowest possible power state. +config TEST_SYNCHRONIZE_CORES + bool "Synchronization with other core" + help + When set to 'y' core will synchronize code execution with the other core. + source "Kconfig.zephyr" diff --git a/tests/benchmarks/multicore/idle_wdt/Kconfig.sysbuild b/tests/benchmarks/multicore/idle_wdt/Kconfig.sysbuild index d5238c072470..fc063bf82f90 100644 --- a/tests/benchmarks/multicore/idle_wdt/Kconfig.sysbuild +++ b/tests/benchmarks/multicore/idle_wdt/Kconfig.sysbuild @@ -4,8 +4,33 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -source "share/sysbuild/Kconfig" +choice NETCORE + default NETCORE_REMOTE + +config NETCORE_REMOTE + bool "Remote image" + +config NETCORE_REMOTE_SLEEP_FOREVER + bool "Remote sleep forever image" + +endchoice -config REMOTE_BOARD - string - default "$(BOARD)/nrf54h20/cpurad" if SOC_NRF54H20_CPUAPP +config NETCORE_IMAGE_NAME + default "remote" if NETCORE_REMOTE + default "remote_sleep_forever" if NETCORE_REMOTE_SLEEP_FOREVER + +config NETCORE_IMAGE_PATH + default "${ZEPHYR_NRF_MODULE_DIR}/tests/benchmarks/multicore/idle_wdt/remote" if NETCORE_REMOTE + default "${ZEPHYR_NRF_MODULE_DIR}/tests/benchmarks/power_consumption/common/remote_sleep_forever" if NETCORE_REMOTE_SLEEP_FOREVER + +config TEST_SYNCHRONIZE_CORES + bool "Synchronize both cores" + depends on NETCORE_REMOTE + default y + help + When set to 'y' both cores will synchronize just before entering the main loop. + This requires test code to be compiled for both Application and Radio cores. + When one of the cores is flashed with remote_sleep_forever it will not confirm its readines. + In such case, the other core will wait forever for event that never happens. + +source "share/sysbuild/Kconfig" diff --git a/tests/benchmarks/multicore/idle_wdt/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/benchmarks/multicore/idle_wdt/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 000000000000..cc10b7737d12 --- /dev/null +++ b/tests/benchmarks/multicore/idle_wdt/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,7 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y diff --git a/tests/benchmarks/multicore/idle_wdt/enable_logs.conf b/tests/benchmarks/multicore/idle_wdt/enable_logs.conf new file mode 100644 index 000000000000..518a3ffeca6f --- /dev/null +++ b/tests/benchmarks/multicore/idle_wdt/enable_logs.conf @@ -0,0 +1,15 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_PM=n +CONFIG_PM_DEVICE=n +CONFIG_PM_DEVICE_RUNTIME=n + +CONFIG_PRINTK=y +CONFIG_LOG=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y diff --git a/tests/benchmarks/multicore/idle_wdt/prj.conf b/tests/benchmarks/multicore/idle_wdt/prj.conf index a0f56f9968a2..93ecc023b4ff 100644 --- a/tests/benchmarks/multicore/idle_wdt/prj.conf +++ b/tests/benchmarks/multicore/idle_wdt/prj.conf @@ -1,5 +1,18 @@ -CONFIG_PRINTK=y -CONFIG_LOG=y -CONFIG_LOG_MODE_IMMEDIATE=y -CONFIG_ASSERT=y CONFIG_WATCHDOG=y +CONFIG_GPIO=y + +CONFIG_PM=y +CONFIG_POWEROFF=y +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y + +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_ASSERT=y + +# Enable for debugging purposes only +CONFIG_PRINTK=n +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_SERIAL=n diff --git a/tests/benchmarks/multicore/idle_wdt/prj_s2ram.conf b/tests/benchmarks/multicore/idle_wdt/prj_s2ram.conf deleted file mode 100644 index acdff9696441..000000000000 --- a/tests/benchmarks/multicore/idle_wdt/prj_s2ram.conf +++ /dev/null @@ -1,17 +0,0 @@ -CONFIG_PM=y -CONFIG_POWEROFF=y - -CONFIG_PM_DEVICE=y -CONFIG_PM_DEVICE_RUNTIME=y - -# Enable for debugging purposes only -CONFIG_BOOT_BANNER=n -CONFIG_NCS_BOOT_BANNER=n -CONFIG_PRINTK=n -CONFIG_LOG=n -CONFIG_CONSOLE=n -CONFIG_UART_CONSOLE=n -CONFIG_SERIAL=n - -CONFIG_WATCHDOG=y -CONFIG_ASSERT=y diff --git a/tests/benchmarks/multicore/idle_wdt/remote/Kconfig b/tests/benchmarks/multicore/idle_wdt/remote/Kconfig index e145863ab494..93463968c5cb 100644 --- a/tests/benchmarks/multicore/idle_wdt/remote/Kconfig +++ b/tests/benchmarks/multicore/idle_wdt/remote/Kconfig @@ -19,4 +19,9 @@ config TEST_ROLE_REMOTE KConfig used in synchronization phase. Set TEST_ROLE_REMOTE=y on core that shall synchronize with the Host core. +config TEST_SYNCHRONIZE_CORES + bool "Synchronization with other core" + help + When set to 'y' core will synchronize code execution with the other core. + source "Kconfig.zephyr" diff --git a/tests/benchmarks/multicore/idle_wdt/remote/prj.conf b/tests/benchmarks/multicore/idle_wdt/remote/prj.conf index 05a94cf19d44..93ecc023b4ff 100644 --- a/tests/benchmarks/multicore/idle_wdt/remote/prj.conf +++ b/tests/benchmarks/multicore/idle_wdt/remote/prj.conf @@ -1,6 +1,18 @@ -CONFIG_PRINTK=y -CONFIG_LOG=y -CONFIG_LOG_MODE_IMMEDIATE=y -CONFIG_ASSERT=y CONFIG_WATCHDOG=y CONFIG_GPIO=y + +CONFIG_PM=y +CONFIG_POWEROFF=y +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y + +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_ASSERT=y + +# Enable for debugging purposes only +CONFIG_PRINTK=n +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_SERIAL=n diff --git a/tests/benchmarks/multicore/idle_wdt/remote/prj_s2ram.conf b/tests/benchmarks/multicore/idle_wdt/remote/prj_s2ram.conf deleted file mode 100644 index b5dbb63af6ca..000000000000 --- a/tests/benchmarks/multicore/idle_wdt/remote/prj_s2ram.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_PM=y -CONFIG_POWEROFF=y - -CONFIG_CONSOLE=n -CONFIG_UART_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_BOOT_BANNER=n -CONFIG_NCS_BOOT_BANNER=n - -CONFIG_WATCHDOG=y -CONFIG_GPIO=y diff --git a/tests/benchmarks/multicore/idle_wdt/src/main.c b/tests/benchmarks/multicore/idle_wdt/src/main.c index 86a3fcda8321..4cfc0e870166 100644 --- a/tests/benchmarks/multicore/idle_wdt/src/main.c +++ b/tests/benchmarks/multicore/idle_wdt/src/main.c @@ -104,6 +104,7 @@ int main(void) __ASSERT(false, "wdt_install_timeout() returned %d\n", my_wdt_channel); } +#if defined(CONFIG_TEST_SYNCHRONIZE_CORES) /* Synchronize Remote core with Host core */ #if !defined(CONFIG_TEST_ROLE_REMOTE) LOG_DBG("HOST starts"); @@ -115,8 +116,8 @@ int main(void) sys_cache_data_invd_range((void *) shared_var, sizeof(*shared_var)); LOG_DBG("shared_var is: %u", *shared_var); } - LOG_DBG("HOST continues"); -#else + LOG_INF("HOST continues"); +#else /* !defined(CONFIG_TEST_ROLE_REMOTE) */ LOG_DBG("REMOTE starts"); while (*shared_var != HOST_IS_READY) { k_msleep(1); @@ -127,8 +128,9 @@ int main(void) *shared_var = REMOTE_IS_READY; sys_cache_data_flush_range((void *) shared_var, sizeof(*shared_var)); LOG_DBG("REMOTE wrote REMOTE_IS_READY: %u", *shared_var); - LOG_DBG("REMOTE continues"); -#endif + LOG_INF("REMOTE continues"); +#endif /* !defined(CONFIG_TEST_ROLE_REMOTE) */ +#endif /* defined(CONFIG_TEST_SYNCHRONIZE_CORES) */ /* Start Watchdog */ ret = wdt_setup(my_wdt_device, WDT_OPT_PAUSE_HALTED_BY_DBG | WDT_OPT_PAUSE_IN_SLEEP); diff --git a/tests/benchmarks/multicore/idle_wdt/sysbuild.cmake b/tests/benchmarks/multicore/idle_wdt/sysbuild.cmake index 80f51bddea6d..03795f67b8f9 100644 --- a/tests/benchmarks/multicore/idle_wdt/sysbuild.cmake +++ b/tests/benchmarks/multicore/idle_wdt/sysbuild.cmake @@ -4,14 +4,13 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -if("${SB_CONFIG_REMOTE_BOARD}" STREQUAL "") - message(FATAL_ERROR "REMOTE_BOARD must be set to a valid board name") -endif() +if(SB_CONFIG_TEST_SYNCHRONIZE_CORES) + set_config_bool(${DEFAULT_IMAGE} CONFIG_TEST_SYNCHRONIZE_CORES y) + set_config_bool(${SB_CONFIG_NETCORE_IMAGE_NAME} CONFIG_TEST_SYNCHRONIZE_CORES y) +else() + set_config_bool(${DEFAULT_IMAGE} CONFIG_TEST_SYNCHRONIZE_CORES n) -# Add remote project -ExternalZephyrProject_Add( - APPLICATION remote - SOURCE_DIR ${APP_DIR}/remote - BOARD ${SB_CONFIG_REMOTE_BOARD} - BOARD_REVISION ${BOARD_REVISION} -) + if(SB_CONFIG_NETCORE_REMOTE) + set_config_bool(${SB_CONFIG_NETCORE_IMAGE_NAME} CONFIG_TEST_SYNCHRONIZE_CORES n) + endif() +endif() diff --git a/tests/benchmarks/multicore/idle_wdt/testcase.yaml b/tests/benchmarks/multicore/idle_wdt/testcase.yaml index 8aa3caa4a058..e576c536374c 100644 --- a/tests/benchmarks/multicore/idle_wdt/testcase.yaml +++ b/tests/benchmarks/multicore/idle_wdt/testcase.yaml @@ -7,10 +7,10 @@ common: - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf54h20dk/nrf54h20/cpuapp - extra_args: - - CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y tests: + # cpuapp - idle_wdt test with logging + # cpurad - idle_wdt test with logging benchmarks.multicore.idle_wdt.nrf54h20dk_cpuapp_cpurad.no_sleep: harness: console harness_config: @@ -20,12 +20,15 @@ tests: - "Multicore idle_wdt test on" - "Run 0" - "Run 1" + extra_args: + - idle_wdt_EXTRA_CONF_FILE=enable_logs.conf + - remote_EXTRA_CONF_FILE=../enable_logs.conf + # cpuapp - idle_wdt test (idle_retained) + # cpurad - idle_wdt test (idle) benchmarks.multicore.idle_wdt.nrf54h20dk_cpuapp_cpurad.idle_retained: tags: ppk_power_measure extra_args: - - idle_wdt_CONF_FILE=prj_s2ram.conf - - remote_CONF_FILE=prj_s2ram.conf - idle_wdt_CONFIG_TEST_SLEEP_DURATION_MS=500 - remote_CONFIG_TEST_SLEEP_DURATION_MS=500 - idle_wdt_EXTRA_DTC_OVERLAY_FILE="${ZEPHYR_NRF_MODULE_DIR}/tests/benchmarks/multicore/common/workaround_idle_retained.overlay" @@ -35,11 +38,11 @@ tests: pytest_root: - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_pwm_and_idle" + # cpuapp - idle_wdt test (idle) + # cpurad - idle_wdt test (idle) benchmarks.multicore.idle_wdt.nrf54h20dk_cpuapp_cpurad.idle: tags: ppk_power_measure extra_args: - - idle_wdt_CONF_FILE=prj_s2ram.conf - - remote_CONF_FILE=prj_s2ram.conf - idle_wdt_CONFIG_TEST_SLEEP_DURATION_MS=500 - remote_CONFIG_TEST_SLEEP_DURATION_MS=500 - idle_wdt_EXTRA_DTC_OVERLAY_FILE="${ZEPHYR_NRF_MODULE_DIR}/tests/benchmarks/multicore/common/workaround_idle.overlay" @@ -49,13 +52,28 @@ tests: pytest_root: - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_pwm_and_idle" + # cpuapp - idle_wdt test (s2ram) + # cpurad - idle_wdt test (idle) benchmarks.multicore.idle_wdt.nrf54h20dk_cpuapp_cpurad.s2ram: tags: ppk_power_measure - extra_args: - - idle_wdt_CONF_FILE=prj_s2ram.conf - - remote_CONF_FILE=prj_s2ram.conf harness: pytest harness_config: fixture: ppk_power_measure pytest_root: - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_pwm_and_s2ram" + + # cpuapp - idle_wdt test (s2ram) + # cpurad - remote sleep forever (idle) + benchmarks.multicore.idle_wdt.nrf54h20dk_cpuapp.s2ram: + tags: ppk_power_measure + extra_args: + - SB_CONFIG_NETCORE_REMOTE_SLEEP_FOREVER=y + harness: pytest + harness_config: + fixture: ppk_power_measure + pytest_root: + - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_wdt_and_s2ram" + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp From 6702d3a71e8e20b92e03517fd3fd928ea2d28660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Thu, 27 Nov 2025 15:49:06 +0100 Subject: [PATCH 052/155] tests: benchmarks: multicore: idle_wdt: Run test on Radio core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add test configuration that uses WDT on Radio core only. APP core sleeps forever. Signed-off-by: Sebastian Głąb --- .../multicore/idle_wdt/Kconfig.sysbuild | 14 +++++++ .../boards/nrf54h20dk_nrf54h20_cpurad.overlay | 33 +++++++++++++++ .../multicore/idle_wdt/testcase.yaml | 41 ++++++++++++++++--- 3 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 tests/benchmarks/multicore/idle_wdt/boards/nrf54h20dk_nrf54h20_cpurad.overlay diff --git a/tests/benchmarks/multicore/idle_wdt/Kconfig.sysbuild b/tests/benchmarks/multicore/idle_wdt/Kconfig.sysbuild index fc063bf82f90..9ad3d69497ac 100644 --- a/tests/benchmarks/multicore/idle_wdt/Kconfig.sysbuild +++ b/tests/benchmarks/multicore/idle_wdt/Kconfig.sysbuild @@ -23,6 +23,20 @@ config NETCORE_IMAGE_PATH default "${ZEPHYR_NRF_MODULE_DIR}/tests/benchmarks/multicore/idle_wdt/remote" if NETCORE_REMOTE default "${ZEPHYR_NRF_MODULE_DIR}/tests/benchmarks/power_consumption/common/remote_sleep_forever" if NETCORE_REMOTE_SLEEP_FOREVER +choice APPCORE + default APPCORE_REMOTE_SLEEP_FOREVER + +config APPCORE_REMOTE_SLEEP_FOREVER + bool "Remote sleep forever image" + +endchoice + +config APPCORE_IMAGE_NAME + default "remote_sleep_forever" if APPCORE_REMOTE_SLEEP_FOREVER + +config APPCORE_IMAGE_PATH + default "${ZEPHYR_NRF_MODULE_DIR}/tests/benchmarks/power_consumption/common/remote_sleep_forever" if APPCORE_REMOTE_SLEEP_FOREVER + config TEST_SYNCHRONIZE_CORES bool "Synchronize both cores" depends on NETCORE_REMOTE diff --git a/tests/benchmarks/multicore/idle_wdt/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/benchmarks/multicore/idle_wdt/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 000000000000..6e2cb6259627 --- /dev/null +++ b/tests/benchmarks/multicore/idle_wdt/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + aliases { + led = &led1; + watchdog0 = &wdt010; + }; + + leds { + compatible = "gpio-leds"; + + led1: led_1 { + gpios = <&gpio9 1 GPIO_ACTIVE_HIGH>; + label = "Green LED 1"; + }; + }; +}; + +&gpio9 { + status = "okay"; +}; + +&gpiote130 { + status = "okay"; +}; + +&wdt010 { + status = "okay"; +}; diff --git a/tests/benchmarks/multicore/idle_wdt/testcase.yaml b/tests/benchmarks/multicore/idle_wdt/testcase.yaml index e576c536374c..6009c434c3a4 100644 --- a/tests/benchmarks/multicore/idle_wdt/testcase.yaml +++ b/tests/benchmarks/multicore/idle_wdt/testcase.yaml @@ -3,10 +3,6 @@ common: tags: - ci_build - ci_tests_benchmarks_multicore - platform_allow: - - nrf54h20dk/nrf54h20/cpuapp - integration_platforms: - - nrf54h20dk/nrf54h20/cpuapp tests: # cpuapp - idle_wdt test with logging @@ -23,6 +19,10 @@ tests: extra_args: - idle_wdt_EXTRA_CONF_FILE=enable_logs.conf - remote_EXTRA_CONF_FILE=../enable_logs.conf + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp # cpuapp - idle_wdt test (idle_retained) # cpurad - idle_wdt test (idle) @@ -37,6 +37,10 @@ tests: fixture: ppk_power_measure pytest_root: - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_pwm_and_idle" + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp # cpuapp - idle_wdt test (idle) # cpurad - idle_wdt test (idle) @@ -51,6 +55,10 @@ tests: fixture: ppk_power_measure pytest_root: - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_pwm_and_idle" + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp # cpuapp - idle_wdt test (s2ram) # cpurad - idle_wdt test (idle) @@ -60,10 +68,14 @@ tests: harness_config: fixture: ppk_power_measure pytest_root: - - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_pwm_and_s2ram" + - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_wdt_and_s2ram" + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp # cpuapp - idle_wdt test (s2ram) - # cpurad - remote sleep forever (idle) + # cpurad - remote_sleep_forever (idle) benchmarks.multicore.idle_wdt.nrf54h20dk_cpuapp.s2ram: tags: ppk_power_measure extra_args: @@ -77,3 +89,20 @@ tests: - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf54h20dk/nrf54h20/cpuapp + + # cpuapp - empty_app_core (s2ram) + # cpurad - idle_wdt test (idle) + benchmarks.multicore.idle_wdt.nrf54h20dk_cpurad.s2ram: + tags: ppk_power_measure + extra_args: + - SB_CONFIG_APPCORE_REMOTE_SLEEP_FOREVER=y + - remote_sleep_forever_CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y + harness: pytest + harness_config: + fixture: ppk_power_measure + pytest_root: + - "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_wdt_and_s2ram" + platform_allow: + - nrf54h20dk/nrf54h20/cpurad + integration_platforms: + - nrf54h20dk/nrf54h20/cpurad From 71b0b78a21d93dcfbfc247774e32a8075dcff09a Mon Sep 17 00:00:00 2001 From: Mateusz Kapala Date: Mon, 1 Dec 2025 11:15:53 +0100 Subject: [PATCH 053/155] Revert "samples: benchmarks: coremark: indicate the broken nRF54H20 DK target" This reverts commit 7db5d9bd5fb598bd783bd265c59674fa7d8c804b. Jira: NCSDK-36540 Signed-off-by: Mateusz Kapala --- samples/benchmarks/coremark/README.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/samples/benchmarks/coremark/README.rst b/samples/benchmarks/coremark/README.rst index a6b6ccedee28..82525ef168c6 100644 --- a/samples/benchmarks/coremark/README.rst +++ b/samples/benchmarks/coremark/README.rst @@ -17,11 +17,6 @@ The sample supports the following development kits: .. table-from-sample-yaml:: -.. note:: - This sample does not build or run for the ``nrf54h20dk/nrf54h20/cpuapp`` board target due to the IronSide SE migration. - See the ``NCSDK-34698`` in the :ref:`known_issues` page for more information. - The codebase and documentation will be updated in the future releases to address this issue. - Overview ******** From 818a16b3d89e41d6739a14ea0287032febfda2ed Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Mon, 1 Dec 2025 13:50:11 +0000 Subject: [PATCH 054/155] manifest: Update sdk-nrfxlib revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-nrfxlib/pull/1944 Signed-off-by: Nordic Builder --- west.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/west.yml b/west.yml index 6da75b5f244e..92d0b406bcb0 100644 --- a/west.yml +++ b/west.yml @@ -143,7 +143,7 @@ manifest: - name: nrfxlib repo-path: sdk-nrfxlib path: nrfxlib - revision: 82c041e33c40820c4694995c869bfd5eedefe68a + revision: 86b79e3269b6322d4113e5a34f966a1a9cbb0fa7 - name: trusted-firmware-m repo-path: sdk-trusted-firmware-m path: modules/tee/tf-m/trusted-firmware-m @@ -217,7 +217,7 @@ manifest: upstream-sha: 1be6ca7253133a21a1e9fe0fbb4656e17d63a936 compare-by-default: false - name: libmodem - revision: 5e2ff763095e44c279fc3c2e41464874aab27c2c + revision: c1056e47eda61024a6937cda5574c97667467346 groups: - libmodem - name: openthread From 4890ac95e227ed49821ff3133069fe3c325b04f4 Mon Sep 17 00:00:00 2001 From: divya pillai Date: Thu, 27 Nov 2025 12:20:43 +0100 Subject: [PATCH 055/155] doc: Minor updates to Kconfig options Updates to Kconfig file to reflect some doc fixes in the documentation and render Kconfig option specific to BT. Signed-off-by: divya pillai --- samples/bluetooth/peripheral_uart/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/bluetooth/peripheral_uart/Kconfig b/samples/bluetooth/peripheral_uart/Kconfig index 67a0216fc435..997add55eb5c 100644 --- a/samples/bluetooth/peripheral_uart/Kconfig +++ b/samples/bluetooth/peripheral_uart/Kconfig @@ -21,11 +21,11 @@ config BT_NUS_UART_BUFFER_SIZE Size of the payload buffer in each RX and TX FIFO element config BT_NUS_SECURITY_ENABLED - bool "Enable security" + bool "Security" default y select BT_SMP help - "Enable BLE security for the UART service" + Enable Bluetooth LE security for the UART service config BT_NUS_UART_RX_WAIT_TIME int "Timeout for UART RX complete event" From 7e270a41521d52ce1d5f226208584cf66230add8 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Tue, 2 Dec 2025 07:22:33 +0000 Subject: [PATCH 056/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3572 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 92d0b406bcb0..73326d202659 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: 0783923a766da87024851b71030e1f70dd404b60 + revision: 796b28fa4b098a276322b31eca3516fc190af37a import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From 168501126689d9fe13cc94b17c2bc979431b2595 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Tue, 2 Dec 2025 08:44:09 +0100 Subject: [PATCH 057/155] samples: bluetooth: Fix usage of nrfx error codes Since nrfx 4, driver APIs return errno values. Comparing against NRFX_SUCCESS is therefore wrong. Unfortunately such cases cannot be found by enabling compiler warnings. Signed-off-by: Rubin Gerritsen --- .../bluetooth/conn_time_sync/src/controller_time_nrf52.c | 4 ++-- .../conn_time_sync/src/controller_time_nrf53_app.c | 4 ++-- .../bluetooth/conn_time_sync/src/controller_time_nrf54.c | 4 ++-- samples/bluetooth/direct_test_mode/src/dtm.c | 8 ++++---- .../bluetooth/iso_time_sync/src/controller_time_nrf52.c | 4 ++-- .../iso_time_sync/src/controller_time_nrf53_app.c | 4 ++-- .../bluetooth/iso_time_sync/src/controller_time_nrf54.c | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/samples/bluetooth/conn_time_sync/src/controller_time_nrf52.c b/samples/bluetooth/conn_time_sync/src/controller_time_nrf52.c index 31fcac3e3bca..efb24f384803 100644 --- a/samples/bluetooth/conn_time_sync/src/controller_time_nrf52.c +++ b/samples/bluetooth/conn_time_sync/src/controller_time_nrf52.c @@ -121,8 +121,8 @@ static int timer_config(void) uint32_t tep; ret = nrfx_timer_init(&app_timer_instance, &timer_cfg, unused_timer_isr_handler); - if (ret != NRFX_SUCCESS) { - printk("Failed initializing timer (ret: %d)\n", ret - NRFX_ERROR_BASE_NUM); + if (ret != 0) { + printk("Failed initializing timer (ret: %d)\n", ret); return -ENODEV; } diff --git a/samples/bluetooth/conn_time_sync/src/controller_time_nrf53_app.c b/samples/bluetooth/conn_time_sync/src/controller_time_nrf53_app.c index dabaef53e13b..f363b7423cad 100644 --- a/samples/bluetooth/conn_time_sync/src/controller_time_nrf53_app.c +++ b/samples/bluetooth/conn_time_sync/src/controller_time_nrf53_app.c @@ -95,8 +95,8 @@ static int timer_config(void) uint32_t tep = nrfx_timer_task_address_get(&app_timer_instance, NRF_TIMER_TASK_CLEAR); ret = nrfx_timer_init(&app_timer_instance, &timer_cfg, unused_timer_isr_handler); - if (ret != NRFX_SUCCESS) { - printk("Failed initializing timer (ret: %d)\n", ret - NRFX_ERROR_BASE_NUM); + if (ret != 0) { + printk("Failed initializing timer (ret: %d)\n", ret); return -ENODEV; } diff --git a/samples/bluetooth/conn_time_sync/src/controller_time_nrf54.c b/samples/bluetooth/conn_time_sync/src/controller_time_nrf54.c index 6bf550e92ac4..82becae620d1 100644 --- a/samples/bluetooth/conn_time_sync/src/controller_time_nrf54.c +++ b/samples/bluetooth/conn_time_sync/src/controller_time_nrf54.c @@ -42,8 +42,8 @@ void controller_time_trigger_set(uint64_t timestamp_us) }; ret = nrfx_grtc_syscounter_cc_absolute_set(&chan_data, timestamp_us, false); - if (ret != NRFX_SUCCESS) { - printk("Failed setting CC (ret: %d)\n", ret - NRFX_ERROR_BASE_NUM); + if (ret != 0) { + printk("Failed setting CC (ret: %d)\n", ret); } } diff --git a/samples/bluetooth/direct_test_mode/src/dtm.c b/samples/bluetooth/direct_test_mode/src/dtm.c index bef31f1b8ba4..68e2eea0daff 100644 --- a/samples/bluetooth/direct_test_mode/src/dtm.c +++ b/samples/bluetooth/direct_test_mode/src/dtm.c @@ -795,7 +795,7 @@ BUILD_ASSERT(false, "No Clock Control driver"); static int timer_init(void) { - nrfx_err_t err; + int err; nrfx_timer_config_t timer_cfg = { .frequency = NRFX_MHZ_TO_HZ(1), .mode = NRF_TIMER_MODE_TIMER, @@ -803,7 +803,7 @@ static int timer_init(void) }; err = nrfx_timer_init(&dtm_inst.timer, &timer_cfg, dtm_timer_handler); - if (err != NRFX_SUCCESS) { + if (err != 0) { printk("nrfx_timer_init failed with: %d\n", err); return -EAGAIN; } @@ -817,7 +817,7 @@ static int timer_init(void) #if NRF52_ERRATA_172_PRESENT static int anomaly_timer_init(void) { - nrfx_err_t err; + int err; nrfx_timer_config_t timer_cfg = { .frequency = NRFX_KHZ_TO_HZ(125), .mode = NRF_TIMER_MODE_TIMER, @@ -826,7 +826,7 @@ static int anomaly_timer_init(void) err = nrfx_timer_init(&dtm_inst.anomaly_timer, &timer_cfg, anomaly_timer_handler); - if (err != NRFX_SUCCESS) { + if (err != 0) { printk("nrfx_timer_init failed with: %d\n", err); return -EAGAIN; } diff --git a/samples/bluetooth/iso_time_sync/src/controller_time_nrf52.c b/samples/bluetooth/iso_time_sync/src/controller_time_nrf52.c index e18c27d8071e..e0535c975d2f 100644 --- a/samples/bluetooth/iso_time_sync/src/controller_time_nrf52.c +++ b/samples/bluetooth/iso_time_sync/src/controller_time_nrf52.c @@ -121,8 +121,8 @@ static int timer_config(void) uint32_t tep = nrfx_timer_task_address_get(&app_timer_instance, NRF_TIMER_TASK_CLEAR); ret = nrfx_timer_init(&app_timer_instance, &timer_cfg, unused_timer_isr_handler); - if (ret != NRFX_SUCCESS) { - printk("Failed initializing timer (ret: %d)\n", ret - NRFX_ERROR_BASE_NUM); + if (ret != 0) { + printk("Failed initializing timer (ret: %d)\n", ret); return -ENODEV; } diff --git a/samples/bluetooth/iso_time_sync/src/controller_time_nrf53_app.c b/samples/bluetooth/iso_time_sync/src/controller_time_nrf53_app.c index e9411ce535f1..49f4c3d9004c 100644 --- a/samples/bluetooth/iso_time_sync/src/controller_time_nrf53_app.c +++ b/samples/bluetooth/iso_time_sync/src/controller_time_nrf53_app.c @@ -95,8 +95,8 @@ static int timer_config(void) uint32_t tep = nrfx_timer_task_address_get(&app_timer_instance, NRF_TIMER_TASK_CLEAR); ret = nrfx_timer_init(&app_timer_instance, &timer_cfg, unused_timer_isr_handler); - if (ret != NRFX_SUCCESS) { - printk("Failed initializing timer (ret: %d)\n", ret - NRFX_ERROR_BASE_NUM); + if (ret != 0) { + printk("Failed initializing timer (ret: %d)\n", ret); return -ENODEV; } diff --git a/samples/bluetooth/iso_time_sync/src/controller_time_nrf54.c b/samples/bluetooth/iso_time_sync/src/controller_time_nrf54.c index 20935f398b9e..ad485994c05f 100644 --- a/samples/bluetooth/iso_time_sync/src/controller_time_nrf54.c +++ b/samples/bluetooth/iso_time_sync/src/controller_time_nrf54.c @@ -42,8 +42,8 @@ void controller_time_trigger_set(uint64_t timestamp_us) }; ret = nrfx_grtc_syscounter_cc_absolute_set(&chan_data, timestamp_us, false); - if (ret != NRFX_SUCCESS) { - printk("Failed setting CC (ret: %d)\n", ret - NRFX_ERROR_BASE_NUM); + if (ret != 0) { + printk("Failed setting CC (ret: %d)\n", ret); } } From 2590ab67b1270d5cd4d4a2bc19a3bef5c7f18a0f Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Tue, 2 Dec 2025 08:49:35 +0100 Subject: [PATCH 058/155] debug: cpu_load: Fix usage of nrfx error codes Since nrfx 4, driver APIs return errno values. Comparing against NRFX_SUCCESS is therefore wrong. Unfortunately such cases cannot be found by enabling compiler warnings. Signed-off-by: Rubin Gerritsen --- subsys/debug/cpu_load/cpu_load.c | 4 ++-- tests/subsys/debug/cpu_load/src/test_cpu_load.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/debug/cpu_load/cpu_load.c b/subsys/debug/cpu_load/cpu_load.c index 46e0d3bc149d..0178553ebf2c 100644 --- a/subsys/debug/cpu_load/cpu_load.c +++ b/subsys/debug/cpu_load/cpu_load.c @@ -99,7 +99,7 @@ static int ppi_setup(uint32_t eep, uint32_t tep) int cpu_load_init_internal(void) { - nrfx_err_t err; + int err; uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer.p_reg); nrfx_timer_config_t config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency); int ret = 0; @@ -135,7 +135,7 @@ int cpu_load_init_internal(void) } err = nrfx_timer_init(&timer, &config, timer_handler); - if (err != NRFX_SUCCESS) { + if (err != 0) { return -EBUSY; } diff --git a/tests/subsys/debug/cpu_load/src/test_cpu_load.c b/tests/subsys/debug/cpu_load/src/test_cpu_load.c index 518561232588..062a90b46e88 100644 --- a/tests/subsys/debug/cpu_load/src/test_cpu_load.c +++ b/tests/subsys/debug/cpu_load/src/test_cpu_load.c @@ -21,7 +21,7 @@ static void timer_handler(nrf_timer_event_t event_type, void *context) static int dppi_shared_resources_init(void) { - nrfx_err_t err; + int err; static nrfx_timer_t timer = NRFX_TIMER_INSTANCE(NRF_TIMER1); uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer.p_reg); nrfx_timer_config_t config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency); @@ -35,7 +35,7 @@ static int dppi_shared_resources_init(void) config.bit_width = NRF_TIMER_BIT_WIDTH_32; err = nrfx_timer_init(&timer, &config, timer_handler); - zassert_equal(err, NRFX_SUCCESS, "Unexpected error:%d", err); + zassert_equal(err, 0, "Unexpected error:%d", err); rv = nrfx_gppi_conn_alloc(evt, tsk, &handle); zassert_equal(rv, 0); From 9be2fd438c9e9cdbac9a237a2541abe594b44a4a Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Tue, 2 Dec 2025 08:50:42 +0100 Subject: [PATCH 059/155] nrf_security: cracen: Fix usage of nrfx error codes Since nrfx 4, driver APIs return errno values. Comparing against NRFX_SUCCESS is therefore wrong. Unfortunately such cases cannot be found by enabling compiler warnings. Signed-off-by: Rubin Gerritsen --- .../src/drivers/nrf_oberon/cracen_trng/cracen_trng.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/nrf_security/src/drivers/nrf_oberon/cracen_trng/cracen_trng.c b/subsys/nrf_security/src/drivers/nrf_oberon/cracen_trng/cracen_trng.c index 29e33c1bb6a2..e18c66560db0 100644 --- a/subsys/nrf_security/src/drivers/nrf_oberon/cracen_trng/cracen_trng.c +++ b/subsys/nrf_security/src/drivers/nrf_oberon/cracen_trng/cracen_trng.c @@ -13,13 +13,13 @@ static psa_status_t cracen_trng_init(void) { - nrfx_err_t nrfx_error; + int nrfx_error; /* This is TRNG even though the naming states otherwise. * On devices that don't support hardware crypto it will default to trng */ nrfx_error = nrfx_cracen_ctr_drbg_init(); - if (nrfx_error != NRFX_SUCCESS) { + if (nrfx_error != 0) { return PSA_ERROR_HARDWARE_FAILURE; } @@ -31,7 +31,7 @@ psa_status_t cracen_trng_get_entropy(uint32_t flags, size_t *estimate_bits, { uint16_t request_len = MIN(UINT16_MAX, output_size); psa_status_t status; - nrfx_err_t nrfx_error; + int nrfx_error; /* Ignore flags as CRACEN TRNG doesn't support entropy generation flags */ (void)flags; @@ -49,7 +49,7 @@ psa_status_t cracen_trng_get_entropy(uint32_t flags, size_t *estimate_bits, * On devices that don't support hardware crypto it will default to trng */ nrfx_error = nrfx_cracen_ctr_drbg_random_get(output, request_len); - if (nrfx_error != NRFX_SUCCESS) { + if (nrfx_error != 0) { return PSA_ERROR_HARDWARE_FAILURE; } From cf8857aef206a0c5bf628d5a97849a3eb0ed45bd Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Tue, 2 Dec 2025 08:51:14 +0100 Subject: [PATCH 060/155] tests: benchmarks: i2c_endless: Fix usage of nrfx error codes Since nrfx 4, driver APIs return errno values. Comparing against NRFX_SUCCESS is therefore wrong. Unfortunately such cases cannot be found by enabling compiler warnings. Signed-off-by: Rubin Gerritsen --- tests/benchmarks/i2c_endless/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/benchmarks/i2c_endless/src/main.c b/tests/benchmarks/i2c_endless/src/main.c index b6ac2f9631be..0d377ac05915 100644 --- a/tests/benchmarks/i2c_endless/src/main.c +++ b/tests/benchmarks/i2c_endless/src/main.c @@ -121,7 +121,7 @@ void twis_setup(void) int ret; ret = nrfx_twis_init(&twis, &config, i2s_slave_handler); - if (ret != NRFX_SUCCESS) { + if (ret != 0) { LOG_ERR("nrfx_twis_init returned %d", ret); } From b7b8a9c96db4ef9a9b883179b4ac8b76cfc1c455 Mon Sep 17 00:00:00 2001 From: Kapil Bhatt Date: Mon, 1 Dec 2025 13:23:05 +0000 Subject: [PATCH 061/155] doc: wifi: Add doc changes for Wi-Fi direct Add proper text in Wi-Fi direct doc. Signed-off-by: Kapil Bhatt --- doc/nrf/protocols/wifi/wifi_direct.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/nrf/protocols/wifi/wifi_direct.rst b/doc/nrf/protocols/wifi/wifi_direct.rst index ad08a6a55c40..2ef4f5dd026d 100644 --- a/doc/nrf/protocols/wifi/wifi_direct.rst +++ b/doc/nrf/protocols/wifi/wifi_direct.rst @@ -107,14 +107,12 @@ To get detailed information about a specific peer, use the following commands: wpa_cli p2p_peer -For example: +For example, to display detailed information about a specified peer device, use the following command: .. code-block:: console wpa_cli p2p_peer D2:39:FA:43:23:C1 -This command displays detailed information about the specified peer device. - Connecting to a peer ==================== @@ -134,7 +132,7 @@ To establish a Wi-Fi Direct connection with a discovered peer: wpa_cli p2p_connect go_intent= -Parameters: +This command uses the following parameters: * ```` - MAC address of the peer device to connect to. * ```` - WPS provisioning method: From 479be76d7d770130c7fe931f72d5e5b0b050ef19 Mon Sep 17 00:00:00 2001 From: Kapil Bhatt Date: Tue, 2 Dec 2025 06:06:06 +0000 Subject: [PATCH 062/155] doc: nrf: Update references of Wi-Fi direct and restructure wifi doc Add Wi-Fi direct in functionalities and update it's references. Restructure wifi section in doc. Signed-off-by: Kapil Bhatt --- .../app_dev/device_guides/nrf70/features.rst | 20 +++++++++---------- doc/nrf/drivers/wifi/nrf70_native.rst | 13 +++++++++--- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/doc/nrf/app_dev/device_guides/nrf70/features.rst b/doc/nrf/app_dev/device_guides/nrf70/features.rst index 2dcabe57ca39..5ed3e9efb053 100644 --- a/doc/nrf/app_dev/device_guides/nrf70/features.rst +++ b/doc/nrf/app_dev/device_guides/nrf70/features.rst @@ -39,22 +39,20 @@ Wi-Fi 6 aligns with IEEE 802.11ax and all earlier versions of the IEEE 802.11 su Currently, the nRF70 Series devices support the following modes: -* :ref:`Station (STA) `: Operates as a wireless client device. -* :ref:`Software-enabled Access Point (SoftAP or SAP) `: Operates as a virtual access point device. -* :ref:`Scan `: Operates as a scan-only device. +* :ref:`Wi-Fi mode `: For IEEE 802.11 protocol stack functionality. * :ref:`Radio test `: For PHY (Baseband and Radio) characterizations and calibrations. -* :ref:`Monitor `: Operates as an IEEE 802.11 wireless packet sniffer. +* :ref:`Offloaded raw transmission `: Allows the offloading of raw IEEE 802.11 frame transmission to the nRF Wi-Fi driver. -The nRF70 Series devices also support the following functionalities: +The nRF70 Series devices support the following functionalities in the Wi-Fi mode: +* :ref:`Station (STA) `: Operates as a wireless client device. +* :ref:`Software-enabled Access Point (SoftAP or SAP) `: Operates as a virtual access point device. +* :ref:`Scan `: Operates as a scan-only device. +* :ref:`Wi-Fi advanced security `: Allows the use of advanced security, certificate-based Wi-Fi security, and the Platform Security Architecture (PSA) security framework. +* :ref:`Wi-Fi Direct® (P2P) mode `: Allows the establishment of direct device-to-device connections without requiring a traditional access point. * :ref:`ug_nrf70_developing_raw_ieee_80211_packet_transmission`: Allows the injection of raw IEEE 802.11 frames in Station and Monitor modes. +* :ref:`Monitor `: Operates as an IEEE 802.11 wireless packet sniffer. * :ref:`Promiscuous reception `: Allows the reception of IEEE 802.11 packets from a connected BSSID when operating in Station mode. -* :ref:`Offloaded raw transmission `: Allows the offloading of raw IEEE 802.11 frame transmission to the nRF Wi-Fi driver. -* :ref:`Wi-Fi advanced security modes `: Allows the use of advanced security modes, certificate-based Wi-Fi security, and the Platform Security Architecture (PSA) security framework. - -Peer-to-peer support in the form of Wi-Fi Direct® will be available in the future. - -See the :ref:`ug_wifi` documentation for more information related to Wi-Fi modes of operation. .. _ug_nrf70_features_hostap: diff --git a/doc/nrf/drivers/wifi/nrf70_native.rst b/doc/nrf/drivers/wifi/nrf70_native.rst index 16d57beaf671..22ca250a09d9 100644 --- a/doc/nrf/drivers/wifi/nrf70_native.rst +++ b/doc/nrf/drivers/wifi/nrf70_native.rst @@ -36,7 +36,7 @@ Design overview The nRF Wi-Fi driver follows an OS-agnostic design, and the driver implementation is split into OS-agnostic and OS (Zephyr)-specific code. The OS-agnostic code is located in the :file:`${ZEPHYR_BASE}/../modules/nrf_wifi/` folder, and the Zephyr OS port is located in the :file:`${ZEPHYR_BASE}/drivers/wifi/nrf_wifi/` folder. -The driver supports two modes of operation: +The driver supports three modes of operation: Wi-Fi mode ========== @@ -52,8 +52,7 @@ The driver supports the following IEEE 802.11 features: * Scan-only mode * IEEE 802.11 :term:`Station mode (STA)` * :term:`Software-enabled Access Point (SoftAP or SAP)` mode - -The Wi-Fi Direct® mode feature is in the driver code but is not yet supported. +* :ref:`Wi-Fi Direct® ` (P2P) mode Except for scan-only mode, the driver uses the host access point daemon (hostapd) to implement AP Media Access Control (MAC) Sublayer Management Entity (AP MLME) and wpa_supplicant to implement 802.1X supplicant. @@ -65,6 +64,14 @@ This is a build time option that you can enable using the :kconfig:option:`CONFI For more details about using this driver in Radio Test mode, see :ref:`wifi_radio_test`. +Offloaded raw TX mode +===================== + +The nRF Wi-Fi driver supports Offloaded raw TX mode, where the nRF70 Series device transmits frames at regular intervals with very low power consumption. +Frame transmission is offloaded to the nRF70 device, minimizing host processing and memory requirements. + +For more details about using this driver in Offloaded raw TX mode, see :ref:`ug_nrf70_developing_offloaded_raw_tx`. + Driver to nRF70 Series device communication ******************************************* From 41fc9499e912d5ae0cb4e59b6eeb0545e0f22550 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 2 Dec 2025 16:17:30 +0530 Subject: [PATCH 063/155] doc: nrf7002eb2: Document the pin conflict with LED1 On nRF54L15DK, document the pin conflict with LED1. Signed-off-by: Chaitanya Tata --- doc/nrf/app_dev/device_guides/nrf70/nrf7002eb2_dev_guide.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/nrf/app_dev/device_guides/nrf70/nrf7002eb2_dev_guide.rst b/doc/nrf/app_dev/device_guides/nrf70/nrf7002eb2_dev_guide.rst index 42d9a21181c7..5aed0a9bed03 100644 --- a/doc/nrf/app_dev/device_guides/nrf70/nrf7002eb2_dev_guide.rst +++ b/doc/nrf/app_dev/device_guides/nrf70/nrf7002eb2_dev_guide.rst @@ -31,7 +31,7 @@ The board can be mounted on the **P1** connector of the nRF54L15 DK and the **P1 +===================================+===================+===============================================+ | CLK (CLK) | P1.11 | SPI Clock | +-----------------------------------+-------------------+-----------------------------------------------+ - | CS (CS) | P1.10 | SPI Chip Select | + | CS (CS) | P1.10\ :sup:`1` | SPI Chip Select | +-----------------------------------+-------------------+-----------------------------------------------+ | MOSI (D0) | P1.06 | SPI MOSI | +-----------------------------------+-------------------+-----------------------------------------------+ @@ -50,6 +50,8 @@ The board can be mounted on the **P1** connector of the nRF54L15 DK and the **P1 | STATUS (ST0) | P1.08 | Coexistence status from nRF7002 | +-----------------------------------+-------------------+-----------------------------------------------+ + [1]: There is a pin conflict with **LED1** on **P1.10** (CS) on the nRF54L15 DK, use other LEDs for status indication. + .. group-tab:: nRF54LM20 DK +-----------------------------------+-------------------+-----------------------------------------------+ From 002c75be46c98d55ae24652cdb1c2ebb5ff43d0e Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 2 Dec 2025 16:29:51 +0530 Subject: [PATCH 064/155] doc: nrf70: Document the Kconfig option for WPA3-SAE PSA WPA3-SAE is default disabled, document the option. Signed-off-by: Chaitanya Tata --- .../device_guides/nrf70/wifi_advanced_security_modes.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/nrf/app_dev/device_guides/nrf70/wifi_advanced_security_modes.rst b/doc/nrf/app_dev/device_guides/nrf70/wifi_advanced_security_modes.rst index 76b8719566de..1bc4968febee 100644 --- a/doc/nrf/app_dev/device_guides/nrf70/wifi_advanced_security_modes.rst +++ b/doc/nrf/app_dev/device_guides/nrf70/wifi_advanced_security_modes.rst @@ -228,3 +228,9 @@ Enable PSA support To enable the nRF70 PSA crypto support in your applications, use the :kconfig:option:`CONFIG_HOSTAP_CRYPTO_ALT_PSA` Kconfig option. The Wi-Fi connection process is similar to the non-PSA mode, however, the only difference is that the cryptographic operations are performed using PSA crypto APIs. + +WPA3-SAE support +---------------- + +To enable WPA3-SAE support in your applications, use the :kconfig:option:`CONFIG_HOSTAP_CRYPTO_WPA3_PSA` Kconfig option. +This is disabled by default. From d62944bf1c4d9b3e14c60ab3b8c751520b1b4805 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Wed, 26 Nov 2025 08:53:05 +0000 Subject: [PATCH 065/155] manifest: Update sdk-find-my revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-find-my/pull/352 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 73326d202659..4471293e45fc 100644 --- a/west.yml +++ b/west.yml @@ -195,7 +195,7 @@ manifest: compare-by-default: false - name: find-my repo-path: sdk-find-my - revision: 1bccfd5dcd26637c34a2af755e00a93e070b7f32 + revision: 8df233300dcf02bb8737ba8d0360abbf2c9002e5 groups: - find-my - name: azure-sdk-for-c From a516b63fae7b9e7d4599d74feba0540d5aff8d23 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Mon, 1 Dec 2025 11:15:28 +0000 Subject: [PATCH 066/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3560 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 4471293e45fc..a9369131dde9 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: 796b28fa4b098a276322b31eca3516fc190af37a + revision: d2bc88b13d5e8f142cd2abed9e5bdec51c0a7336 import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From 002e57174cdd7d6ec7dbb51745a484b34b7ce229 Mon Sep 17 00:00:00 2001 From: Grzegorz Ferenc Date: Tue, 2 Dec 2025 10:38:21 +0100 Subject: [PATCH 067/155] doc: gsg_guides: add nRF54LV10 to the list Added an entry for the nRF54LV10 DK. Signed-off-by: Grzegorz Ferenc --- doc/nrf/gsg_guides.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/nrf/gsg_guides.rst b/doc/nrf/gsg_guides.rst index 07906af48cdb..1a945777753d 100644 --- a/doc/nrf/gsg_guides.rst +++ b/doc/nrf/gsg_guides.rst @@ -30,6 +30,8 @@ The application uses Nordic Semiconductor tools and precompiled binaries and doe +----------------------+ +---------------------------------------+ | nRF7002 DK | | `nRF7002 DK Hardware`_ | +----------------------+ +---------------------------------------+ +| nRF54LV10 DK | | `nRF54LV10 DK User Guide`_ | ++----------------------+ +---------------------------------------+ | nRF54LM20 DK | | `nRF54LM20 DK User Guide`_ | +----------------------+ +---------------------------------------+ | nRF54L15 DK | `Quick Start app`_ | `nRF54L15 DK User Guide`_ | From 7ad7393484184b57c60f84751e3d22ce903b9710 Mon Sep 17 00:00:00 2001 From: divya pillai Date: Wed, 19 Nov 2025 16:54:51 +0100 Subject: [PATCH 068/155] doc: nRF91 Series: remove updating firmware sections Moved the section about Updating the firmware using the Programmer app to the tool docs. Signed-off-by: divya pillai --- .../programmer_erasewrite_nrf9151dk.png | Bin 35066 -> 0 bytes .../programmer_erasewrite_nrf9160dk.png | Bin 20001 -> 0 bytes .../images/programmer_hex_write_nrf9151.png | Bin 92450 -> 0 bytes .../programmer_select_device_nrf9151.png | Bin 27575 -> 0 bytes .../programmer_selectdevice_nrf9160.png | Bin 19932 -> 0 bytes .../images/programmer_write_nrf9160dk.png | Bin 30817 -> 0 bytes .../nrf91/images/programmerapp_modemdfu.png | Bin 12879 -> 0 bytes .../images/programmerapp_modemdfu_nrf9151.png | Bin 9860 -> 0 bytes .../nrf91/nrf91_dk_updating_fw_programmer.rst | 212 +----------------- .../device_guides/nrf91/nrf91_features.rst | 2 +- .../device_guides/nrf91/nrf91_testing.rst | 2 +- .../nrf_cloud_rest_sample_requirements.txt | 6 +- doc/nrf/links.txt | 4 +- .../releases/release-notes-1.1.0.rst | 2 +- .../releases/release-notes-1.2.0.rst | 2 +- .../releases/release-notes-1.2.1.rst | 2 +- .../releases/release-notes-1.3.0.rst | 2 +- .../releases/release-notes-1.3.1.rst | 2 +- .../releases/release-notes-1.3.2.rst | 2 +- .../releases/release-notes-1.4.0.rst | 2 +- .../releases/release-notes-1.4.1.rst | 2 +- .../releases/release-notes-1.4.2.rst | 2 +- .../releases/release-notes-1.5.0.rst | 2 +- .../releases/release-notes-1.5.1.rst | 2 +- .../releases/release-notes-1.5.2.rst | 2 +- .../releases/release-notes-1.6.0.rst | 2 +- .../releases/release-notes-1.6.1.rst | 2 +- .../releases/release-notes-1.7.0.rst | 2 +- .../releases/release-notes-1.7.1.rst | 2 +- .../releases/release-notes-1.8.0.rst | 2 +- .../releases/release-notes-1.9.0.rst | 2 +- .../releases/release-notes-1.9.1.rst | 2 +- .../releases/release-notes-1.9.2.rst | 2 +- .../releases/release-notes-2.0.0.rst | 2 +- .../releases/release-notes-2.0.1.rst | 2 +- .../releases/release-notes-2.0.2.rst | 2 +- .../releases/release-notes-2.1.0.rst | 4 +- .../releases/release-notes-2.1.1.rst | 2 +- .../releases/release-notes-2.1.2.rst | 2 +- .../releases/release-notes-2.1.3.rst | 2 +- .../releases/release-notes-2.1.4.rst | 2 +- .../releases/release-notes-2.2.0.rst | 2 +- .../releases/release-notes-2.3.0.rst | 2 +- .../releases/release-notes-2.4.0.rst | 2 +- .../releases/release-notes-2.4.1.rst | 2 +- .../releases/release-notes-2.4.2.rst | 2 +- .../releases/release-notes-2.4.3.rst | 2 +- .../releases/release-notes-2.4.4.rst | 2 +- .../releases/release-notes-2.5.0.rst | 2 +- .../releases/release-notes-2.5.1.rst | 2 +- .../releases/release-notes-2.5.2.rst | 2 +- .../releases/release-notes-2.5.3.rst | 2 +- .../releases/release-notes-2.6.0.rst | 2 +- .../releases/release-notes-2.6.1.rst | 2 +- .../releases/release-notes-2.6.2.rst | 2 +- .../releases/release-notes-2.6.3.rst | 2 +- .../releases/release-notes-2.6.4.rst | 2 +- .../releases/release-notes-2.7.0.rst | 2 +- .../releases/release-notes-2.8.0.rst | 2 +- .../releases/release-notes-2.9.0.rst | 2 +- .../releases/release-notes-2.9.1.rst | 2 +- .../releases/release-notes-2.9.2.rst | 2 +- .../releases/release-notes-3.0.0.rst | 2 +- .../releases/release-notes-3.0.1.rst | 2 +- .../releases/release-notes-3.0.2.rst | 2 +- .../releases/release-notes-3.1.0.rst | 2 +- .../releases/release-notes-3.1.1.rst | 2 +- .../releases/release-notes-changelog.rst | 2 +- samples/cellular/modem_shell/README.rst | 2 +- 69 files changed, 64 insertions(+), 276 deletions(-) delete mode 100644 doc/nrf/app_dev/device_guides/nrf91/images/programmer_erasewrite_nrf9151dk.png delete mode 100644 doc/nrf/app_dev/device_guides/nrf91/images/programmer_erasewrite_nrf9160dk.png delete mode 100644 doc/nrf/app_dev/device_guides/nrf91/images/programmer_hex_write_nrf9151.png delete mode 100644 doc/nrf/app_dev/device_guides/nrf91/images/programmer_select_device_nrf9151.png delete mode 100644 doc/nrf/app_dev/device_guides/nrf91/images/programmer_selectdevice_nrf9160.png delete mode 100644 doc/nrf/app_dev/device_guides/nrf91/images/programmer_write_nrf9160dk.png delete mode 100644 doc/nrf/app_dev/device_guides/nrf91/images/programmerapp_modemdfu.png delete mode 100644 doc/nrf/app_dev/device_guides/nrf91/images/programmerapp_modemdfu_nrf9151.png diff --git a/doc/nrf/app_dev/device_guides/nrf91/images/programmer_erasewrite_nrf9151dk.png b/doc/nrf/app_dev/device_guides/nrf91/images/programmer_erasewrite_nrf9151dk.png deleted file mode 100644 index 2be7fbec9ab286ff7d3a1b3f5df31501d2b77201..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35066 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 E0MP1~Bme*a diff --git a/doc/nrf/app_dev/device_guides/nrf91/images/programmer_hex_write_nrf9151.png b/doc/nrf/app_dev/device_guides/nrf91/images/programmer_hex_write_nrf9151.png deleted file mode 100644 index 6228b4c07f7545dcb6caaaed0aa505000796ad6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92450 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 TlAy4O00000NkvXXu0mjf8X>sj diff --git a/doc/nrf/app_dev/device_guides/nrf91/images/programmer_select_device_nrf9151.png b/doc/nrf/app_dev/device_guides/nrf91/images/programmer_select_device_nrf9151.png deleted file mode 100644 index 5e7bbed56e0d333fcae553f2e53b636e18bcc6f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27575 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 diff --git a/doc/nrf/app_dev/device_guides/nrf91/images/programmer_selectdevice_nrf9160.png b/doc/nrf/app_dev/device_guides/nrf91/images/programmer_selectdevice_nrf9160.png deleted file mode 100644 index d2b173cf50abb9a710110fb3b94daa4d860f7ae0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19932 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

(rUjG!^b!+sa1Mcff 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�s+YMq0#G_31{ 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 R3!vs8JsqR#C0e(`{}%{widz5x diff --git a/doc/nrf/app_dev/device_guides/nrf91/images/programmerapp_modemdfu_nrf9151.png b/doc/nrf/app_dev/device_guides/nrf91/images/programmerapp_modemdfu_nrf9151.png deleted file mode 100644 index 1c73217e0aadfcd9425f76f157f18aacc58b0247..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9860 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 diff --git a/doc/nrf/app_dev/device_guides/nrf91/nrf91_dk_updating_fw_programmer.rst b/doc/nrf/app_dev/device_guides/nrf91/nrf91_dk_updating_fw_programmer.rst index 814c76ae4274..31814aa3be2d 100644 --- a/doc/nrf/app_dev/device_guides/nrf91/nrf91_dk_updating_fw_programmer.rst +++ b/doc/nrf/app_dev/device_guides/nrf91/nrf91_dk_updating_fw_programmer.rst @@ -9,214 +9,4 @@ Updating the DK firmware using Programmer :depth: 2 Updating the firmware for nRF91 Series devices involves several key steps to ensure the device operates with the latest features, improvements, and security updates. -Before you begin to update the firmware, download and extract the latest application and modem firmware from the `nRF9151 DK Downloads`_, `nRF9161 DK Downloads`_, or `nRF9160 DK Downloads`_ page, depending on the DK you are using. - -The downloaded ZIP archive contains the following firmware: - -Application firmware - The :file:`img_app_bl` folder contains full firmware images for different applications. - The guides in this section use the image for the :ref:`nrf_cloud_multi_service` sample as an example. - The nRF Cloud multi-service sample simulates sensor data and transmits it to Nordic Semiconductor's cloud solution, `nRF Cloud`_. - - The data is transmitted using either LTE-M or NB-IoT. - The nRF Cloud multi-service sample first attempts to use LTE-M, then NB-IoT. - Check with your SIM card provider for the mode they support at your location. - - .. tabs:: - - .. group-tab:: nRF9151 DK - - * For the Onomondo SIM card, check the `Onomondo LTE-M coverage`_ and `Onomondo NB-IoT coverage`_ to see if your country is supported. - - * For the Wireless Logic SIM card, check the `Wireless Logic LTE-M/NB-IoT network coverage`_ to see if your country is supported. - - .. group-tab:: nRF9161 DK - - For the Onomondo SIM card, check the `Onomondo LTE-M coverage`_ and `Onomondo NB-IoT coverage`_ to see the network coverage for different countries. - - .. group-tab:: nRF9160 DK - - For the iBasis SIM card provided with the nRF9160 DK, see `iBasis IoT network coverage`_. - -Application firmware for Device Firmware Update (DFU) - The images in the :file:`img_fota_dfu_bin` and :file:`img_fota_dfu_hex` folders contain firmware images for DFU. - These images are not used in the guides in this section. - -Modem firmware - The modem firmware is in a ZIP archive instead of a folder. - The archive is named :file:`mfw_nrf9160_` or :file:`mfw_nrf91x1_`, followed by the firmware version number. - Do not unzip this file. - -The :file:`CONTENTS.txt` file in the extracted folder contains the location and names of the different firmware images. - -Complete the steps in the following sections to program applications using the `Programmer app`_ from `nRF Connect for Desktop`_. -The nRF Connect for Desktop requires `SEGGER J-Link`_ |jlink_ver|. - -* On Windows, the driver comes bundled with nRF Connect for Desktop. -* On macOS and Linux, you must install the driver manually. - -See the `nRF Connect for Desktop's additional requirements`_ section for more details on the SEGGER J-Link driver. - -You will also need the following USB cables: - -* nRF91x1 DK - USB-C cable -* nRF9160 DK - micro-USB cable - -.. _nrf9161_updating_fw_modem: -.. _nrf9160_updating_fw_modem: -.. _nrf9160_gs_updating_fw_modem: - -Updating the modem firmware -*************************** - -To update the modem firmware, complete the following steps. - -.. tip:: - If you experience any problems during the process, press ``Ctrl+R`` (``command+R`` on macOS) to restart the Programmer app and try again. - -1. Open the Programmer app. -#. For the nRF9160 DK only: Make sure the **PROG/DEBUG SW10** switch on the nRF9160 DK is set to **nRF91**. - On DK v0.9.0 and earlier, this is the **SW5** switch. -#. Connect the DK to the computer with a USB cable, and then turn the DK on. -#. Click :guilabel:`SELECT DEVICE` and select the DK from the drop-down list. - - .. tabs:: - - .. group-tab:: nRF91x1 DK - - .. figure:: images/programmer_select_device_nrf9151.png - :alt: Programmer - Select device (nRF9151 DK shown) - - Programmer - Select device (nRF9151 DK shown) - - .. group-tab:: nRF9160 DK - - .. figure:: images/programmer_selectdevice_nrf9160.png - :alt: Programmer - Select device - - Programmer - Select device - - The drop-down text changes to the type of the selected device, with its SEGGER ID below the name. - The **Device memory layout** section also changes its name to the device name, and indicates that the device is connected. - If the :guilabel:`Auto read memory` option is selected in the **J-LINK SETTINGS** section of the side panel, the memory layout will update. - If it is not selected and you wish to see the memory layout, click :guilabel:`Read` in the **DEVICE** section of the side panel. - -#. Click :guilabel:`Add file` in the **FILE** section, and select :guilabel:`Browse`. -#. Navigate to where you extracted the firmware, and select the file for your DK: - - * nRF9160 DK - :file:`mfw_nrf9160_.zip` - * nRF91x1 DK - :file:`mfw_nrf91x1_.zip` - -#. Click :guilabel:`Write` in the **DEVICE** section of the side panel. - - .. tabs:: - - .. group-tab:: nRF91x1 DK - - .. figure:: images/programmer_hex_write_nrf9151.png - :alt: Programmer - Write (nRF9151 DK shown) - - Programmer - Write (nRF9151 DK shown) - - .. group-tab:: nRF9160 DK - - .. figure:: images/programmer_write_nrf9160dk.png - :alt: Programmer - Write - - Programmer - Write - - The **Modem DFU** window appears. - - .. tabs:: - - .. group-tab:: nRF91x1 DK - - .. figure:: images/programmerapp_modemdfu_nrf9151.png - :alt: Modem DFU window (nRF9151 DK shown) - - The Modem DFU window (nRF9151 DK shown) - - .. group-tab:: nRF9160 DK - - .. figure:: images/programmerapp_modemdfu.png - :alt: Modem DFU window - - The Modem DFU window - -#. Ignore the warning message and click the :guilabel:`Write` button in the **Modem DFU** window to update the firmware. - Do not unplug or turn off the device during this process. - -When the update is complete, you see a success message. -If you update the application firmware now, you can skip the initial steps about connecting and selecting the device in :ref:`nrf9160_updating_fw_application`. - -.. note:: - - If you experience problems updating the modem firmware, click :guilabel:`Erase all` in the **DEVICE** section of the side panel and try updating again. - -.. _nrf9161_updating_fw_application: -.. _nrf9160_updating_fw_application: -.. _nrf9160_gs_updating_fw_application: - -Updating the application firmware -********************************* - -To update the application firmware using the Programmer app, complete the following steps. - -.. tip:: - If you experience any problems during the process, press ``Ctrl+R`` (``command+R`` on macOS) to restart the Programmer app and try again. - -1. Open the Programmer app. -#. For the nRF9160 DK only: Make sure the **PROG/DEBUG SW10** switch (**SW5** on DK v0.9.0 and earlier) on the nRF9160 DK is set to **nRF91** or **nRF52** as appropriate for the application or sample you are programming. - See the `Device programming section in the nRF9160 DK User Guide`_ for more information. - - For the :ref:`nrf_cloud_multi_service` sample, the switch must be set to **nRF91**. - -#. Connect the DK to the computer with a USB cable, and then turn the DK on. -#. Click :guilabel:`SELECT DEVICE` and select the DK from the drop-down list. - - .. tabs:: - - .. group-tab:: nRF91x1 DK - - .. figure:: images/programmer_select_device_nrf9151.png - :alt: Programmer - Select device (nRF9151 DK shown) - - Programmer - Select device (nRF9151 DK shown) - - .. group-tab:: nRF9160 DK - - .. figure:: images/programmer_selectdevice_nrf9160.png - :alt: Programmer - Select device - - Programmer - Select device - - The drop-down text changes to the type of the selected device, with its SEGGER ID below the name. - The **Device memory layout** section also changes its name to the device name, and indicates that the device is connected. - If the :guilabel:`Auto read memory` option is selected in the **J-LINK SETTINGS** section, the memory layout will update. - If it is not selected and you wish to see the memory layout, click :guilabel:`Read` in the **DEVICE** section. - -#. Click :guilabel:`Add file` in the **FILE** section, and select :guilabel:`Browse`. -#. Navigate to where you extracted the firmware, and then to the :file:`img_app_bl` folder there. -#. Select the :file:`.hex` file for your DK for the application you are programming: - - * nRF9160 DK - :file:`nrf9160dk_nrfcloud_multi_service_coap_.hex` - * nRF91x1 DK - :file:`nrf9151dk_nrfcloud_multi_service_coap_.hex` or :file:`nrf9161dk_nrfcloud_multi_service_coap_.hex` - -#. Click the :guilabel:`Erase & write` button in the **DEVICE** section to program the DK. - Do not unplug or turn off the DK during this process. - - .. tabs:: - - .. group-tab:: nRF91x1 DK - - .. figure:: images/programmer_erasewrite_nrf9151dk.png - :alt: Programmer - Erase & write (nRF9151 DK shown) - - Programmer - Erase & write (nRF9151 DK shown) - - .. group-tab:: nRF9160 DK - - .. figure:: images/programmer_erasewrite_nrf9160dk.png - :alt: Programmer - Erase & write - - Programmer - Erase & write +To update the firmware on an mRF91 Series DK using the `Programmer app`_ in nRF Connect for Desktop, complete the steps listed on the `Programming nRF91 Series DK firmware`_ page in the tool documentation. diff --git a/doc/nrf/app_dev/device_guides/nrf91/nrf91_features.rst b/doc/nrf/app_dev/device_guides/nrf91/nrf91_features.rst index fc5ee5da3402..9b611e79299b 100644 --- a/doc/nrf/app_dev/device_guides/nrf91/nrf91_features.rst +++ b/doc/nrf/app_dev/device_guides/nrf91/nrf91_features.rst @@ -121,7 +121,7 @@ Full update Both methods use the :term:`Serial Wire Debug (SWD)` interface to update the firmware. You can use the Programmer app to perform the update, regardless of the images that are part of the existing firmware of the device. - For example, you can update the modem on an nRF9160 DK using the instructions provided in the :ref:`nrf9160_updating_fw_modem` section. + For example, you can update the modem on an nRF9160 DK using the instructions provided in the `Programming nRF91 Series DK firmware`_ page. * When using a wireless connection, the update is applied over-the-air (OTA). See :ref:`nrf91_fota` for more information. diff --git a/doc/nrf/app_dev/device_guides/nrf91/nrf91_testing.rst b/doc/nrf/app_dev/device_guides/nrf91/nrf91_testing.rst index 32741d69d7b1..af6bf37e5ca2 100644 --- a/doc/nrf/app_dev/device_guides/nrf91/nrf91_testing.rst +++ b/doc/nrf/app_dev/device_guides/nrf91/nrf91_testing.rst @@ -12,7 +12,7 @@ You can use it to troubleshoot and debug any connection problems. Complete the following steps to test the cellular connection using the AT Client sample: -1. Follow the steps in :ref:`nrf9160_gs_updating_fw_application` to program the sample to the DK. +1. Follow the steps in the Updating the application firmware tab in the `Programming nRF91 Series DK firmware`_ page to program the sample to the DK. When selecting the HEX file, select the following file instead of the one for :ref:`nrf_cloud_multi_service`: * nRF9151 DK - :file:`nrf9151dk_at_client_.hex` diff --git a/doc/nrf/includes/nrf_cloud_rest_sample_requirements.txt b/doc/nrf/includes/nrf_cloud_rest_sample_requirements.txt index e8823e434840..e055d40777ea 100644 --- a/doc/nrf/includes/nrf_cloud_rest_sample_requirements.txt +++ b/doc/nrf/includes/nrf_cloud_rest_sample_requirements.txt @@ -12,9 +12,9 @@ For an nRF91x1 DK, modem version v2.0.0 or later is required. For instructions on updating your device's modem firmware, see the following documents: - * :ref:`Updating modem firmware on nRF91x1 DK ` - * :ref:`Updating modem firmware on nRF9160 DK ` - * :ref:`Updating modem firmware on Thingy:91 ` + * `Updating modem firmware on nRF91x1 DK `_ + * `Updating modem firmware on nRF9160 DK `_ + * `Updating modem firmware on Thingy:91 `_ .. requirement_cert_provision_start diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index 8eadadc31918..329f6a722eb6 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -455,8 +455,6 @@ .. _`Nordic Semiconductor TechDocs`: https://docs.nordicsemi.com -.. _`nRF Connect for Desktop's additional requirements`: https://docs.nordicsemi.com/bundle/nrf-connect-desktop/page/download_cfd.html#additional-requirements - .. _`nRF Connect SDK v1.4.0 documentation`: https://docs.nordicsemi.com/bundle/ncs-1.4.0/page/nrf/index.html .. _`nRF Connect SDK v1.3.0 documentation`: https://docs.nordicsemi.com/bundle/ncs-1.3.0/page/nrf/index.html .. _`nRF Connect SDK v1.2.1 documentation`: https://docs.nordicsemi.com/bundle/ncs-1.2.1/page/nrf/index.html @@ -746,6 +744,7 @@ .. _`Programming a Development Kit`: https://docs.nordicsemi.com/bundle/nrf-connect-programmer/page/programming_dk.html .. _`Programming Nordic Thingy53`: .. _`Programming Nordic Thingy prototyping platforms`: https://docs.nordicsemi.com/bundle/nrf-connect-programmer/page/programming_thingy.html +.. _`Programming nRF91 Series DK firmware`: https://docs.nordicsemi.com/bundle/nrf-connect-programmer/page/programming_91dk.html .. _`Serial Terminal app`: https://docs.nordicsemi.com/bundle/nrf-connect-serial-terminal/page/index.html .. _`Connecting using the Serial Terminal app`: https://docs.nordicsemi.com/bundle/nrf-connect-serial-terminal/page/connecting.html @@ -781,7 +780,6 @@ .. _`nRF9160 DK board control section in the nRF9160 DK User Guide`: https://docs.nordicsemi.com/bundle/ug_nrf9160_dk/page/UG/nrf91_DK/hw_description/nrf9160_board_controller.html .. _`Measuring current on nRF9160 DK`: https://docs.nordicsemi.com/bundle/ug_nrf9160_dk/page/UG/nrf91_DK/measuring_current/hw_measure_current.html .. _`External memory section in the nRF9160 DK User Guide`: https://docs.nordicsemi.com/bundle/ug_nrf9160_dk/page/UG/nrf91_DK/hw_description/external_memory.html -.. _`Device programming section in the nRF9160 DK User Guide`: https://docs.nordicsemi.com/bundle/ug_nrf9160_dk/page/UG/nrf91_DK/operating_modes/mcu_device_programming.html .. _`VDD supply rail section in the nRF9160 DK User Guide`: https://docs.nordicsemi.com/bundle/ug_nrf9160_dk/page/UG/nrf91_DK/hw_description/power_sources_vdd.html .. _`nRF9160 RESETREAS`: https://docs.nordicsemi.com/bundle/ps_nrf9160/page/power.html#ariaid-title16 diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.1.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.1.0.rst index ea41ba1f910a..14fa641a5189 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.1.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.1.0.rst @@ -43,7 +43,7 @@ Supported modem firmware * mfw_nrf9160_1.1.0 Use the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Supported boards diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.2.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.2.0.rst index 85d9adf4fdfb..929486d6d824 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.2.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.2.0.rst @@ -42,7 +42,7 @@ This version of the |NCS| supports the following modem firmware for cellular IoT * mfw_nrf9160_1.1.1 Use the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Tested boards ************* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.2.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.2.1.rst index 1d0944ce7815..d865cf07f8f6 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.2.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.2.1.rst @@ -45,7 +45,7 @@ This version of the |NCS| supports the following modem firmware for cellular IoT * mfw_nrf9160_1.1.2 Use the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Tested boards ************* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.3.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.3.0.rst index 7b370d731b38..e5889a53dd4a 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.3.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.3.0.rst @@ -52,7 +52,7 @@ This version of the |NCS| has been tested with the following modem firmware for * mfw_nrf9160_1.2.0 Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Changelog ********* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.3.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.3.1.rst index 9038f2db8ecf..8fba306ca27f 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.3.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.3.1.rst @@ -41,7 +41,7 @@ This version of the |NCS| has been tested with the following modem firmware for * mfw_nrf9160_1.2.1 Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Changelog ********* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.3.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.3.2.rst index f4960b980f4d..b218659f319a 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.3.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.3.2.rst @@ -39,7 +39,7 @@ This version of the |NCS| has been tested with the following modem firmware for * mfw_nrf9160_1.2.1 Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Changelog ********* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.4.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.4.0.rst index 3f0cb9f6a7da..f45f8c0f93e1 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.4.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.4.0.rst @@ -47,7 +47,7 @@ This version of the |NCS| has been tested with the following modem firmware for * mfw_nrf9160_1.2.2 Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Changelog ********* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.4.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.4.1.rst index bd0a41961724..c3c1042ed7b2 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.4.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.4.1.rst @@ -38,7 +38,7 @@ This version of the |NCS| has been tested with the following modem firmware for * mfw_nrf9160_1.2.2 Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Changelog ********* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.4.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.4.2.rst index fe85b289e23f..0a18369b525d 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.4.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.4.2.rst @@ -37,7 +37,7 @@ This version of the |NCS| has been tested with the following modem firmware for * mfw_nrf9160_1.2.3 Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Changelog ********* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.5.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.5.0.rst index 785933e69682..c20dc021d38d 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.5.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.5.0.rst @@ -49,7 +49,7 @@ This version of the |NCS| has been tested with the following modem firmware for Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Changelog ********* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.5.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.5.1.rst index b44afc432e4d..15e808b8ae92 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.5.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.5.1.rst @@ -42,7 +42,7 @@ This version of the |NCS| has been tested with the following modem firmware for Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Changelog ********* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.5.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.5.2.rst index dc661511b876..3470e74faac7 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.5.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.5.2.rst @@ -51,7 +51,7 @@ This version of the |NCS| has been tested with the following modem firmware for * mfw_nrf9160_1.1.4 Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Changelog ********* diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.6.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.6.0.rst index 50718d2120bf..5b8d30d51d00 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.6.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.6.0.rst @@ -45,7 +45,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Known issues ************ diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.6.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.6.1.rst index 30c5d0a435a5..952ba08a18e5 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.6.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.6.1.rst @@ -38,7 +38,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Known issues ************ diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.7.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.7.0.rst index 5a84a3118e17..e7ad8c60ef43 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.7.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.7.0.rst @@ -56,7 +56,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Known issues ************ diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.7.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.7.1.rst index 3f504710497e..06a6e43bec51 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.7.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.7.1.rst @@ -37,7 +37,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Known issues ************ diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.8.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.8.0.rst index 93717a3f4243..031da5787f40 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.8.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.8.0.rst @@ -45,7 +45,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Known issues ************ diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.9.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.9.0.rst index 33fbbda4533d..0286f17f2455 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.9.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.9.0.rst @@ -56,7 +56,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.9.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.9.1.rst index 23d0e02183ff..c77160bd6537 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.9.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.9.1.rst @@ -48,7 +48,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-1.9.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-1.9.2.rst index 113bde0b041e..b63e8035516c 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-1.9.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-1.9.2.rst @@ -47,7 +47,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.0.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.0.0.rst index 59693180c0cd..2f524ab52c14 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.0.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.0.0.rst @@ -64,7 +64,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.0.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.0.1.rst index 46ab40b7eccc..0b30a14a8c8f 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.0.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.0.1.rst @@ -49,7 +49,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.0.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.0.2.rst index 0a2eb8c0053f..43cd366790c1 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.0.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.0.2.rst @@ -49,7 +49,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.1.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.1.0.rst index cff05782b5f2..dc99f360c304 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.1.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.1.0.rst @@ -66,7 +66,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== @@ -1085,7 +1085,7 @@ Documentation * :ref:`ug_nrf91` with the following changes: * In the :ref:`ug_nrf91_features` page, added a section about :ref:`modem_trace`. - * In the :ref:`ug_nrf9160_gs` guide, :ref:`nrf9160_gs_updating_fw_modem` section is now moved before :ref:`nrf9160_gs_updating_fw_application` because updating modem firmware erases application firmware. + * In the :ref:`ug_nrf9160_gs` guide, Updating the modem firmware section is now moved before Updating the application firmware because updating modem firmware erases application firmware. * In the :ref:`ug_nrf9160` guide, the :ref:`build_pgm_nrf9160` section now mentions |VSC| and command-line instructions. * In the :ref:`ug_thingy91_gsg` guide, Programming firmware and :ref:`connect_nRF_cloud` sections now have different structure. * The instructions and images in the :ref:`ug_thingy91_gsg` and :ref:`ug_nrf9160_gs` guides now also mention accepting :term:`eUICC Identifier (EID)` when activating your iBasis SIM card from the `nRF Cloud`_ website. diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.1.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.1.1.rst index eb34b59dba01..60e0ef7c141e 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.1.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.1.1.rst @@ -48,7 +48,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.1.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.1.2.rst index 197176c065b0..28f6136323e6 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.1.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.1.2.rst @@ -48,7 +48,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.1.3.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.1.3.rst index 46ee18d71b9c..8d53ea9a4cd9 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.1.3.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.1.3.rst @@ -57,7 +57,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.1.4.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.1.4.rst index 0bdd99352829..25635b192cdb 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.1.4.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.1.4.rst @@ -46,7 +46,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.2.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.2.0.rst index 832f6d2c78ab..d74ffec6ef0e 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.2.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.2.0.rst @@ -79,7 +79,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.3.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.3.0.rst index 013fbf3267e7..c23cd0120b8a 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.3.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.3.0.rst @@ -74,7 +74,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.4.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.4.0.rst index d9761f4e7abf..d0d196227d49 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.4.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.4.0.rst @@ -118,7 +118,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.4.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.4.1.rst index e0e5b7911ba8..09fa2ddb3ac0 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.4.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.4.1.rst @@ -46,7 +46,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.4.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.4.2.rst index 9db887745b10..73bf04b357fa 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.4.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.4.2.rst @@ -46,7 +46,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.4.3.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.4.3.rst index fd3a491c0bff..f283879c9bdf 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.4.3.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.4.3.rst @@ -46,7 +46,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.4.4.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.4.4.rst index 2ff2aa55200e..c2a926b7d4f1 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.4.4.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.4.4.rst @@ -49,7 +49,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.5.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.5.0.rst index 27bcb129dc3c..3b484979e7ef 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.5.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.5.0.rst @@ -120,7 +120,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.5.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.5.1.rst index 0d17e6d155d5..64f5fca1bc75 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.5.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.5.1.rst @@ -45,7 +45,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.5.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.5.2.rst index 804d38a94674..6d5239b2dfb6 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.5.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.5.2.rst @@ -44,7 +44,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.5.3.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.5.3.rst index b082219bcffd..df9a09f39399 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.5.3.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.5.3.rst @@ -44,7 +44,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.6.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.6.0.rst index a6dd62e228f6..5d5e086705b6 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.6.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.6.0.rst @@ -142,7 +142,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.6.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.6.1.rst index 5a7ae15db664..dbee0f8ab258 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.6.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.6.1.rst @@ -44,7 +44,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.6.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.6.2.rst index e2a8ae5e08d4..f35e4474beb6 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.6.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.6.2.rst @@ -44,7 +44,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.6.3.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.6.3.rst index ef6e7c4d0be9..6355b7f664bf 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.6.3.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.6.3.rst @@ -44,7 +44,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.6.4.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.6.4.rst index 115aa103f732..0757625dad46 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.6.4.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.6.4.rst @@ -44,7 +44,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.7.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.7.0.rst index 18985a03756a..a4ecfd518632 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.7.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.7.0.rst @@ -125,7 +125,7 @@ See the following documentation for an overview of which modem firmware versions * `Modem firmware compatibility matrix for the nRF9161 SoC`_ Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.8.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.8.0.rst index 0b42148871cb..59328891d392 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.8.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.8.0.rst @@ -145,7 +145,7 @@ See the following documentation for an overview of which modem firmware versions * `Modem firmware compatibility matrix for the nRF9160 SoC`_ Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.9.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.9.0.rst index be2733c302e7..dc0fc23d6c09 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.9.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.9.0.rst @@ -94,7 +94,7 @@ See the following documentation for an overview of which modem firmware versions * `Modem firmware compatibility matrix for the nRF9160 SoC`_ Use the latest version of the `Programmer app`_ of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.9.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.9.1.rst index 0376deffff73..4b6acac537ae 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.9.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.9.1.rst @@ -45,7 +45,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.9.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.9.2.rst index 210ddb265610..ad2f45fa0a2b 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.9.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.9.2.rst @@ -45,7 +45,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-3.0.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-3.0.0.rst index 3052f94f22b6..05d1df42d8cb 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-3.0.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-3.0.0.rst @@ -143,7 +143,7 @@ See the following documentation for an overview of which modem firmware versions * `Modem firmware compatibility matrix for the nRF9160 SoC`_ Use the latest version of the `Programmer app`_ of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-3.0.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-3.0.1.rst index 0b06ea0640e8..b0f684e09666 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-3.0.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-3.0.1.rst @@ -43,7 +43,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-3.0.2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-3.0.2.rst index 1dfd1db95721..b7acf02f3823 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-3.0.2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-3.0.2.rst @@ -43,7 +43,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the nRF Programmer app of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-3.1.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-3.1.0.rst index 0e326bb18ef6..7d08b731dcc3 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-3.1.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-3.1.0.rst @@ -122,7 +122,7 @@ See the following documentation for an overview of which modem firmware versions * `Modem firmware compatibility matrix for the nRF9160 SoC`_ Use the latest version of the `Programmer app`_ of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-3.1.1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-3.1.1.rst index 91f5a1e380f3..aa517d6ef07e 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-3.1.1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-3.1.1.rst @@ -76,7 +76,7 @@ Supported modem firmware See `Modem firmware compatibility matrix`_ for an overview of which modem firmware versions have been tested with this version of the |NCS|. Use the latest version of the `Programmer app`_ of `nRF Connect for Desktop`_ to update the modem firmware. -See :ref:`nrf9160_gs_updating_fw_modem` for instructions. +See the `Programming nRF91 Series DK firmware` page for instructions. Modem-related libraries and versions ==================================== diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index 574f0b479715..2bc350bb9029 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -63,7 +63,7 @@ Bootloaders and DFU Developing with nRF91 Series ============================ -|no_changes_yet_note| +* Moved the sections about updating the firmware using the Programmer app to the `Programming nRF91 Series DK firmware`_ tools page. Developing with nRF70 Series ============================ diff --git a/samples/cellular/modem_shell/README.rst b/samples/cellular/modem_shell/README.rst index fd1f260726d2..ddf62c0463b6 100644 --- a/samples/cellular/modem_shell/README.rst +++ b/samples/cellular/modem_shell/README.rst @@ -1038,7 +1038,7 @@ Getting nRF91 Series DK out-of-the-box and to nRF Cloud To program the certificates and connect to nRF Cloud, complete the following steps: 1. `Download nRF Connect for Desktop`_. -#. Update the modem firmware on the on-board modem of the nRF91 Series DK to the latest version as instructed in :ref:`nrf9160_updating_fw_modem`. +#. Update the modem firmware on the on-board modem of the nRF91 Series DK to the latest version as instructed in `Programming nRF91 Series DK firmware`_. #. Build and program the MoSh to the nRF91 Series DK using the default MoSh configuration (with REST as the transport): .. parsed-literal:: From e4649fe9417224e050d9dfdf528c23a649bed373 Mon Sep 17 00:00:00 2001 From: divya pillai Date: Wed, 26 Nov 2025 17:59:44 +0100 Subject: [PATCH 069/155] doc: nRF91 FOTA - Updated to sysbuild nRF91 FOTA - Updated to sysbuild Signed-off-by: divya pillai --- doc/nrf/app_dev/device_guides/nrf91/nrf91_building.rst | 4 ++-- doc/nrf/includes/cert-flashing.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/nrf/app_dev/device_guides/nrf91/nrf91_building.rst b/doc/nrf/app_dev/device_guides/nrf91/nrf91_building.rst index 7b82923b07b9..e2e4f808bbd5 100644 --- a/doc/nrf/app_dev/device_guides/nrf91/nrf91_building.rst +++ b/doc/nrf/app_dev/device_guides/nrf91/nrf91_building.rst @@ -52,8 +52,8 @@ To perform a FOTA update, complete the following steps: In its default configuration, the DFU target library is set to support all the types of FOTA updates except full modem firmware updates, but you can freely enable or disable the support for specific targets. In addition, the following requirements apply: - * To upgrade the application, you must use :doc:`mcuboot:index-ncs` as the upgradable bootloader (:kconfig:option:`CONFIG_BOOTLOADER_MCUBOOT` must be enabled). - * If you want to upgrade the upgradable bootloader, you must use the :ref:`bootloader` (:kconfig:option:`CONFIG_SECURE_BOOT` must be enabled). + * To upgrade the application, use :doc:`mcuboot:index-ncs` as the upgradable bootloader (:kconfig:option:`SB_CONFIG_BOOTLOADER_MCUBOOT` must be enabled). + * If you want to upgrade the upgradable bootloader, use the :ref:`bootloader` (:kconfig:option:`SB_CONFIG_SECURE_BOOT_APPCORE` must be enabled). * If you want to update the modem firmware through modem delta updates, you do not need to use MCUboot or the immutable bootloader, because the modem firmware update is handled by the modem itself. * If you want to perform a full modem firmware update, an |external_flash_size| is required. diff --git a/doc/nrf/includes/cert-flashing.txt b/doc/nrf/includes/cert-flashing.txt index a1907cd3d041..b54ae4537899 100644 --- a/doc/nrf/includes/cert-flashing.txt +++ b/doc/nrf/includes/cert-flashing.txt @@ -1,7 +1,7 @@ To provision the certificates and the private key to the nRF91 Series modem, complete the following steps: 1. `Download nRF Connect for Desktop`_. -#. Update the modem firmware on the onboard modem of the nRF91 Series device to the latest version by following the steps in :ref:`nrf9160_gs_updating_fw_modem`. +#. Update the modem firmware on the onboard modem of the nRF91 Series device to the latest version as instructed in the `Programming nRF91 Series DK firmware`_ page. #. Build and program the :ref:`at_client_sample` sample to the nRF91 Series device as explained in :ref:`building` and :ref:`programming`. #. Launch the `Cellular Monitor app`_ in `nRF Connect for Desktop`_. #. Click :guilabel:`CERTIFICATE MANAGER` located at the upper right corner. From 7381dfe10c60bc874ab18bb5c51a989c66c0c471 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Thu, 13 Nov 2025 09:37:11 +0000 Subject: [PATCH 070/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by Github Action Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index a9369131dde9..18d509853559 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: d2bc88b13d5e8f142cd2abed9e5bdec51c0a7336 + revision: pull/3498/head import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From ab3a3277e7bd519fe44876f9c256b75a73896766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Stasiak?= Date: Thu, 13 Nov 2025 10:45:22 +0100 Subject: [PATCH 071/155] dts: nrf54ls05b: add TAMPC node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Required to make use of SWD pins as GPIOs. Signed-off-by: Michał Stasiak --- dts/common/nordic/nrf54ls05b.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dts/common/nordic/nrf54ls05b.dtsi b/dts/common/nordic/nrf54ls05b.dtsi index 0491e052ed86..c5d01f57ad50 100644 --- a/dts/common/nordic/nrf54ls05b.dtsi +++ b/dts/common/nordic/nrf54ls05b.dtsi @@ -403,6 +403,11 @@ status = "disabled"; }; + tampc: tampc@e7000 { + compatible = "nordic,nrf-tampc"; + reg = <0xe7000 0x1000>; + status = "disabled"; + }; dppic30: dppic@102000 { compatible = "nordic,nrf-dppic"; From 6f95f3353b318086d397d9428e8bc5701701d28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Stasiak?= Date: Thu, 13 Nov 2025 10:46:52 +0100 Subject: [PATCH 072/155] tests: drivers: gpio_swd: allow use of SWD pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using TAMPC feature to use SWD pins as GPIOs. Signed-off-by: Michał Stasiak --- .../gpio_swd/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay | 6 +++++- west.yml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/drivers/gpio/gpio_swd/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay b/tests/drivers/gpio/gpio_swd/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay index 9cf9d56dd8a8..47ba1cd629da 100644 --- a/tests/drivers/gpio/gpio_swd/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay +++ b/tests/drivers/gpio/gpio_swd/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay @@ -9,7 +9,7 @@ * No other driver on out-gpios[n] */ zephyr,user { - out-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>, <&gpio1 31 GPIO_ACTIVE_HIGH>, + out-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>, <&gpio1 31 GPIO_ACTIVE_HIGH>, <&gpio1 29 GPIO_ACTIVE_HIGH>, <&gpio1 30 GPIO_ACTIVE_HIGH>; }; }; @@ -17,3 +17,7 @@ &gpio1 { status = "okay"; }; + +&tampc { + swd-pins-as-gpios; +}; diff --git a/west.yml b/west.yml index 18d509853559..4dbe2866efac 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: pull/3498/head + revision: f3cc078cbe9761282c83b5c6059fd66097ed62c0 import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From a2afc157a5f7cffedf7bde490a3c80e2e0be9ae4 Mon Sep 17 00:00:00 2001 From: Francesco Domenico Servidio Date: Mon, 1 Dec 2025 10:44:48 +0100 Subject: [PATCH 073/155] doc: Cleaned changelog on 3.2.0 RC1 doc: Cleaned changelog on 3.2.0 RC1 Signed-off-by: Francesco Domenico Servidio --- .../releases/release-notes-changelog.rst | 820 ++---------------- 1 file changed, 57 insertions(+), 763 deletions(-) diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index 2bc350bb9029..cc3e61ef698f 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -33,18 +33,12 @@ The following sections provide detailed lists of changes by component. IDE, OS, and tool support ========================= -* Added macOS 26 support (Tier 3) to the table listing :ref:`supported operating systems for proprietary tools `. -* Updated: - - * The required `SEGGER J-Link`_ version to v8.76. - * Steps on the :ref:`install_ncs` page for installing the |NCS| and toolchain together. - With this change, the separate steps to install the toolchain and the SDK were merged into a single step. - * The table listing :ref:`supported operating systems for proprietary tools `: Windows 11 is now Tier 1, Windows 10 is now Tier 3, macOS 15 is now Tier 1, and macOS 13 is now Tier 3. +|no_changes_yet_note| Board support ============= -* Added support for the nRF7002-EB II Wi-Fi shield for use with the nRF54LM20 DK board target. +|no_changes_yet_note| Build and configuration system ============================== @@ -54,11 +48,7 @@ Build and configuration system Bootloaders and DFU =================== -* Added support for extra images in DFU packages (multi-image binary and ZIP). - This allows applications to extend the built-in DFU functionality with additional firmware images beyond those natively supported by the |NCS|, for example, firmware for external devices. - See :ref:`lib_dfu_extra` for details. -* Added an option to restore progress after a power failure when using DFU multi-image with MCUboot. -* Updated the NSIB monotonic counter configuration by moving it to sysbuild where it is now configured using the :kconfig:option:`SB_CONFIG_SECURE_BOOT_MONOTONIC_COUNTER` and :kconfig:option:`SB_CONFIG_SECURE_BOOT_NUM_VER_COUNTER_SLOTS` Kconfig options. +|no_changes_yet_note| Developing with nRF91 Series ============================ @@ -73,12 +63,12 @@ Developing with nRF70 Series Developing with nRF54L Series ============================= -* Added the :ref:`ug_nrf54l_otp_map` page, showing the OTP memory allocation for the nRF54L Series devices. +|no_changes_yet_note| Developing with nRF54H Series ============================= -* Updated the location of the merged binaries in direct-xip mode from :file:`build/zephyr` to :file:`build`. +|no_changes_yet_note| Developing with nRF53 Series ============================ @@ -98,11 +88,7 @@ Developing with Thingy:91 X Developing with Thingy:91 ========================= -* Updated the title of the page about updating the Thingy:91 firmware using the Cellular Monitor app to :ref:`thingy91_update_firmware`. - -* Removed the page about updating the Thingy:91 firmware using the Programmer app and cellular app. - Contents are now available in the app documentation on the `Programming Nordic Thingy prototyping platforms`_ and `Programming Nordic Thingy:91 firmware`_ pages, respectively. - The :ref:`thingy91_partition_layout` section has been moved to the :ref:`thingy91_update_firmware` page. +|no_changes_yet_note| Developing with Thingy:53 ========================= @@ -124,66 +110,10 @@ Developing with custom boards |no_changes_yet_note| -Developing with coprocessors -============================ - -|no_changes_yet_note| - Security ======== -* Added: - - * CRACEN and nrf_oberon driver support for nRF54LM20 and nRF54LV10. - For the list of supported features and limitations, see the :ref:`ug_crypto_supported_features` page. - - * Support for disabling Internal Trusted Storage (ITS) on nRF54L series devices when using - :kconfig:option:`CONFIG_TFM_PARTITION_CRYPTO` with Trusted Firmware-M (TF-M) through the - :kconfig:option:`CONFIG_TFM_PARTITION_INTERNAL_TRUSTED_STORAGE` Kconfig option. - - * Support for AES in counter mode and CBC mode using CRACEN for the :zephyr:board:`nrf54lm20dk`. - - * Experimental support for TF-M on the nRF54LV10A SoC. - * Experimental support for NSIB and MCUBoot on the nRF54LV10A SoC. - * Experimental support for KMU on the nRF54LV10A SoC. - * Experimental support for compression and encryption on the nRF54LV10A SoC. - - * Support for the PureEdDSA and HashEdDSA for Ed448 curve in the :ref:`CRACEN driver `. - * Support for the SHAKE256 hash function with 64-byte and 114-byte digests in the :ref:`CRACEN driver `. - -* Updated: - - * The :ref:`security_index` page with a table that lists the versions of security components implemented in the |NCS|. - * The :ref:`secure_storage_in_ncs` page with updated information about the secure storage configuration in the |NCS|. - Also renamed the page from "Trusted storage in the |NCS|." - * The :ref:`ug_crypto_supported_features` page with the missing entries for the HMAC key type (:kconfig:option:`CONFIG_PSA_WANT_KEY_TYPE_HMAC`). - * The :ref:`ug_nrf54l_crypto_kmu_supported_key_types` section specific for the nRF54L Series devices to list the supported algorithms for each key type. - * The :ref:`ug_nrf54l_developing_provision_kmu` page with more detailed information about requirements for KMU provisioning and steps for provisioning KMU for development and production. - This also led to some updates to the :ref:`ug_nrf54l_crypto_kmu_storing_keys` section on the :ref:`ug_nrf54l_cryptography` page. - -* Removed: - - * Support for curve types smaller than 224 bytes from the :ref:`CRACEN driver `. - * Support for some curve types that were marked as unsupported. - The :ref:`ug_crypto_supported_features` page has been updated accordingly. - -Mbed TLS --------- - -* Updated to version 3.6.5. - -Trusted Firmware-M ------------------- - -* Updated: - - * The TF-M version to 2.2.0. - * Documentation to clarify the support for TF-M on devices emulated using the nRF54L15 DK. - nRF54L05 does not support TF-M. - nRF54L10 supports TF-M experimentally. - -* Removed several documentation pages from the :ref:`tfm_wrapper` section that were misleading or not relevant for understanding the TF-M integration in the |NCS|. - The section now includes only pages that provide background information about TF-M design that are relevant for the |NCS|. +|no_changes_yet_note| Protocols ========= @@ -193,23 +123,12 @@ Protocols Bluetooth® LE ------------- -* Added the :c:func:`bt_nrf_conn_set_ltk` API. - - This API allows you to set a custom Long Term Key (LTK) for a connection. - You can use it when two devices have a shared proprietary method for obtaining an LTK. +|no_changes_yet_note| Bluetooth Mesh -------------- -* Updated the NLC profile configuration system: - - * Introduced individual profile configuration options for better user control. - * Deprecated the :kconfig:option:`CONFIG_BT_MESH_NLC_PERF_CONF` and :kconfig:option:`CONFIG_BT_MESH_NLC_PERF_DEFAULT` Kconfig options. - Existing configurations continue to work but you should migrate to individual profile options. - -* Updated the LE Pairing Responder model: - - * Deprecated the :kconfig:option:`CONFIG_BT_FIXED_PASSKEY` option in favor of the new and supported :kconfig:option:`CONFIG_BT_APP_PASSKEY` option. +|no_changes_yet_note| DECT NR+ -------- @@ -219,15 +138,7 @@ DECT NR+ Enhanced ShockBurst (ESB) ------------------------- -* Added: - - * The :ref:`esb_monitor_mode` feature. - * Experimental support for the nRF54LV10A SoC in the following samples: - - * :ref:`esb_prx` - * :ref:`esb_ptx` - - * A workaround for the hardware errata HMPAN-229 for the nRF54H20 SoC. +|no_changes_yet_note| * Updated: @@ -242,59 +153,12 @@ Gazell Matter ------ -* Added documentation for leveraging Matter Compliant Platform certification through the Derived Matter Product (DMP) process. - See :ref:`ug_matter_platform_and_dmp`. -* Updated to using the :kconfig:option:`CONFIG_PICOLIBC` Kconfig option as the C library instead of :kconfig:option:`CONFIG_NEWLIB_LIBC`, in compliance with Zephyr requirements. -* Removed the ``CONFIG_CHIP_SPI_NOR`` and ``CONFIG_CHIP_QSPI_NOR`` Kconfig options. -* Released the `Matter Quick Start app`_ v1.0.0 as part of nRF Connect for Desktop. -* Deprecated the Matter over Wi-Fi samples that are using nRF5340 SoC (nRF7002 DK and nRF5340 DK with the nRF7002 EK shield attached). - This is mainly due to the very limited non-volatile memory space left for application code. - As an alternative, it is recommended to use the nRF54LM20A SoC in combination with the nRF7002-EB II shield, which provides a significantly greater amount of available non-volatile memory for Matter over Wi-Fi applications. +|no_changes_yet_note| Matter fork +++++++++++ -The Matter fork in the |NCS| (``sdk-connectedhomeip``) contains all commits from the upstream Matter repository up to, and including, the ``v1.5.0.0`` tag. - -* Added: - - * Support for the following new device types: - - * Irrigation System - * Soil Sensor - * Closure - * Closure Panel - * Closure Controller - * Meter Reference Point - * Electrical Energy Tariff - * Electrical Meter - * Electrical Utility Meter - * Camera - * Floodlight Camera - * Video Doorbell - * Snapshot Camera - * Chime - * Camera Controller - * Doorbell - * Intercom - * Audio Doorbell - - * Improved Data Transport by adding full support for operation over TCP transport, which enables more efficient and reliable transmission of large messages. - * The new code-driven approach for the Matter Data Model and Cluster configuration handling. - This approach assumes gradually replacing the configuration based on the ZAP files and the ZAP-generated code, and handling the configuration in the source code. - For example, to enable a specific cluster or its attribute, the new model requires calling a dedicated delegate and registering the cluster in a source code. - The code-driven approach is not yet fully implemented for all the available clusters, but the coverage will be increasing and it is used for the newly created clusters. - The new model is meant to be backward compatible with the previous configuration based on the ZAP files and the ZAP-generated code, until the code-driven approach is fully implemented for all the available clusters. - See the `Migration guide for nRF Connect SDK v3.2.0`_ for more information. - * The :ref:`ug_matter_gs_tools_matter_west_commands_sync` command to synchronize the ZAP and :file:`zcl.json` files after updating the ZAP tool version. - * The check to all :ref:`ug_matter_gs_tools_matter_west_commands_zap_tool` commands that verify whether ZAP tool sandbox permissions are correctly set. - In case of detecting incorrect permissions, the command will prompt the user to accept automatically updating the permissions to required ones. -* Updated: - - * The :ref:`ug_matter_gs_tools_matter_west_commands_append` command to accept ``--clusters`` argument instead of ``new_clusters`` argument. - -* Removed dependencies on Nordic DK-specific configurations in Matter configurations. - See the `Migration guide for nRF Connect SDK v3.2.0`_ for more information. +|no_changes_yet_note| nRF IEEE 802.15.4 radio driver ------------------------------ @@ -304,24 +168,17 @@ nRF IEEE 802.15.4 radio driver Thread ------ -* Updated: - - * The :ref:`thread_sed_ssed` documentation to clarify the impact of the SSED configuration on the device's power consumption and provide a guide for :ref:`thread_ssed_fine_tuning` of SSED devices. - * The platform configuration to use the :kconfig:option:`CONFIG_PICOLIBC` Kconfig opiton as the C library instead of :kconfig:option:`CONFIG_NEWLIB_LIBC`, in compliance with Zephyr requirements. +|no_changes_yet_note| Wi-Fi® ------ -Added: - - * Support for Wi-Fi Direct (P2P) mode, see :ref:`ug_wifi_direct` for details. - * Support for WPA3-SAE using the Oberon PSA PAKE implementation, see :ref:`ug_nrf70_wifi_advanced_security_modes` for details. +|no_changes_yet_note| Applications ============ -* Removed the Serial LTE modem application. - Instead, use `Serial Modem`_, an |NCS| add-on application. +|no_changes_yet_note| Connectivity bridge ------------------- @@ -336,117 +193,32 @@ IPC radio firmware Matter bridge ------------- -* Added: - - * Support for the nRF54LM20 DK working with both Thread and Wi-Fi protocol variants. - For the Wi-Fi protocol variant, the nRF54LM20 DK works with the nRF7002-EB II shield attached. - * The ``matter_bridge list`` command to show a list of all bridged devices and their endpoints. - -* Updated: - - * The application to store a portion of the application code related to the nRF70 Series Wi-Fi firmware in the external flash memory by default. - This change breaks the DFU between the previous |NCS| versions and the upcoming release. - To fix this, you need to disable storing the Wi-Fi firmware patch in external memory. - See the :ref:`migration guide ` for more information. - * By moving code from :file:`samples/matter/common/src/bridge` to :file:`applications/matter_bridge/src/core` and :file:`applications/matter_bridge/src/ble` directories. - * The Identify cluster implementation in the application to use the code-driven approach instead of the zap-driven approach. - * The default number of Bluetooth Low Energy connections that can be selected using the kconfig configuration from ``10`` to ``8`` for the Matter bridge over Thread configuration. +|no_changes_yet_note| nRF5340 Audio ------------- -* Added: - - * A way to store servers in RAM on the unicast client (gateway) side. - The storage does a compare on server address to match multiple servers in a unicast group. - This means that if another device appears with the same address, it will be treated as the same server. - * Experimental support for stereo in :ref:`unicast server application`. - * The :ref:`Audio application API documentation ` page. - * The :ref:`config_audio_app_options` page. - * The API documentation in the header files listed on the :ref:`audio_api` page. - * Ability to connect by address as a unicast client. - -* Updated: - - * The unicast client (gateway) application has been rewritten to support N channels. - * The unicast client (gateway) application now checks if a server has a resolvable address. - If this has not been resolved, the discovery process will start in the identity resolved callback. - * The power measurements to be disabled by default in the default debug versions of the applications. - To enable power measurements, see :ref:`nrf53_audio_app_configuration_power_measurements`. - * The audio application targeting the :zephyr:board:`nrf5340dk` to use pins **P1.5** to **P1.9** for the I2S interface instead of **P0.13** to **P0.17**. - This change was made to avoid conflicts with the onboard peripherals on the nRF5340 DK. - * The documentation pages with information about the :ref:`SD card playback module ` and :ref:`how to enable it `. - * The API documentation in the header files listed on the :ref:`audio_api` page. - -* Removed the LC3 QDID from the :ref:`nrf53_audio_feature_support` page. - The QDID is now listed in the `nRF5340 Bluetooth DNs and QDIDs Compatibility Matrix`_. +|no_changes_yet_note| nRF Desktop ----------- - * Updated: - - * The memory layouts for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target to make more space for the application code. - This change in the partition map of every nRF54LM20 configuration is a breaking change and cannot be performed using DFU. - As a result, the DFU procedure will fail if you attempt to upgrade the application firmware based on one of the |NCS| v3.1 releases. - * The application and MCUboot configurations for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target to use the CRACEN hardware crypto driver instead of the Oberon software crypto driver. - The application image signature is verified with the CRACEN hardware peripheral. - * The MCUboot configurations for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target to use the KMU-based key storage. - The public key used by MCUboot for validating the application image is securely stored in the KMU hardware peripheral. - To simplify the programming procedure, the application is configured to use the automatic KMU provisioning. - The KMU provisioning is performed by the west runner as a part of the ``west flash`` command when the ``--erase`` or ``--recover`` flag is used. - * Application configurations to avoid using the deprecated Kconfig options :ref:`CONFIG_DESKTOP_HID_REPORT_EXPIRATION ` and :ref:`CONFIG_DESKTOP_HID_EVENT_QUEUE_SIZE `. - The configurations rely on Kconfig options specific to HID providers instead. - The HID keypress queue sizes for HID consumer control (:ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_CONSUMER_CTRL_EVENT_QUEUE_SIZE `) and HID system control (:ref:`CONFIG_DESKTOP_HID_REPORT_PROVIDER_SYSTEM_CTRL_EVENT_QUEUE_SIZE `) reports were decreased to ``10``. - * Application configurations integrating the USB legacy stack (:ref:`CONFIG_DESKTOP_USB_STACK_LEGACY `) to suppress build warnings related to deprecated APIs of the USB legacy stack (:kconfig:option:`CONFIG_USB_DEVICE_STACK`). - The configurations enable the :kconfig:option:`CONFIG_DEPRECATION_TEST` Kconfig option to suppress the deprecation warnings. - The USB legacy stack is still used by default. - * MCUboot configurations that support serial recovery over USB CDC ACM to enable the :kconfig:option:`CONFIG_DEPRECATION_TEST` Kconfig option to suppress deprecation warnings. - The implementation of serial recovery over USB CDC ACM still uses the deprecated APIs of the USB legacy stack (:kconfig:option:`CONFIG_USB_DEVICE_STACK`). - * Configurations of the ``nrf52840dongle/nrf52840`` board target to align them after the ``bare`` variant of the board was introduced in Zephyr. - The application did not switch to the ``bare`` board variant to keep backwards compatibility. - * The :ref:`nrf_desktop_hid_state` to allow for delayed registration of HID report providers. - Before the change was introduced, subscribing to a HID input report before the respective provider was registered triggered an assertion failure. - * HID transports (:ref:`nrf_desktop_hids`, :ref:`nrf_desktop_usb_state`) to use the early :c:struct:`hid_report_event` subscription (:c:macro:`APP_EVENT_SUBSCRIBE_EARLY`). - This update improves the reception speed of HID input reports in HID transports. - * The :ref:`nrf_desktop_motion` implementations to align internal state names for consistency. - * The :ref:`nrf_desktop_motion` implementation that generates simulated motion. - Improved the Zephyr shell (:kconfig:option:`CONFIG_SHELL`) integration to prevent potential race conditions related to using preemptive execution context for shell commands. - * The :c:struct:`motion_event` to include information if the sensor is still active or goes to idle state waiting for user activity (:c:member:`motion_event.active`). - The newly added field is filled by all :ref:`nrf_desktop_motion` implementations. - The :ref:`nrf_desktop_hid_provider_mouse` uses the newly added field to improve the synchronization of motion sensor sampling. - After the motion sensor sampling is triggered, the provider waits for the result before submitting a subsequent HID mouse input report. - * The :ref:`nrf_desktop_hid_state_pm` to skip submitting the :c:struct:`keep_alive_event` if the :c:enum:`POWER_MANAGER_LEVEL_ALIVE` power level is enforced by any application module through the :c:struct:`power_manager_restrict_event`. - This is done to improve performance. - * The documentation of the :ref:`nrf_desktop_hid_state` and default HID report providers to simplify getting started with updating HID input reports used by the application or introducing support for a new HID input report. - * The default value of the :kconfig:option:`CONFIG_SOC_FLASH_NRF_RADIO_SYNC_MPSL_NORMAL_PRIORITY_TIMEOUT_US` Kconfig option to ``0``. - This is done to start using high MPSL timeslot priority quicker and speed up non-volatile memory operations. - * The number of preemptive priorities (:kconfig:option:`CONFIG_NUM_PREEMPT_PRIORITIES`). - The Kconfig option value was increased to ``15`` (default value from Zephyr). - The priority of ``10`` is used by default for preemptive contexts (for example, :kconfig:option:`CONFIG_BT_GATT_DM_WORKQ_PRIO` and :kconfig:option:`CONFIG_BT_LONG_WQ_PRIO`). - The previously used Kconfig option value of ``11`` leads to using the same priority for the mentioned preemptive contexts as the lowest available application thread priority (used for example, by the log processing thread). - * Application image configurations to explicitly specify the LED driver used by the :ref:`nrf_desktop_leds` (:kconfig:option:`CONFIG_CAF_LEDS_GPIO` or :kconfig:option:`CONFIG_CAF_LEDS_PWM`). - Also, disabled unused LED drivers enabled by default to reduce memory footprint. - * The :ref:`nrf_desktop_hid_forward` to allow using the module when configuration channel support (:ref:`CONFIG_DESKTOP_CONFIG_CHANNEL_ENABLE `) is disabled in the application configuration. - * The :ref:`nrf_desktop_keys_state` to rely on runtime assertions, ensuring that the initialization function is called only once and other APIs of the utility are called after the utility was initialized. - This is done to align the utility with other application utilities. +|no_changes_yet_note| nRF Machine Learning (Edge Impulse) ----------------------------------- -* Updated: +|no_changes_yet_note| - * The application to change the default libc from the :ref:`zephyr:c_library_newlib` to the :ref:`zephyr:c_library_picolibc` to align with the |NCS| and Zephyr. - * By changing the number of preemptive priorities (:kconfig:option:`CONFIG_NUM_PREEMPT_PRIORITIES`) from ``11`` to default value ``15`` from Zephyr. - The priority of ``10`` is used by default for some preemptive contexts (for example, :kconfig:option:`CONFIG_BT_LONG_WQ_PRIO`). - The previously used Kconfig option value of ``11`` led to using the lowest available application thread priority for the mentioned preemptive contexts, which at the same time is used, for example, by the log processing thread. +Serial LTE modem +---------------- -* Removed support for the ``thingy53/nrf5340/cpuapp/ns`` build target. +|no_changes_yet_note| Thingy:53: Matter weather station --------------------------------- -* Updated the application to use the code-driven approach for the Identify cluster implementation instead of the zap-driven approach. +|no_changes_yet_note| Samples ======= @@ -456,250 +228,27 @@ This section provides detailed lists of changes by :ref:`sample `. Bluetooth samples ----------------- -* Added: - - * The :ref:`ble_shorter_conn_intervals` sample to demonstrate how to use the Bluetooth Shorter Connection Intervals feature. - * The :ref:`bluetooth_path_loss_monitoring` sample. - * The :ref:`samples_test_app` application to demonstrate how to use the Bluetooth LE Test GATT Server and test Bluetooth LE functionality in peripheral samples. - * Experimental support for the nRF54LV10A SoC in the following Bluetooth samples: - - * :ref:`central_and_peripheral_hrs` - * :ref:`central_bas` - * :ref:`bluetooth_central_hids` - * :ref:`bluetooth_central_hr_coded` - * :ref:`bluetooth_central_dfu_smp` - * :ref:`central_uart` - * :ref:`channel_sounding_ras_initiator` - * :ref:`channel_sounding_ras_reflector` - * :ref:`bluetooth_conn_time_synchronization` - * :ref:`direct_test_mode` - * :ref:`direction_finding_connectionless_tx` - * :ref:`direction_finding_peripheral` - * :ref:`ble_event_trigger` - * :ref:`bluetooth_iso_combined_bis_cis` - * :ref:`bluetooth_isochronous_time_synchronization` - * :ref:`ble_llpm` - * :ref:`multiple_adv_sets` - * :ref:`peripheral_bms` - * :ref:`peripheral_cgms` - * :ref:`peripheral_cts_client` - * :ref:`peripheral_gatt_dm` - * :ref:`peripheral_hids_keyboard` - * :ref:`peripheral_hids_mouse` - * :ref:`peripheral_hr_coded` - * :ref:`peripheral_lbs` - * :ref:`peripheral_mds` - * :ref:`power_profiling` - * :ref:`peripheral_rscs` - * :ref:`peripheral_status` - * :ref:`peripheral_uart` - * :ref:`bt_peripheral_with_multiple_identities` - * :ref:`bluetooth_radio_coex_1wire_sample` - * :ref:`ble_radio_notification_conn_cb` - * :ref:`bt_scanning_while_connecting` - * :ref:`shell_bt_nus` - * :ref:`ble_shorter_conn_intervals` - * :ref:`ble_subrating` - * :ref:`ble_throughput` - -* Added the :ref:`bluetooth_automated_power_control` sample. - -* Updated the network core image applications for the following samples from the :zephyr:code-sample:`bluetooth_hci_ipc` sample to the :ref:`ipc_radio` application for multicore builds: - - * :ref:`bluetooth_conn_time_synchronization` - * :ref:`bluetooth_iso_combined_bis_cis` - * :ref:`bluetooth_isochronous_time_synchronization` - * :ref:`bt_scanning_while_connecting` - * :ref:`channel_sounding_ras_initiator` - * :ref:`channel_sounding_ras_reflector` - - The :ref:`ipc_radio` application is commonly used for multicore builds in other |NCS| samples and projects. - Hence, this is to align with the common practice. - -* Disabled legacy pairing in the following samples: - - * :ref:`central_nfc_pairing` - * :ref:`power_profiling` - - Support for legacy pairing remains exclusively for :ref:`peripheral_nfc_pairing` sample to retain compatibility with older Andorid devices. - -* :ref:`direct_test_mode` sample: - - * Updated by simplifying the 2-wire UART polling. - This is done by replacing the hardware timer with the ``k_sleep()`` function. +|no_changes_yet_note| Bluetooth Mesh samples ---------------------- -* Added: - - * Support for external flash settings for the ``nrf52840dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp``, ``nrf54l15dk/nrf54l10/cpuapp``, and ``nrf54l15dk/nrf54l05/cpuapp`` board targets in all Bluetooth Mesh samples. - * Support for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target in all Bluetooth Mesh samples. - -* :ref:`ble_mesh_dfu_distributor` sample: - - * Added: - - * Support for external flash memory for the ``nrf52840dk/nrf52840`` and the ``nrf54l15dk/nrf54l15/cpuapp`` as the secondary partition for the DFU process. - - * Updated: - - * The sample to use the :kconfig:option:`CONFIG_BT_APP_PASSKEY` option instead of the deprecated :kconfig:option:`CONFIG_BT_FIXED_PASSKEY` option. - -* :ref:`ble_mesh_dfu_target` sample: - - * Added: - - * Support for external flash memory for the ``nrf52840dk/nrf52840`` and the ``nrf54l15dk/nrf54l15/cpuapp`` as the secondary partition for the DFU process. - -* :ref:`bluetooth_mesh_sensor_client` sample: - - * Added polling toggle to **Button 1** (**Button 0** on nRF54 DKs) to start/stop the periodic Sensor Get loop, ensuring the functionality is available on all supported devices including single-button hardware. - - * Updated: - - * To demonstrate the Bluetooth :ref:`ug_bt_mesh_nlc` HVAC Integration profile. - - * To use individual NLC profile configurations instead of the deprecated options. - * The sample name to indicate NLC support. - - * Button functions. - Assignments are shifted down one index to accommodate the new polling toggle. - The descriptor action has been removed from button actions but is still available through mesh shell commands. - - * Removed support for the ``nrf52dk/nrf52832``, since it does not have enough RAM space after NLC support was added. - -* :ref:`bluetooth_mesh_sensor_server`: - - * Updated: - - * To use individual NLC profile configurations instead of the deprecated options. - * The sample name to indicate NLC support. - -* :ref:`bluetooth_mesh_light_dim`: - - * Updated: - - * To use individual NLC profile configurations instead of the deprecated options. - * The sample name to indicate NLC support. - -* :ref:`bluetooth_mesh_light_lc`: - - * Updated: - - * To use individual NLC profile configurations instead of the deprecated options. - * The sample name to indicate NLC support. +|no_changes_yet_note| Bluetooth Fast Pair samples --------------------------- -* :ref:`fast_pair_locator_tag` sample: - - * Updated: - - * The memory layout for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target to make more space for the application code. - This change in the nRF54LM20 partition map is a breaking change and cannot be performed using DFU. - As a result, the DFU procedure will fail if you attempt to upgrade the sample firmware based on one of the |NCS| v3.1 releases. - * The application and MCUBoot configurations for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target to use the CRACEN hardware crypto driver instead of the Oberon software crypto driver. - Note, that the Fast Pair subsystem still uses the Oberon software library. - The application image signature is verified with the CRACEN hardware peripheral. - * The MCUBoot configuration for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target to use the KMU-based key storage. - The public key used by MCUboot for validating the application image is securely stored in the KMU hardware peripheral. - To simplify the programming procedure, the samples are configured to use the automatic KMU provisioning. - The KMU provisioning is performed by the west runner as a part of the ``west flash`` command when the ``--erase`` or ``--recover`` flag is used. - -* :ref:`fast_pair_input_device` sample: - - * Updated the application configuration for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target to use the CRACEN hardware crypto driver instead of the Oberon software crypto driver. - Note, that the Fast Pair subsystem still uses the Oberon software library. +|no_changes_yet_note| Cellular samples ---------------- -* Added: - - * The :ref:`nrf_cloud_coap_cell_location` sample to demonstrate how to use the `nRF Cloud CoAP API`_ for nRF Cloud's cellular location service. - * The :ref:`nrf_cloud_coap_fota_sample` sample to demonstrate how to use the `nRF Cloud CoAP API`_ for FOTA updates. - * The :ref:`nrf_cloud_coap_device_message` sample to demonstrate how to use the `nRF Cloud CoAP API`_ for device messages. - * The :ref:`nrf_cloud_mqtt_device_message` sample to demonstrate how to use the `nRF Cloud MQTT API`_ for device messages. - * The :ref:`nrf_cloud_mqtt_fota` sample to demonstrate how to use the `nRF Cloud MQTT API`_ for FOTA updates. - * The :ref:`nrf_cloud_mqtt_cell_location` sample to demonstrate how to use the `nRF Cloud MQTT API`_ for nRF Cloud's cellular location service. - -* Updated the following samples to use the new ``SEC_TAG_TLS_INVALID`` definition: - - * :ref:`modem_shell_application` - * :ref:`http_application_update_sample` - * :ref:`http_modem_delta_update_sample` - * :ref:`http_modem_full_update_sample` - -* Removed: - - * The SLM Shell sample. - Use the sample from `Serial Modem`_ instead. - * The deprecated LTE Sensor Gateway sample. - -* :ref:`nrf_cloud_rest_cell_location` sample: - - * Added runtime setting of the log level for the nRF Cloud logging feature. - -* :ref:`modem_shell_application` sample: - - * Added: - - * Support for environment evaluation using the ``link enveval`` command. - * Support for NTN NB-IoT to the ``link sysmode`` and ``link edrx`` commands. - * Support for Non-Terrestrial Network (NTN) helper functionality using the ``ntn`` command. - - * Updated the PDN connection management to use the PDN functionality in the :ref:`lte_lc_readme` library instead of the :ref:`pdn_readme` library. - -* :ref:`pdn_sample` sample: - - * Updated the PDN functionality to use the PDN management in the :ref:`lte_lc_readme` library instead of the :ref:`pdn_readme` library. - -* :ref:`gnss_sample` sample: - - * Added TLS support for connection to the SUPL server. - -* :ref:`nrf_cloud_multi_service` sample: - - * Fixed an issue where sporadically the application was stuck waiting for the device to connect to the internet. - This was due to wrong :ref:`Connection Manager ` initialization. - * Deprecated the sample. +|no_changes_yet_note| Cryptography samples -------------------- -* Added: - - * Support for the ``nrf54lv10dk/nrf54lv10a/cpuapp`` and ``nrf54lv10dk/nrf54lv10a/cpuapp/ns`` board targets to all samples (except :ref:`crypto_test`). - * Support for the ``nrf54lm20dk/nrf54lm20a/cpuapp/ns`` board target in all supported cryptography samples. - * The :ref:`crypto_kmu_cracen_usage` sample. - -* Updated documentation of all samples for style consistency: added lists of cryptographic features used by each sample and sample output in the testing section. - -* :ref:`crypto_persistent_key` sample: - - * Added support for the ``nrf54h20dk/nrf54h20/cpuapp`` board target, demonstrating use of Internal Trusted Storage (ITS) on the nRF54H20 DK. - -* :ref:`crypto_aes_ctr` sample: - - * Added support for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target. - -* :ref:`crypto_tls` sample: - - * Updated sample-specific Kconfig configuration structure and documentation. - -* :ref:`crypto_aes_ctr` sample: - - * Added support for ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target. - -* :ref:`crypto_aes_cbc` sample: - - * Added support for ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target. - -* :ref:`crypto_persistent_key` sample: - - * Added support for the ``nrf54h20dk/nrf54h20/cpuapp`` board target, demonstrating use of Internal Trusted Storage (ITS) on the nRF54H20 DK. +|no_changes_yet_note| Debug samples ------------- @@ -709,29 +258,7 @@ Debug samples DECT NR+ samples ---------------- -* :ref:`dect_shell_application` sample: - - * Added: - - * ``dect perf`` command client: LBT (Listen Before Talk) support with configurable LBT period and busy threshold. - - * Updated: - - * PCC and PDC printings improved to show SNR and RSSI-2 values with actual dB/dBm resolutions. - * ``dect perf`` command: improved operation schedulings to avoid scheduling conflicts and fix to TX the results in server side. - * ``dect ping`` command: improved operation schedulings to avoid scheduling conflicts. - -DFU samples ------------ - -* Added: - - * The :ref:`dfu_multi_image_sample` sample to demonstrate how to use the :ref:`lib_dfu_target` library. - * The :ref:`ab_sample` sample to demonstrate how to implement the A/B firmware update strategy using :ref:`MCUboot `. - * The :ref:`fw_loader_ble_mcumgr` sample that provides a minimal configuration for firmware loading using SMP over Bluetooth LE. - This sample is intended as a starting point for developing custom firmware loader applications that work with the MCUboot bootloader. - * The :ref:`single_slot_sample` sample to demonstrate how to maximize the available space for the application with MCUboot using firmware loader mode (single-slot layout). - * The :ref:`mcuboot_with_encryption` sample demonstrating how to build MCUboot with image encryption enabled. +|no_changes_yet_note| Edge Impulse samples -------------------- @@ -741,7 +268,7 @@ Edge Impulse samples Enhanced ShockBurst samples --------------------------- -* Added the :ref:`esb_monitor` sample to demonstrate how to use the :ref:`ug_esb` protocol in Monitor mode. +|no_changes_yet_note| Gazell samples -------------- @@ -756,43 +283,12 @@ Keys samples Matter samples -------------- -* Added: - - * The :ref:`matter_temperature_sensor_sample` sample that demonstrates how to implement and test a Matter temperature sensor device. - * The :ref:`matter_contact_sensor_sample` sample that demonstrates how to implement and test a Matter contact sensor device. - * The :ref:`matter_closure_sample` sample that demonstrates how to implement and test a Matter closure device. - * The ``matter_custom_board`` toggle paragraph in the Matter advanced configuration section of all Matter samples that demonstrates how add and configure a custom board. - * Support for the Matter over Wi-Fi on the nRF54LM20 DK with the nRF7002-EB II shield attached to all Matter over Wi-Fi samples. - * Enabled deprecated warnings for all Matter over Wi-Fi samples that are using nRF5340 SoC. - -* Updated: - - * All Matter over Wi-Fi samples and applications to store a portion of the application code related to the nRF70 Series Wi-Fi firmware in the external flash memory by default. - This change breaks the DFU between the previous |NCS| versions and the |NCS| v3.2.0. - To fix this, you need to disable storing the Wi-Fi firmware patch in external memory. - See the :ref:`migration guide ` for more information. - * All Matter samples that support low-power mode to use the :ref:`lib_ram_pwrdn` feature with the nRF54LM20 DK. - This change resulted in decreasing the sleep current consumption by more than two uA. - * All Matter samples to use the code-driven approach for the Identify cluster implementation instead of the zap-driven approach. - -* :ref:`matter_lock_sample` sample: - - * Added a callback for the auto-relock feature. - This resolves the :ref:`known issue ` KRKNWK-20691. - * Updated the NUS service to use the :kconfig:option:`CONFIG_BT_APP_PASSKEY` Kconfig option instead of the deprecated :kconfig:option:`CONFIG_BT_FIXED_PASSKEY` Kconfig option. +|no_changes_yet_note| Networking samples ------------------ -* Added support for the nRF7002-EB II with the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target in the following samples: - - * :ref:`aws_iot` - * :ref:`net_coap_client_sample` - * :ref:`download_sample` - * :ref:`http_server` - * :ref:`https_client` - * :ref:`mqtt_sample` - * :ref:`udp_sample` +|no_changes_yet_note| NFC samples ----------- @@ -837,14 +333,7 @@ SUIT samples Trusted Firmware-M (TF-M) samples --------------------------------- -* :ref:`tfm_hello_world` sample: - - * Added support for the ``nrf54lv10dk/nrf54lv10a/cpuapp/ns`` board target. - * Added support for the ``nrf54lm20dk/nrf54lm20a/cpuapp/ns`` board target. - -* :ref:`tfm_secure_peripheral_partition` - - * Added support for the ``nrf54lm20dk/nrf54lm20a/cpuapp/ns`` board target. +|no_changes_yet_note| Thread samples -------------- @@ -854,35 +343,12 @@ Thread samples Wi-Fi samples ------------- -* Removed support for the nRF7002-EB II with the ``nrf54h20dk/nrf54h20/cpuapp`` board target from the following samples: - - * :ref:`wifi_station_sample` - * :ref:`wifi_scan_sample` - * :ref:`wifi_shell_sample` - * :ref:`wifi_radio_test` - * :ref:`ble_wifi_provision` - * :ref:`wifi_provisioning_internal_sample` +|no_changes_yet_note| Other samples ------------- -* Added experimental support for the nRF54LV10A SoC in the following samples: - - * :ref:`event_manager_proxy_sample` - * :ref:`ipc_service_sample` - - -* Added the :ref:`secondary_boot_sample` sample that demonstrates how to build and boot a secondary application image on the nRF54H20 DK. - -* :ref:`nrf_profiler_sample` sample: - - * Added a new testing step demonstrating how to calculate event propagation statistics. - Also added the related test preset for the :file:`calc_stats.py` script (:file:`nrf/scripts/nrf_profiler/stats_nordic_presets/nrf_profiler.json`). - -* :ref:`app_event_manager_profiling_tracer_sample` sample: - - * Added a new testing step demonstrating how to calculate event propagation statistics. - Also added the related test preset for the :file:`calc_stats.py` script (:file:`nrf/scripts/nrf_profiler/stats_nordic_presets/app_event_manager_profiler_tracer.json`). +|no_changes_yet_note| Drivers ======= @@ -897,38 +363,22 @@ Wi-Fi drivers Flash drivers ------------- -* Added a Kconfig option to configure timeout for normal priority MPSL request (:kconfig:option:`CONFIG_SOC_FLASH_NRF_RADIO_SYNC_MPSL_NORMAL_PRIORITY_TIMEOUT_US`) in MPSL flash synchronization driver (:file:`nrf/drivers/mpsl/flash_sync/flash_sync_mpsl.c`). - After the timeout specified by this Kconfig option, a higher timeslot priority is used to increase the priority of the flash operation. - The default timeout has been reduced from 30 milliseconds to 10 milliseconds to speed up non-volatile memory operations. +|no_changes_yet_note| Libraries ========= This section provides detailed lists of changes by :ref:`library `. - * :ref:`nrf_security_readme` library: - - * The ``CONFIG_CRACEN_PROVISION_PROT_RAM_INV_DATA`` Kconfig option has been renamed to :kconfig:option:`CONFIG_CRACEN_PROVISION_PROT_RAM_INV_SLOTS_ON_INIT`. - Binary libraries ---------------- -* :ref:`liblwm2m_carrier_readme` library: - - * Updated: - - * The glue layer to manage PDN connections using the PDN management functionality in the :ref:`lte_lc_readme` library when the :kconfig:option:`CONFIG_LTE_LC_PDN_MODULE` Kconfig option is enabled, or direct AT commands otherwise. - - * Removed the dependency on the deprecated :ref:`pdn_readme` library. +|no_changes_yet_note| Bluetooth libraries and services -------------------------------- -* :ref:`hids_readme` library: - - * Updated the report length of the HID boot mouse to ``3``. - The :c:func:`bt_hids_boot_mouse_inp_rep_send` function only allows to provide the state of the buttons and mouse movement (for both X and Y axes). - No additional data can be provided by the application. +|no_changes_yet_note| Common Application Framework ---------------------------- @@ -943,7 +393,7 @@ Debug libraries DFU libraries ------------- -* Added new library :ref:`lib_dfu_extra`. +|no_changes_yet_note| Gazell libraries ---------------- @@ -953,74 +403,12 @@ Gazell libraries Security libraries ------------------ -* :ref:`trusted_storage_readme` library: - - * Updated the API documentation to be based on headers in :file:`subsys/trusted_storage/include/psa` instead of :file:`include/`. - * Removed the :file:`internal_trusted_storage.h` and :file:`protected_storage.h` files from :file:`include/` as they were duplicating the same files in :file:`subsys/trusted_storage/include/psa`. +|no_changes_yet_note| Modem libraries --------------- -* Added the :ref:`lib_ntn` library to provide helper functionality for Non-Terrestrial Network (NTN) usage. - -* Removed: - - * The AT command parser library. - Use the :ref:`at_parser_readme` library instead. - * The AT parameters library. - * The Modem SLM library. - Use the library from `Serial Modem`_ instead. - -* :ref:`lte_lc_readme` library: - - * Added: - - * Support for environment evaluation. - * Support for NTN NB-IoT system mode. - * eDRX support for NTN NB-IoT. - * Support for new modem events :c:enumerator:`LTE_LC_MODEM_EVT_RF_CAL_NOT_DONE`, :c:enumerator:`LTE_LC_MODEM_EVT_INVALID_BAND_CONF`, and :c:enumerator:`LTE_LC_MODEM_EVT_DETECTED_COUNTRY`. - * Description of new features supported by mfw_nrf91x1 and mfw_nrf9151-ntn in receive only functional mode. - * Sending of the ``LTE_LC_EVT_PSM_UPDATE`` event with ``tau`` and ``active_time`` set to ``-1`` when registration status is ``LTE_LC_NW_REG_NOT_REGISTERED``. - * New registration statuses and functional modes for the ``mfw_nrf9151-ntn`` modem firmware. - * Support for PDP context and PDN connection management. - The functionality is available when the :kconfig:option:`CONFIG_LTE_LC_PDN_MODULE` Kconfig option is enabled. - * Support for also disabling the default modules that are enabled by default. - This is useful when the application only needs a subset of the functionality provided by the library and to reduce the size of the application image. - To disable a module, set the corresponding ``CONFIG_LTE_LC__MODULE`` Kconfig option to ``n``. - - * Updated: - - * The type of the :c:member:`lte_lc_evt.modem_evt` field to :c:struct:`lte_lc_modem_evt`. - * Replaced modem events ``LTE_LC_MODEM_EVT_CE_LEVEL_0``, ``LTE_LC_MODEM_EVT_CE_LEVEL_1``, ``LTE_LC_MODEM_EVT_CE_LEVEL_2`` and ``LTE_LC_MODEM_EVT_CE_LEVEL_3`` with the :c:enumerator:`LTE_LC_MODEM_EVT_CE_LEVEL` modem event. - * The order of the ``LTE_LC_MODEM_EVT_SEARCH_DONE`` modem event, and registration and cell related events. - See the :ref:`migration guide ` for more information. - - * Fixed an issue where band lock, RAI notification subscription, and DNS fallback address were lost when the modem was put into :c:enumerator:`LTE_LC_FUNC_MODE_POWER_OFF` functional mode. - -* :ref:`nrf_modem_lib_readme` library: - - * Added the :c:func:`nrf_modem_lib_trace_peek_at` function to the :c:struct:`nrf_modem_lib_trace_backend` interface to peek trace data at a byte offset without consuming it. - Support for this API has been added to the flash trace backend. - - * Updated the PDN functionality to use the PDN management in the :ref:`lte_lc_readme` library instead of the :ref:`pdn_readme` library. - - * Removed the deprecated ``CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART_ZEPHYR`` Kconfig option. - -* :ref:`at_parser_readme` library: - - * Fixed an issue where an unquoted string parameter in the middle of a response would not be parsed correctly. - -* :ref:`pdn_readme` library: - - * Deprecated the library. - Use the PDN management functionality in the :ref:`lte_lc_readme` library instead. - - * Fixed: - - * An issue where wrong APN rate control event was sent. - * An issue where a malformed +CGEV notification was not handled correctly. - - * Removed the deprecated ``pdn_dynamic_params_get()`` function. +|no_changes_yet_note| Multiprotocol Service Layer libraries ------------------------------------- @@ -1030,61 +418,7 @@ Multiprotocol Service Layer libraries Libraries for networking ------------------------ -* Added missing brackets that caused C++ compilation to fail in the following libraries: - - * :ref:`lib_nrf_cloud_pgps` - * :ref:`lib_nrf_cloud_fota` - -* Updated the following libraries to use the new ``SEC_TAG_TLS_INVALID`` definition for checking whether a security tag is valid: - - * :ref:`lib_aws_fota` - * :ref:`lib_fota_download` - * :ref:`lib_ftp_client` - -* Removed the Download client library. - Use the :ref:`lib_downloader` library instead. - -* :ref:`lib_nrf_provisioning` library: - - * Added a blocking call to wait for a functional-mode change, relocating the logic from the app into the library. - - * Updated: - - * By making internal scheduling optional. - Applications can now trigger provisioning manually using the :kconfig:option:`CONFIG_NRF_PROVISIONING_SCHEDULED` Kconfig option. - * By moving root CA provisioning to modem initialization callback to avoid blocking and ensure proper state. - * By expanding the event handler to report more provisioning events, including failures. - * By making the event handler callback mandatory to notify the application of failures and prevent silent errors. - * By unifying the device‐mode and modem‐mode callbacks into a single handler for cleaner integration. - * The documentation and sample code accordingly. - - * Fixed multiple bugs and enhanced error handling. - -* :ref:`lib_nrf_cloud_rest` library: - - * Deprecated the library. - Use the :ref:`lib_nrf_cloud_coap` library instead. - -* :ref:`lib_nrf_cloud_fota` library: - - * Fixed occasional message truncation notifying that the download was complete. - -* :ref:`lib_nrf_cloud_log` library: - - * Updated by adding a missing CONFIG prefix. - -* :ref:`lib_nrf_cloud` library: - - * Added the :c:func:`nrf_cloud_obj_location_request_create_timestamped` function to make location requests for past cellular or Wi-Fi scans. - * Updated: - - * By refactoring the folder structure of the library to separate the different backend implementations. - * Handling of ports, which led to confusing log messages with byte-inversed values. - -* :ref:`lib_downloader` library: - - * Fixed an issue where HTTP download would hang if the application had not set the socket receive timeout and data flow from the server stopped. - The HTTP transport now sets the socket receive timeout to 30 seconds by default. +|no_changes_yet_note| Libraries for NFC ----------------- @@ -1099,13 +433,7 @@ nRF RPC libraries Other libraries --------------- -* :ref:`nrf_profiler` library: - - * Updated the documentation by separating out the :ref:`nrf_profiler_script` documentation. - -* :ref:`lib_ram_pwrdn` library: - - * Added support for the nRF54LM20A SoC. +|no_changes_yet_note| Shell libraries --------------- @@ -1120,16 +448,7 @@ See the changelog for each library in the :doc:`nrfxlib documentation Date: Thu, 27 Nov 2025 15:25:40 +0000 Subject: [PATCH 074/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3551 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 4dbe2866efac..d487f77a23fb 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: f3cc078cbe9761282c83b5c6059fd66097ed62c0 + revision: ed09d97b549002e9534e23827b4e190ce6b1e40d import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From b1214a7e435fd28947029d06feacdf9fc6f66b3e Mon Sep 17 00:00:00 2001 From: Triveni Danda Date: Tue, 2 Dec 2025 13:11:37 +0530 Subject: [PATCH 075/155] samples: wifi: wfa_qt_app: Fix enterprise build with SLIP This change fixes the QuickTrack sample enterprise build when using the SLIP configuration.`NET_L2_WIFI_SHELL` is required to ensure that the enterprise test certificates are included. Signed-off-by: Triveni Danda --- samples/wifi/wfa_qt_app/overlay-slip.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/samples/wifi/wfa_qt_app/overlay-slip.conf b/samples/wifi/wfa_qt_app/overlay-slip.conf index 1d5e5c98dc92..98fb0591dff0 100644 --- a/samples/wifi/wfa_qt_app/overlay-slip.conf +++ b/samples/wifi/wfa_qt_app/overlay-slip.conf @@ -4,7 +4,6 @@ CONFIG_SLIP_TAP=y CONFIG_SLIP_MAC_ADDR="00:00:00:00:00:01" # Shell should be disabled for SLIP to work -CONFIG_NET_L2_WIFI_SHELL=n CONFIG_NET_SHELL=n CONFIG_DEVICE_SHELL=n CONFIG_DATE_SHELL=n From 5bdd05ed95d7584b9ab025739dac6c75f6ce2b28 Mon Sep 17 00:00:00 2001 From: Triveni Danda Date: Tue, 2 Dec 2025 15:54:58 +0530 Subject: [PATCH 076/155] samples: wifi: wfa_qt_app: Add 7002DK with SLIP and enterprise test Add 7002DK with SLIP and enterprise configuration test to twister. Signed-off-by: Triveni Danda --- samples/wifi/wfa_qt_app/sample.yaml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/samples/wifi/wfa_qt_app/sample.yaml b/samples/wifi/wfa_qt_app/sample.yaml index 5426d3bc94ac..24f54a104a54 100644 --- a/samples/wifi/wfa_qt_app/sample.yaml +++ b/samples/wifi/wfa_qt_app/sample.yaml @@ -12,7 +12,7 @@ tests: - ci_build - sysbuild - ci_samples_wifi - sample.nrf7002.enterprise_mode.wfa_qt_app: + sample.nrf7002.enterprise_mode.wfa_qt_app.netusb: sysbuild: true build_only: true extra_args: @@ -25,6 +25,20 @@ tests: - ci_build - sysbuild - ci_samples_wifi + sample.nrf7002.enterprise_mode.wfa_qt_app.slip: + sysbuild: true + build_only: true + extra_args: + - EXTRA_CONF_FILE="overlay-slip.conf;overlay-enterprise.conf" + - EXTRA_DTC_OVERLAY_FILE="nrf7002_uart_pipe.overlay" + - wfa_qt_app_SNIPPET="wifi-enterprise" + integration_platforms: + - nrf7002dk/nrf5340/cpuapp + platform_allow: nrf7002dk/nrf5340/cpuapp + tags: + - ci_build + - sysbuild + - ci_samples_wifi sample.nrf7002_eks.wfa_qt_app: sysbuild: true build_only: true From 9ed6863401c6131b097a92afbefa649bbdb2cbf7 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Tue, 2 Dec 2025 14:43:44 +0000 Subject: [PATCH 077/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3580 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index d487f77a23fb..a9bf158ba360 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: ed09d97b549002e9534e23827b4e190ce6b1e40d + revision: fc695cbbf493d4a50e6d6c48fb0d87ebaebba998 import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From f83904b660f21dd5d4b4c12b0ad7e2f39ee2827b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag=20Erik=20Gj=C3=B8rvad?= Date: Tue, 2 Dec 2025 14:29:01 +0100 Subject: [PATCH 078/155] nrf_security: CRACEN: Fix issue with hanging IKG on CRACEN lite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix an issue with the IKG hanging in some /ns builds. This was due to a previously fixed issue with entropy errors in CRACEN lite due to misconfiguration of the TRNG. This was solved by updating the repeat threshold and propthreshold values, but this only happened when the TRNG was opened, which mean it would still fail silently for IKG operations. Signed-off-by: Dag Erik Gjørvad --- .../src/drivers/cracen/cracenpsa/src/cracen.c | 11 +++++++++++ .../cracen/sxsymcrypt/include/sxsymcrypt/trng.h | 15 +++++++++++++++ .../src/drivers/cracen/sxsymcrypt/src/trng.c | 16 ++++++++++------ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen.c index 5b27284d636d..22bd7c42e76c 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen.c @@ -16,6 +16,7 @@ #include "common.h" #include "microcode_binary.h" #include +#include #if !defined(CONFIG_BUILD_WITH_TFM) #define LOG_ERR_MSG(msg) LOG_ERR(msg) @@ -60,6 +61,16 @@ void cracen_acquire(void) CRACEN_ENABLE_PKEIKG_Msk); irq_enable(CRACEN_IRQn); LOG_DBG_MSG("Powered on CRACEN."); + +#ifdef CONFIG_CRACEN_HW_VERSION_LITE + /* CRACEN Lite TRNG workaround. Configure TRNG test thresholds after power-on. + * The IKG's internal PRNG directly accesses the TRNG hardware, but these + * registers reset to incorrect default values when CRACEN is powered down. + * We must reconfigure them every time CRACEN powers up to prevent entropy + * errors in IKG operations. + */ + sx_trng_configure_cracen_lite_workaround(); +#endif /* CONFIG_CRACEN_HW_VERSION_LITE */ } nrf_security_mutex_unlock(cracen_mutex); diff --git a/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/include/sxsymcrypt/trng.h b/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/include/sxsymcrypt/trng.h index e03e4a65aeee..f2db7ca4c026 100644 --- a/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/include/sxsymcrypt/trng.h +++ b/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/include/sxsymcrypt/trng.h @@ -208,6 +208,21 @@ int sx_trng_restore_state(struct sx_trng *ctx, const struct sx_trng_config *conf */ void sx_trng_restart(struct sx_trng *ctx); +#if defined(CONFIG_CRACEN_HW_VERSION_LITE) +/** Configure CRACEN Lite TRNG test threshold registers + * + * This function configures the TRNG REPEATTHRESHOLD and PROPTHRESHOLD registers + * with values that work around incorrect hardware defaults on CRACEN Lite. + * + * This must be called after CRACEN is powered on to ensure the IKG's internal + * CTR-DRBG can access the TRNG without entropy errors. The registers are lost + * when CRACEN powers down and must be reconfigured on every power-up. + * + * This function is safe to call even when the TRNG is not yet enabled. + */ +void sx_trng_configure_cracen_lite_workaround(void); +#endif + #ifdef __cplusplus } #endif diff --git a/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/src/trng.c b/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/src/trng.c index c9ff3ce5edc4..7836d1236ffc 100644 --- a/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/src/trng.c +++ b/subsys/nrf_security/src/drivers/cracen/sxsymcrypt/src/trng.c @@ -30,7 +30,13 @@ #if defined(CONFIG_CRACEN_HW_VERSION_LITE) #define RNG_REPEATTHRESHOLD_VAL (21) #define RNG_PROPTESTCUTOFF_VAL (311) -#endif + +void sx_trng_configure_cracen_lite_workaround(void) +{ + sx_wr_trng(BA431_REG_REPEATTHRESHOLD, RNG_REPEATTHRESHOLD_VAL); + sx_wr_trng(BA431_REG_PROPTHRESHOLD, RNG_PROPTESTCUTOFF_VAL); +} +#endif /* CONFIG_CRACEN_HW_VERSION_LITE */ static int ba431_check_state(void) { @@ -120,12 +126,10 @@ int sx_trng_open(struct sx_trng *ctx, const struct sx_trng_config *config) sx_wr_trng(BA431_REG_ClkDiv_OFST, rng_clkdiv); sx_wr_trng(BA431_REG_InitWaitVal_OFST, rng_init_wait_val); - /* CRACEN Lite has incorrect values for the TRNG tests. We update these here as a workaround + /* Note that CRACEN Lite TRNG test threshold registers (REPEATTHRESHOLD and PROPTHRESHOLD) + * are configured in cracen_acquire() to ensure they're set correctly on every power-up, + * including for IKG operations that access the TRNG hardware directly. */ -#if defined(CONFIG_CRACEN_HW_VERSION_LITE) - sx_wr_trng(BA431_REG_REPEATTHRESHOLD, RNG_REPEATTHRESHOLD_VAL); - sx_wr_trng(BA431_REG_PROPTHRESHOLD, RNG_PROPTESTCUTOFF_VAL); -#endif /* CONFIG_CRACEN_HW_VERSION_LITE */ /* Configure the control register and set the enable bit */ control = (RNG_NB_128BIT_BLOCKS << BA431_FLD_Control_Nb128BitBlocks_LSB); From 53e6e4053ab24ae4e1ee58bf0c10595669c78516 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Tue, 2 Dec 2025 14:50:14 +0100 Subject: [PATCH 079/155] tests: benchmarks: current_consumption: system_off: lv10/ns config Use TF-M system off service for lv10/ns. Signed-off-by: Piotr Kosycarz --- .../system_off/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/benchmarks/current_consumption/system_off/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf diff --git a/tests/benchmarks/current_consumption/system_off/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf b/tests/benchmarks/current_consumption/system_off/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf new file mode 100644 index 000000000000..6cd2bff57223 --- /dev/null +++ b/tests/benchmarks/current_consumption/system_off/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf @@ -0,0 +1,2 @@ +CONFIG_TFM_SFN=y +CONFIG_TFM_NRF_SYSTEM_OFF_SERVICE=y From 7d133afc72237465d72006a006cd798ab0d6f560 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 2 Dec 2025 16:09:30 +0530 Subject: [PATCH 080/155] samples: net: mqtt: Fix nRF54L15 Wi-Fi boot failure nRF54l15DK LED1 and nRF7002EB2 both use GPIO1.10, so, disable the LED feature in this sample for now while we address the actual conflict. Fixes SHEL-3797. Signed-off-by: Chaitanya Tata --- samples/net/mqtt/src/modules/led/Kconfig.led | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/samples/net/mqtt/src/modules/led/Kconfig.led b/samples/net/mqtt/src/modules/led/Kconfig.led index 7c04bf9e11f0..e2e34666e810 100644 --- a/samples/net/mqtt/src/modules/led/Kconfig.led +++ b/samples/net/mqtt/src/modules/led/Kconfig.led @@ -4,10 +4,18 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # +# Hidden symbol to group conditions +config NRF7002EB2_NRF54L15DK_LED1_CONFLICT + bool + default y if (SHIELD_NRF7002EB2 || SHIELD_NRF7002EB2_NRF7001 || \ + SHIELD_NRF7002EB2_NRF7000) && BOARD_NRF54L15DK + + menuconfig MQTT_SAMPLE_LED bool "LED" + depends on !NRF7002EB2_NRF54L15DK_LED1_CONFLICT select LED - default y if !BOARD_NATIVE_SIM + default y if !BOARD_NATIVE_SIM && !NRF7002EB2_NRF54L15DK_LED1_CONFLICT if MQTT_SAMPLE_LED From eeb4e3447ea9bd5c212363951d02a6b29468cced Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Wed, 3 Dec 2025 03:51:13 +0530 Subject: [PATCH 081/155] manifest: sdk-nrfxlib: Pull fix for QT SVD tests Fix QT SVD tests, SHEL-3939. Signed-off-by: Chaitanya Tata --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index a9bf158ba360..3bd6c35e5dad 100644 --- a/west.yml +++ b/west.yml @@ -143,7 +143,7 @@ manifest: - name: nrfxlib repo-path: sdk-nrfxlib path: nrfxlib - revision: 86b79e3269b6322d4113e5a34f966a1a9cbb0fa7 + revision: 68e1843243c6719578c3d6680d77d981e9801bf2 - name: trusted-firmware-m repo-path: sdk-trusted-firmware-m path: modules/tee/tf-m/trusted-firmware-m From 3d98c515219e56f85ec5c1c879bc5d59eadfbfb6 Mon Sep 17 00:00:00 2001 From: Andrei Urs-Hadadea Date: Wed, 26 Nov 2025 17:02:26 +0200 Subject: [PATCH 082/155] nrf_security: PSA crypto driver wrapper redundant status tests. Jira:NCSDK-31607 Signed-off-by: Andrei Urs-Hadadea --- .../src/psa_crypto_driver_wrappers.c | 118 ++++-------------- 1 file changed, 23 insertions(+), 95 deletions(-) diff --git a/subsys/nrf_security/src/psa_crypto_driver_wrappers.c b/subsys/nrf_security/src/psa_crypto_driver_wrappers.c index 166b608cbfea..5b33c73af36b 100644 --- a/subsys/nrf_security/src/psa_crypto_driver_wrappers.c +++ b/subsys/nrf_security/src/psa_crypto_driver_wrappers.c @@ -184,10 +184,7 @@ psa_status_t psa_driver_wrapper_init(void) #endif /* PSA_CRYPTO_DRIVER_TFM_BUILTIN_KEY_LOADER */ #if defined(CONFIG_HW_UNIQUE_KEY_WRITE_ON_CRYPTO_INIT) - status = hw_unique_key_provisioning(); - if (status != PSA_SUCCESS) { - return status; - } + return hw_unique_key_provisioning(); #endif /* CONFIG_HW_UNIQUE_KEY_WRITE_ON_CRYPTO_INIT */ return PSA_SUCCESS; @@ -363,12 +360,8 @@ psa_status_t psa_driver_wrapper_sign_hash(const psa_key_attributes_t *attributes } #endif /* PSA_NEED_CC3XX_ASYMMETRIC_SIGNATURE_DRIVER */ #if defined(PSA_NEED_OBERON_ASYMMETRIC_SIGNATURE_DRIVER) - status = oberon_sign_hash(attributes, key_buffer, key_buffer_size, alg, hash, + return oberon_sign_hash(attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_ASYMMETRIC_SIGNATURE_DRIVER */ /* Fell through, meaning nothing supports this operation */ (void)attributes; @@ -431,13 +424,8 @@ psa_status_t psa_driver_wrapper_verify_hash(const psa_key_attributes_t *attribut } #endif /* PSA_NEED_CC3XX_ASYMMETRIC_SIGNATURE_DRIVER */ #if defined(PSA_NEED_OBERON_ASYMMETRIC_SIGNATURE_DRIVER) - status = oberon_verify_hash(attributes, key_buffer, key_buffer_size, alg, hash, + return oberon_verify_hash(attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length); - - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_ASYMMETRIC_SIGNATURE_DRIVER */ /* Fell through, meaning nothing supports this operation */ (void)attributes; @@ -596,9 +584,8 @@ psa_status_t psa_driver_wrapper_generate_key(const psa_key_attributes_t *attribu #if defined(PSA_NEED_CRACEN_KMU_DRIVER) case PSA_KEY_LOCATION_CRACEN_KMU: - status = cracen_generate_key(attributes, key_buffer, key_buffer_size, + return cracen_generate_key(attributes, key_buffer, key_buffer_size, key_buffer_length); - return status; #endif default: @@ -670,9 +657,8 @@ psa_status_t psa_driver_wrapper_import_key(const psa_key_attributes_t *attribute #if defined(PSA_NEED_CRACEN_KMU_DRIVER) case PSA_KEY_LOCATION_CRACEN: case PSA_KEY_LOCATION_CRACEN_KMU: - status = cracen_import_key(attributes, data, data_length, key_buffer, + return cracen_import_key(attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits); - return status; #endif default: @@ -810,7 +796,6 @@ psa_status_t psa_driver_wrapper_copy_key(psa_key_attributes_t *attributes, uint8_t *target_key_buffer, size_t target_key_buffer_size, size_t *target_key_buffer_length) { - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(attributes->lifetime); switch (location) { @@ -831,9 +816,8 @@ psa_status_t psa_driver_wrapper_copy_key(psa_key_attributes_t *attributes, (void)target_key_buffer; (void)target_key_buffer_size; (void)target_key_buffer_length; - status = PSA_ERROR_INVALID_ARGUMENT; + return PSA_ERROR_INVALID_ARGUMENT; } - return status; } psa_status_t psa_driver_wrapper_derive_key(const psa_key_attributes_t *attributes, @@ -865,12 +849,8 @@ psa_status_t psa_driver_wrapper_derive_key(const psa_key_attributes_t *attribute #endif /* PSA_NEED_CRACEN_KEY_MANAGEMENT_DRIVER */ #ifdef PSA_NEED_OBERON_KEY_MANAGEMENT_DRIVER - status = oberon_derive_key(attributes, input, input_length, key_buffer, + return oberon_derive_key(attributes, input, input_length, key_buffer, key_buffer_size, key_buffer_length); - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_KEY_MANAGEMENT_DRIVER */ break; @@ -933,14 +913,9 @@ psa_status_t psa_driver_wrapper_cipher_encrypt(const psa_key_attributes_t *attri } #endif /* PSA_NEED_CC3XX_CIPHER_DRIVER */ #if defined(PSA_NEED_OBERON_CIPHER_DRIVER) - status = oberon_cipher_encrypt(attributes, key_buffer, key_buffer_size, alg, iv, + return oberon_cipher_encrypt(attributes, key_buffer, key_buffer_size, alg, iv, iv_length, input, input_length, output, output_size, output_length); - - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_CIPHER_DRIVER */ (void)attributes; (void)key_buffer; @@ -1012,12 +987,8 @@ psa_status_t psa_driver_wrapper_cipher_decrypt(const psa_key_attributes_t *attri } #endif /* PSA_NEED_CC3XX_CIPHER_DRIVER */ #if defined(PSA_NEED_OBERON_CIPHER_DRIVER) - status = oberon_cipher_decrypt(attributes, key_buffer, key_buffer_size, alg, input, + return oberon_cipher_decrypt(attributes, key_buffer, key_buffer_size, alg, input, input_length, output, output_size, output_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_CIPHER_DRIVER */ return PSA_ERROR_NOT_SUPPORTED; default: @@ -1085,10 +1056,7 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup(psa_cipher_operation_t *ope if (status == PSA_SUCCESS) { operation->id = PSA_CRYPTO_OBERON_DRIVER_ID; } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } + return status; #endif /* PSA_NEED_OBERON_CIPHER_DRIVER */ return PSA_ERROR_NOT_SUPPORTED; default: @@ -1151,10 +1119,7 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup(psa_cipher_operation_t *ope if (status == PSA_SUCCESS) { operation->id = PSA_CRYPTO_OBERON_DRIVER_ID; } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } + return status; #endif /* PSA_NEED_OBERON_CIPHER_DRIVER */ return PSA_ERROR_NOT_SUPPORTED; default: @@ -1312,10 +1277,7 @@ psa_status_t psa_driver_wrapper_hash_compute(psa_algorithm_t alg, const uint8_t } #endif /* PSA_NEED_CC3XX_HASH_DRIVER */ #if defined(PSA_NEED_OBERON_HASH_DRIVER) - status = oberon_hash_compute(alg, input, input_length, hash, hash_size, hash_length); - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } + return oberon_hash_compute(alg, input, input_length, hash, hash_size, hash_length); #endif /* PSA_NEED_OBERON_HASH_DRIVER */ (void)status; @@ -1365,10 +1327,7 @@ psa_status_t psa_driver_wrapper_hash_setup(psa_hash_operation_t *operation, psa_ if (status == PSA_SUCCESS) { operation->id = PSA_CRYPTO_OBERON_DRIVER_ID; } - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } + return status; #endif /* PSA_NEED_OBERON_HASH_DRIVER */ /* Nothing left to try if we fall through here */ @@ -1521,14 +1480,10 @@ psa_status_t psa_driver_wrapper_aead_encrypt(const psa_key_attributes_t *attribu } #endif /* PSA_NEED_CC3XX_AEAD_DRIVER */ #if defined(PSA_NEED_OBERON_AEAD_DRIVER) - status = oberon_aead_encrypt(attributes, key_buffer, key_buffer_size, alg, nonce, + return oberon_aead_encrypt(attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, additional_data, additional_data_length, plaintext, plaintext_length, ciphertext, ciphertext_size, ciphertext_length); - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_AEAD_DRIVER */ (void)attributes; (void)key_buffer; @@ -1598,14 +1553,10 @@ psa_status_t psa_driver_wrapper_aead_decrypt(const psa_key_attributes_t *attribu } #endif /* PSA_NEED_CC3XX_AEAD_DRIVER */ #if defined(PSA_NEED_OBERON_AEAD_DRIVER) - status = oberon_aead_decrypt(attributes, key_buffer, key_buffer_size, alg, nonce, + return oberon_aead_decrypt(attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, additional_data, additional_data_length, ciphertext, ciphertext_length, plaintext, plaintext_size, plaintext_length); - - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_AEAD_DRIVER */ (void)attributes; @@ -1678,10 +1629,7 @@ psa_status_t psa_driver_wrapper_aead_encrypt_setup(psa_aead_operation_t *operati operation->id = PSA_CRYPTO_OBERON_DRIVER_ID; } - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } + return status; #endif /* PSA_NEED_OBERON_AEAD_DRIVER*/ (void)operation; @@ -1744,10 +1692,7 @@ psa_status_t psa_driver_wrapper_aead_decrypt_setup(psa_aead_operation_t *operati operation->id = PSA_CRYPTO_OBERON_DRIVER_ID; } - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } + return status; #endif /* PSA_NEED_OBERON_AEAD_DRIVER */ (void)operation; @@ -2008,12 +1953,8 @@ psa_status_t psa_driver_wrapper_mac_compute(const psa_key_attributes_t *attribut } #endif /* PSA_NEED_CC3XX_MAC_DRIVER */ #if defined(PSA_NEED_OBERON_MAC_DRIVER) - status = oberon_mac_compute(attributes, key_buffer, key_buffer_size, alg, input, + return oberon_mac_compute(attributes, key_buffer, key_buffer_size, alg, input, input_length, mac, mac_size, mac_length); - /* Declared with fallback == true */ - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_MAC_DRIVER */ return PSA_ERROR_NOT_SUPPORTED; default: @@ -2082,9 +2023,7 @@ psa_status_t psa_driver_wrapper_mac_sign_setup(psa_mac_operation_t *operation, if (status == PSA_SUCCESS) { operation->id = PSA_CRYPTO_OBERON_DRIVER_ID; } - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } + return status; #endif /* PSA_NEED_OBERON_MAC_DRIVER */ return PSA_ERROR_NOT_SUPPORTED; @@ -2149,9 +2088,7 @@ psa_status_t psa_driver_wrapper_mac_verify_setup(psa_mac_operation_t *operation, if (status == PSA_SUCCESS) { operation->id = PSA_CRYPTO_OBERON_DRIVER_ID; } - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } + return status; #endif /* PSA_NEED_OBERON_MAC_DRIVER */ return PSA_ERROR_NOT_SUPPORTED; default: @@ -2488,11 +2425,8 @@ psa_status_t psa_driver_wrapper_key_agreement(const psa_key_attributes_t *attrib } #endif /* PSA_NEED_CC3XX_KEY_AGREEMENT_DRIVER */ #if defined(PSA_NEED_OBERON_KEY_AGREEMENT_DRIVER) - status = oberon_key_agreement(attributes, priv_key, priv_key_size, alg, publ_key, + return oberon_key_agreement(attributes, priv_key, priv_key_size, alg, publ_key, publ_key_size, output, output_size, output_length); - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_KEY_AGREEMENT_DRIVER */ (void)status; return PSA_ERROR_NOT_SUPPORTED; @@ -2920,12 +2854,9 @@ psa_status_t psa_driver_wrapper_asymmetric_encrypt( } #endif /* PSA_NEED_CC3XX_ASYMMETRIC_ENCRYPTION_DRIVER */ #if defined(PSA_NEED_OBERON_ASYMMETRIC_ENCRYPTION_DRIVER) - status = oberon_asymmetric_encrypt(attributes, key_buffer, key_buffer_size, alg, + return oberon_asymmetric_encrypt(attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length); - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_ASYMMETRIC_ENCRYPTION_DRIVER */ (void)status; return PSA_ERROR_NOT_SUPPORTED; @@ -2980,12 +2911,9 @@ psa_status_t psa_driver_wrapper_asymmetric_decrypt( } #endif /* PSA_NEED_CC3XX_ASYMMETRIC_ENCRYPTION_DRIVER */ #if defined(PSA_NEED_OBERON_ASYMMETRIC_ENCRYPTION_DRIVER) - status = oberon_asymmetric_decrypt(attributes, key_buffer, key_buffer_size, alg, + return oberon_asymmetric_decrypt(attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length); - if (status != PSA_ERROR_NOT_SUPPORTED) { - return status; - } #endif /* PSA_NEED_OBERON_ASYMMETRIC_ENCRYPTION_DRIVER */ (void)status; return PSA_ERROR_NOT_SUPPORTED; From 1b37eb055f5b0ed8143d0a90872c5aca81682a97 Mon Sep 17 00:00:00 2001 From: divya pillai Date: Tue, 2 Dec 2025 10:30:05 +0100 Subject: [PATCH 083/155] doc improvement: Update image for HID mouse report handling Update image for HID mouse report handling NCSDK-36434 Signed-off-by: divya pillai --- doc/nrf/images/nrf_desktop_motion_sensing.svg | 371 +++++++++++------- 1 file changed, 230 insertions(+), 141 deletions(-) diff --git a/doc/nrf/images/nrf_desktop_motion_sensing.svg b/doc/nrf/images/nrf_desktop_motion_sensing.svg index 8f573a38ef25..334b7a81a222 100644 --- a/doc/nrf/images/nrf_desktop_motion_sensing.svg +++ b/doc/nrf/images/nrf_desktop_motion_sensing.svg @@ -2,33 +2,31 @@ + xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="7.82572in" height="5.63801in" + viewBox="0 0 563.452 405.937" xml:space="preserve" color-interpolation-filters="sRGB" class="st19"> + + @@ -36,161 +34,252 @@ - + - + - + - + - + Page-1 - + + + Nordic Blue - + - - Nordic Lake - Wheel Uses QDEC to measure rotation. Submits wheel_event when... - - Wheel Uses QDEC to measure rotation. Submits wheel_event when rotation is detected. - - Nordic Lake.2558 - Buttons Submits button_event on key press or release. The det... - - Buttons Submits button_event on key press or release. The detection of the first button press is based on interrupts. Then, the module scans keyboard matrix periodically until no button is pressed. - + Nordic Middle Grey - USB state / HIDS Sends the HID input report to the host and n... - - USB state / HIDS Sends the HID input report to the host and notifies when the report is sent. - + USB state/HIDS Sends the HID input report to the host and not... + + + + USB state/HIDSSends the HID input report to the host and notifies when the report is sent. + Nordic Lake.2559 HID state - - HID state - + + + + HID state + Nordic Lake.2560 - Updates the HID report data. - - Updates the HID report data. - - Nordic Lake.2561 - Generates the HID input report based on the report data and s... - - Generates the HID input report based on the report data and sends it to the active subscriber. - + Asks provider to send HID input report. + + + + Asks provider to send HID input report. + Nordic Lake.2566 STATE IDLE Uses the trigger to detect motion after inactivity. - - STATE IDLE Uses the trigger to detect motion after inactivity. - + + + + STATE IDLEUses the trigger to detect motion after inactivity. + Nordic Lake.2567 STATE FETCHING Uses a dedicated thread to fetch samples from ... - - STATE FETCHING Uses a dedicated thread to fetch samples from the sensor. Triggers sampling operation when a HID mouse report is sent. - + + + + STATE FETCHINGUses a dedicated thread to fetch samples from the sensor.Triggers sampling operation when a HID mouse report is sent. + Dynamic connector - + - - Sheet.2569 + + Sheet.15 Sensor data ready - - Sensor data ready - + + + + Sensor data ready + Dynamic connector.2570 - + - - Sheet.2571 + + Sheet.17 No motion for predefined number of samples - - No motion for predefined number of samples - - Sheet.2572 + + + + No motion for predefined number of samples + + Sheet.18 Motion sensor - - Motion sensor - + + + + Motion sensor + Dynamic connector.2574 - - - - Dynamic connector.2578 - + - + Dynamic connector.2580 - + - + Nordic Sun - - - - Dynamic connector.2582 - + - - Dynamic connector.2583 - + + Sheet.30 + hid_report_event + + + + hid_report_event + + Sheet.31 + hid_report_sent_event + + + + hid_report_sent_event + + Sheet.32 + hid_report_sent_event + + + + hid_report_sent_event + + Nordic Lake.33 + Wheel Uses QDEC to measure rotation. Submits wheel_event when... + + + + WheelUses QDEC to measure rotation. Submits wheel_event when rotation is detected. + + Nordic Lake.34 + Buttons Submits button_event on key press or release. The det... + + + + ButtonsSubmits button_event on key press or release. The detection of the first button press is based on interrupts. Then, the module scans keyboard matrix periodically until no button is pressed. + + Nordic Lake.35 + HID provider mouse + + + + HID provider mouse + + Nordic Lake.36 + Updates the HID report data. + + + + Updates the HID report data. + + Nordic Lake.2561 + Generates the HID input report based on the report data and s... + + + + Generates the HID input report based on the report data and sends it to the active subscriber. + + Dynamic connector.39 + - - Dynamic connector.2584 - + + Sheet.40 + wheel_event + + + + wheel_event + + Dynamic connector.2582 + - + Dynamic connector.2585 - + - - Sheet.2586 - wheel_event - - wheel_event - - Sheet.2588 + + Sheet.41 button_event - - button_event - - Sheet.2591 + + + + button_event + + Sheet.42 motion_event - - motion_event - - Sheet.2593 - hid_report_event - - hid_report_event - - Sheet.2595 - hid_report_sent_event - - hid_report_sent_event - - Sheet.2597 - hid_report_sent_event - - hid_report_sent_event + + + + motion_event + + Dynamic connector.2578 + + + + Sheet.45 + hid_report_provider_api.send_report + + + + hid_report_provider_api.send_report + + Sheet.46 + hid_state_api.trigger_report_send + + + + hid_state_api.trigger_report_send + + Dynamic connector.47 + + + + Dynamic connector.49 + + From a25611abb0ad818afec5e43476ac537cc51e2401 Mon Sep 17 00:00:00 2001 From: Grzegorz Ferenc Date: Tue, 2 Dec 2025 13:19:21 +0100 Subject: [PATCH 084/155] doc: tfm: system off service Added documentation for the System OFF service. Implemented style edits to the service Kconfig help. NCSDK-35009 and NCSIDB-1793. Signed-off-by: Grzegorz Ferenc --- .../device_guides/nrf54l/building_nrf54l.rst | 13 ++++++++++ doc/nrf/links.txt | 1 + doc/nrf/security/tfm/tfm_services.rst | 25 +++++++++++++++++++ modules/trusted-firmware-m/Kconfig | 10 ++++---- 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/doc/nrf/app_dev/device_guides/nrf54l/building_nrf54l.rst b/doc/nrf/app_dev/device_guides/nrf54l/building_nrf54l.rst index 5febbef1314b..c2fc3ec89f4e 100644 --- a/doc/nrf/app_dev/device_guides/nrf54l/building_nrf54l.rst +++ b/doc/nrf/app_dev/device_guides/nrf54l/building_nrf54l.rst @@ -141,3 +141,16 @@ Depending on the selected method, complete the following steps: .. code-block:: console west flash + +.. _building_nrf54l_system_off_service: + +Enabling the System OFF service +******************************* + +When :ref:`building with Trusted Firmware-M `, you can build the nRF54L Series devices with the System OFF service enabled. + +The System OFF service is one of the :ref:`TF-M platform services ` specific to the |NCS|. + +.. include:: ../../../security/tfm/tfm_services.rst + :start-after: The System OFF service is one of the TF-M platform services specific to the |NCS|. + :end-before: .. _ug_tfm_services_its: diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index 329f6a722eb6..9658ccda6d4d 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -844,6 +844,7 @@ .. _`nRF54L15 RRAMC`: https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/rramc.html .. _`nRF54L15 REGION.CONFIG`: https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/rramc.html#ariaid-title35 .. _`nRF54L15 CRACEN`: https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/cracen.html +.. _`nRF54L15 Power and clock management`: https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/pmu.html .. _`nRF54LM20A Datasheet`: https://docs.nordicsemi.com/bundle/ps_nrf54LM20A/page/keyfeatures_html5.html .. _`nRF54LM20 DK User Guide`: https://docs.nordicsemi.com/bundle/ug_nrf54lm20_dk/page/UG/nRF54LM20_DK/intro/intro.html diff --git a/doc/nrf/security/tfm/tfm_services.rst b/doc/nrf/security/tfm/tfm_services.rst index 8582247929ec..f3fbeb8c414a 100644 --- a/doc/nrf/security/tfm/tfm_services.rst +++ b/doc/nrf/security/tfm/tfm_services.rst @@ -36,6 +36,31 @@ See :ref:`lib_tfm_ioctl_api` for more information about APIs available for the n For more information about the general features of the TF-M Platform partition, see `TF-M Platform`_. +.. _ug_tfm_services_system_reset: + +System Reset service +-------------------- + +The System Reset service is one of the default TF-M platform services that has a specific implementation for the |NCS|. +It allows to perform a system reset through the TF-M platform service using the :c:func:`tfm_hal_system_reset` function. + +This service is enabled when you enable the :kconfig:option:`CONFIG_TFM_PARTITION_PLATFORM` Kconfig option. + +.. _ug_tfm_services_system_off: + +System OFF service +------------------ + +The System OFF service is one of the TF-M platform services specific to the |NCS|. +It allows the non-secure application to request the system to enter the System OFF mode using a secure service call. + +The System OFF mode is part of the power and clock management system and is available on selected Nordic Semiconductor devices, including the nRF54L Series. +For more details about the System OFF mode, see the device datasheet, for example the `nRF54L15 Power and clock management`_ page. + +To enable the System OFF service in the |NCS|, enable the :kconfig:option:`CONFIG_TFM_NRF_SYSTEM_OFF_SERVICE` Kconfig option. + +Zephyr's :zephyr:code-sample:`nrf_system_off` sample demonstrates how to use the System OFF service. + .. _ug_tfm_services_its: Internal Trusted Storage service diff --git a/modules/trusted-firmware-m/Kconfig b/modules/trusted-firmware-m/Kconfig index 78bdd98287d9..cd0b52be06d3 100644 --- a/modules/trusted-firmware-m/Kconfig +++ b/modules/trusted-firmware-m/Kconfig @@ -539,17 +539,17 @@ config TFM_PSA_FRAMEWORK_HAS_MM_IOVEC the Secure Partition. config TFM_NRF_SYSTEM_OFF_SERVICE - bool "TF-M NRF System Off Service [EXPERIMENTAL]" + bool "TF-M System OFF service [EXPERIMENTAL]" depends on TFM_ISOLATION_LEVEL = 1 depends on TFM_SFN depends on SOC_SERIES_NRF54LX depends on !RETAINED_MEM_NRF_RAM_CTRL select EXPERIMENTAL help - Provide a system off service for the nRF54L series SoCs. + Provide a System OFF service for the nRF54L Series SoCs. This service allows the non-secure application to request - the system to enter system off mode via a secure service call. - This service will disable RAM retention for all RAM blocks - before entering system off mode. + the system to enter the System OFF mode using a secure service call. + This service disables RAM retention for all RAM blocks + before entering the System OFF mode. endif # BUILD_WITH_TFM From d40e9dc6b0f875c98a8a1425f106391866dd043f Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Mon, 1 Dec 2025 16:15:34 +0100 Subject: [PATCH 085/155] doc: migration: v3.2: add guidelines for nRF Desktop and nRF54H20 target Added the nRF Desktop entry to the migration guide for nRF Connect SDK v3.2.0 with guidelines for the nRF54H20DK target and its migration to the IronSide SE solution. The migration guide also covers the general changes to the nRF54H20DK configuration that has been added since nRF Connect SDK v3.0.0 release. Ref: NCSDK-35488 Signed-off-by: Kamil Piszczek --- .../migration/migration_guide_3.2.rst | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst b/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst index 94dbfb8d7c81..5377fdf632c1 100644 --- a/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst +++ b/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst @@ -62,6 +62,110 @@ Samples and applications This section describes the changes related to samples and applications. +nRF Desktop +----------- + +.. toggle:: + + * The configuration of the ``nrf54h20dk/nrf54h20/cpuapp`` board target has been updated in the nRF Desktop application to migrate from the SUIT solution to the IronSide SE solution. + To migrate the configuration for your nRF Desktop based application, complete the following steps: + + 1. Remove the Kconfig options related to the SUIT solution in your project configuration files (for example, :file:`prj.conf`). + #. Configure the MCUboot bootloader in your sysbuild configuration file: + + * :kconfig:option:`SB_CONFIG_BOOTLOADER_MCUBOOT` to ``y``. + * :kconfig:option:`SB_CONFIG_MCUBOOT_MODE_DIRECT_XIP` to ``y``. + * :kconfig:option:`SB_CONFIG_BOOT_SIGNATURE_TYPE_ED25519` to ``y``. + * :kconfig:option:`SB_CONFIG_BOOT_SIGNATURE_TYPE_PURE` to ``y``. + * :kconfig:option:`SB_CONFIG_BOOT_SIGNATURE_KEY_FILE` to the path of the private key file which is used to sign the DFU package. + * :kconfig:option:`SB_CONFIG_MCUBOOT_IMAGES_ROM_END_OFFSET_AUTO` to ``ipc_radio;ipc_radio_secondary_app``. + In the case of a merged image slot, space for the MCUboot trailer is only reserved in the radio slots. + + .. note:: + The nRF Desktop configuration for the ``nrf54h20dk/nrf54h20/cpuapp`` board target uses the MCUboot bootloader in the direct-xip mode. + You can configure other MCUboot bootloader modes (for example, the swap mode) in the nRF Desktop application, but they are not used as part of the nRF Desktop configuration for the ``nrf54h20dk/nrf54h20/cpuapp`` board target and are not covered by this migration guide. + The nRF Desktop application also configures the MCUboot bootloader to use the merged image slot that combines both application and radio core images. + The merged image slot is the default configuration for the direct-xip mode. + Other ways of partitioning the application and radio core images are not covered by this migration guide. + + #. Add the configuration files for the MCUboot bootloader image to your application configuration. + See the :file:`nrf/applications/nrf_desktop/configuration/nrf54h20dk_nrf54h20_cpuapp/images/mcuboot` directory for an example. + + Note the following Kconfig options that are specific to the nRF54H configuration of the MCUboot bootloader: + + * :kconfig:option:`CONFIG_SOC_EARLY_RESET_HOOK` to ``y`` - This option is required to support the Suspend to RAM (S2RAM) functionality in the application. + With this Kconfig option, the MCUboot bootloader can detect a wake-up from S2RAM and redirect the execution to the application’s resume routine. + * :kconfig:option:`CONFIG_POWER_DOMAIN` to ``n`` - This option is required to disable the power domain management in the bootloader and simplify its configuration. + * :kconfig:option:`CONFIG_NRF_SECURITY`, :kconfig:option:`CONFIG_MULTITHREADING` and :kconfig:option:`CONFIG_PSA_SSF_CRYPTO_CLIENT` to ``y`` - These options are required to support the hardware cryptography in the MCUboot bootloader and its dependencies. + + #. Since the MCUboot bootloader in the direct-xip mode uses a merged image slot for the ``nrf54h20dk/nrf54h20/cpuapp`` board target, define the custom memory layout in DTS (the ``partitions`` DTS node) and ensure that this DTS customization is propagated to every image that is built as part of the nRF Desktop application. + See the :file:`nrf/applications/nrf_desktop/configuration/nrf54h20dk_nrf54h20_cpuapp/memory_map.dtsi` file for an example of the memory layout file and the :file:`nrf/applications/nrf_desktop/configuration/nrf54h20dk_nrf54h20_cpuapp/images/mcuboot/app.overlay` file for an example integration of the custom memory layout into the MCUboot bootloader image. + Apart from the MCUboot bootloader image, include the custom memory layout in the following images: + + * The ``nrf_desktop`` image (the default application image) + * The ``ipc_radio`` image + * The ``uicr`` image + + To verify that the custom memory layout is propagated to all the images, use the :file:`//zephyr/zephyr.dts` file and validate it for each image. + + .. note:: + The |NCS| v3.2.0 introduces a new image ``uicr`` for the ``nrf54h20dk/nrf54h20/cpuapp`` board target. + Include the custom memory layout in the ``uicr`` image as well to prevent runtime issues. + See the :file:`nrf/applications/nrf_desktop/configuration/nrf54h20dk_nrf54h20_cpuapp/images/uicr/app.overlay` file for an example integration of the custom memory layout into the ``uicr`` image. + + Assign the secondary image partition to the ``secondary_app_partition`` DTS label in the DTS configuration of your primary image: + + * For the ``nrf_desktop`` (primary) image and the ``mcuboot_secondary_app`` (secondary) image, use the following DTS configuration: + + .. code-block:: + + secondary_app_partition: &cpuapp_slot1_partition {}; + + * For the ``ipc_radio`` (primary) image and the ``ipc_radio_secondary_app`` (secondary) image, use the following DTS configuration: + + .. code-block:: + + secondary_app_partition: &cpurad_slot1_partition {}; + + #. Optionally, you can enable the following Kconfig options to improve the HID report rate over USB by suspending Bluetooth when USB is connected: + + * :kconfig:option:`CONFIG_DESKTOP_BLE_ADV_CTRL_ENABLE` + * :kconfig:option:`CONFIG_DESKTOP_BLE_ADV_CTRL_SUSPEND_ON_USB` + + #. Remove the usage of the following Kconfig options related to the S2RAM functionality: + + * :kconfig:option:`CONFIG_PM_S2RAM` + * :kconfig:option:`CONFIG_PM_S2RAM_CUSTOM_MARKING` + + .. note:: + The S2RAM functionality is now enabled by default for the ``nrf54h20dk/nrf54h20/cpuapp`` board target when the :kconfig:option:`CONFIG_PM` Kconfig option is enabled. + The setting of the :kconfig:option:`CONFIG_PM_S2RAM` Kconfig option is now controlled by the devicetree (DTS) description. + + #. Remove the ``pwmleds`` DTS node from the application configuration to prevent the :kconfig:option:`CONFIG_LED_PWM` and :kconfig:option:`CONFIG_CAF_LEDS_PWM` Kconfig options from being enabled for the ``nrf54h20dk/nrf54h20/cpuapp`` board target. + + .. code-block:: + + / { + /delete-node/ pwmleds; + + aliases { + /delete-property/ pwm-led0; + }; + }; + + .. note:: + The nRF Desktop configuration for the ``nrf54h20dk/nrf54h20/cpuapp`` board target relies on GPIO LEDs - the PWM LEDs are not used. + + #. Disable Link Time Optimization (LTO) as a workaround for linker warnings about the type mismatch (``-Wlto-type-mismatch``) that are caused by the :file:`device_deps.c` file (used by the Zephyr power domain driver): + + * :kconfig:option:`CONFIG_LTO` + * :kconfig:option:`CONFIG_ISR_TABLES_LOCAL_DECLARATION` + + #. Replace the ``interface-name`` property with the ``label`` property in all DTS nodes that set the ``compatible`` property to ``zephyr,hid-device``. + See the :file:`nrf/applications/nrf_desktop/configuration/nrf54h20dk_nrf54h20_cpuapp/app.overlay` file for an example. + + For more information regarding differences between SUIT and IronSide SE solutions, see the :ref:`migration_3.1_54h_suit_ironside` document. + Matter ------ From 2e0fd7a3e6fe3936eb87099551e9961a7c00b5ef Mon Sep 17 00:00:00 2001 From: Uma Praseeda Date: Tue, 26 Aug 2025 15:11:51 +0200 Subject: [PATCH 086/155] doc: Doc check for NCS 3.2 Doc check for NCS 3.2 Signed-off-by: Uma Praseeda --- CODEOWNERS | 2 +- .../doc/adding_bridged_matter_device.rst | 2 +- doc/mcuboot/index-ncs.rst | 4 ---- .../device_guides/coprocessors/fault_handling.rst | 4 ++++ .../nrf54h/ug_nrf54h20_architecture_clockman.rst | 4 +++- .../nrf54h/ug_nrf54h20_architecture_pinmap.rst | 9 ++++----- .../nrf54h/ug_nrf54h20_mcuboot_dfu.rst | 2 +- .../nrf54h/ug_nrf54h20_pm_optimization.rst | 3 +-- doc/nrf/app_dev/device_guides/nrf54l/kmu_basics.rst | 2 +- doc/nrf/glossary.rst | 2 +- .../libraries/bluetooth/services/fast_pair/core.rst | 2 +- doc/nrf/libraries/debug/cpu_load.rst | 13 +++++-------- doc/nrf/libraries/dfu/dfu_multi_image.rst | 6 +++--- doc/nrf/links.txt | 3 --- .../getting_started/low_power_configuration.rst | 4 ++-- .../releases/release-notes-2.7.99-cs1.rst | 2 +- .../releases/release-notes-2.7.99-cs2.rst | 2 +- samples/bluetooth/direct_test_mode/README.rst | 2 +- samples/dfu/ab/README.rst | 2 +- samples/dfu/dfu_target/README.rst | 2 +- .../ironside_se/protectedmem_periphconf/README.rst | 2 +- samples/matter/light_bulb/README.rst | 2 +- samples/matter/light_switch/README.rst | 2 +- samples/matter/lock/README.rst | 2 +- samples/matter/manufacturer_specific/README.rst | 2 +- samples/matter/template/README.rst | 2 +- samples/nrf5340/empty_app_core/README.rst | 4 ++-- scripts/nrf_profiler/README.rst | 4 ++++ snippets/nordic-flpr/README.rst | 5 +++++ 29 files changed, 50 insertions(+), 47 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 4f1e37063b63..89ec0934b547 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -235,7 +235,7 @@ /doc/nrf/releases_and_maturity/ @nrfconnect/ncs-doc-release /doc/nrf/releases_and_maturity/abi_compatibility.rst @FrancescoSer /doc/nrf/samples/amazon_sidewalk.rst @nrfconnect/ncs-sidewalk-doc -/doc/nrf/samples/bl.rst @nrfconnect/ncs-dragoon-doc +/doc/nrf/samples/bl.rst @nrfconnect/ncs-doc-leads /doc/nrf/samples/cellular.rst @nrfconnect/ncs-cia-doc /doc/nrf/samples/crypto.rst @nrfconnect/ncs-aegir-doc /doc/nrf/samples/debug.rst @nrfconnect/ncs-cia-doc diff --git a/applications/matter_bridge/doc/adding_bridged_matter_device.rst b/applications/matter_bridge/doc/adding_bridged_matter_device.rst index 1a44c9da72b8..1d457a58ca6f 100644 --- a/applications/matter_bridge/doc/adding_bridged_matter_device.rst +++ b/applications/matter_bridge/doc/adding_bridged_matter_device.rst @@ -137,7 +137,7 @@ The following steps show how to add support for a new Matter device type, using #. Implement the body of the :c:func:`HandleRead` method to handle reading data operations for all supported attributes. The read operations for the ``Descriptor``, ``Bridged Device Basic Information`` and ``Identify`` clusters, which are common to all devices, are handled in a common bridge module. - The read operations for the ``Pressure Measurement`` cluster are the only ones to that need to be handled in the application. + The read operations for the ``Pressure Measurement`` cluster are the only ones that need to be handled in the application. To provide support for reading attributes for the Pressure Sensor device, edit the :file:`pressure_sensor.h` and :file:`pressure_sensor.cpp` files as follows: diff --git a/doc/mcuboot/index-ncs.rst b/doc/mcuboot/index-ncs.rst index 8a5aa3cba8b3..04e2e4190d78 100644 --- a/doc/mcuboot/index-ncs.rst +++ b/doc/mcuboot/index-ncs.rst @@ -3,10 +3,6 @@ Introduction to MCUboot ####################### -.. contents:: - :local: - :depth: 2 - MCUboot is a secure bootloader for 32-bit microcontrollers. Overview diff --git a/doc/nrf/app_dev/device_guides/coprocessors/fault_handling.rst b/doc/nrf/app_dev/device_guides/coprocessors/fault_handling.rst index 972a33c6f0ec..0d6d9da5177b 100644 --- a/doc/nrf/app_dev/device_guides/coprocessors/fault_handling.rst +++ b/doc/nrf/app_dev/device_guides/coprocessors/fault_handling.rst @@ -3,6 +3,10 @@ Fault handling ############## +.. contents:: + :local: + :depth: 2 + .. caution:: The High-Performance Framework (HPF) support in the |NCS| is :ref:`experimental ` and is limited to the nRF54L15 device. diff --git a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_architecture_clockman.rst b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_architecture_clockman.rst index c757168aa1f9..4499656ec538 100644 --- a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_architecture_clockman.rst +++ b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_architecture_clockman.rst @@ -99,7 +99,7 @@ These clocks are fixed frequency, and are by default optimized for low power at The firmware can request a minimum level of accuracy and precision using the ``nrf_clock_control`` API provided by Zephyr RTOS, if the default configuration does not meet the required timing specifications. The startup time of these clocks can be relatively long, typically on the order of hundreds of milliseconds. -To ensure that the clocks meet the required timing constraints, retrieve the startup time for a given accuracy and precision using ``nrf_clock_control_get_startup_time``. +To ensure that the clocks meet the required timing constraints, retrieve the startup time for a given accuracy and precision using ``nrf_clock_control_get_startup_time()``. For more information, see the `Zephyr clock control API`_ section. Global HSFLL @@ -130,6 +130,8 @@ Furthermore, the ISR handling latency will be increased. If the local HSFLL is managed at runtime, the clock control driver will force it to its lowest frequency. The firmware must request a higher frequency using the ``nrf_clock_control`` API. +.. _ug_nrf54h20_zephyr_clock_control: + Zephyr clock control API ************************ diff --git a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_architecture_pinmap.rst b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_architecture_pinmap.rst index 2e4939891fbd..e3385d64a562 100644 --- a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_architecture_pinmap.rst +++ b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_architecture_pinmap.rst @@ -14,13 +14,13 @@ This comes at the cost of additional management by the firmware, thus additional The following sections describe how pins are powered, which domains they are in, and how to map and handle them. Pin groups ----------- +********** A pin group is a group of pins designated by an index, like P0.x, where P0 is the group containing [P0.0, P0.1, ...]. The pin group P0 is distinct from the GPIO controller with the same instance of P0. The P0 peripheral is routed to pins in the pin group P0, but is not necessarily in the same domain as the pin group P0. -The following table shows which domains the pin groups belong to. +The following table shows which domains the pin groups belong to: .. list-table:: Pin group domains :header-rows: 1 @@ -48,14 +48,13 @@ This power is provided by the domain where the pin and the multiplexers are. If a pin is configured as an output, the output value will be retained even when the power domain is suspended. Peripheral domains ------------------- +****************** Peripherals with an instance ending in 120, like UARTE120, PWM120, SPIS120, are in the FAST_ACTIVE_1 domain. The rest are in the SLOW_MAIN and SLOW_ACTIVE domains. Pin group power management --------------------------- - +************************** If a pin and the peripheral it is routed to are in the same domain, the peripheral forces the domain on when in use, thus powering the pin and the required multiplexers, as well. If a pin and the peripheral it is routed to are in different domains, the peripheral can only force on its own domain, not the domain the pin is in. diff --git a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_mcuboot_dfu.rst b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_mcuboot_dfu.rst index ed4ba9373ca0..c3f2b2a58b01 100644 --- a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_mcuboot_dfu.rst +++ b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_mcuboot_dfu.rst @@ -104,7 +104,7 @@ For more information, see the :file:`samples/zephyr/subsys/mgmt/mcumgr/smp_svr` This sample demonstrates how to configure DFU feature in both MCUboot and user application in your project. It uses Simple Management Protocol for DFU and querying device information from the application. -The following build flavours are available: +The following build flavors are available: * ``sample.mcumgr.smp_svr.bt.nrf54h20dk`` - DFU over BLE using the default :ref:`ipc_radio` image and *Swap using move* MCUboot mode. * ``sample.mcumgr.smp_svr.bt.nrf54h20dk.direct_xip_withrevert`` - DFU over BLE using *Direct-XIP with revert* MCUboot mode. diff --git a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_pm_optimization.rst b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_pm_optimization.rst index 21930746dfb7..17af66fd3a43 100644 --- a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_pm_optimization.rst +++ b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_pm_optimization.rst @@ -127,8 +127,7 @@ Consider also the following recommendations: * Disable all unused peripherals before entering sleep (Zephyr's API does this automatically when supported). * Build and program an empty image on any unused core to release shared resources. - * If one or more specific sleep states are not desired, disable them in the devicetree by setting their status - to ``disabled``: + * If one or more specific sleep states are not desired, disable them in the devicetree by setting their status to ``disabled``: .. code-block:: dts diff --git a/doc/nrf/app_dev/device_guides/nrf54l/kmu_basics.rst b/doc/nrf/app_dev/device_guides/nrf54l/kmu_basics.rst index c14fee3b59ce..d18f6c15d08a 100644 --- a/doc/nrf/app_dev/device_guides/nrf54l/kmu_basics.rst +++ b/doc/nrf/app_dev/device_guides/nrf54l/kmu_basics.rst @@ -24,7 +24,7 @@ Key types ********* Different types of keys, such as revocable and locked keys, serve distinct purposes and have unique policies associated with their use and management. -In the PSA abstraction, key types are mapped by the ``psa_set_key_lifetime`` function. +In the PSA abstraction, key types are mapped by the ``psa_set_key_lifetime()`` function. Refer to :ref:`PSA Key programming model` for details. Revocable keys diff --git a/doc/nrf/glossary.rst b/doc/nrf/glossary.rst index 50229c53f174..14ff8dd02c8a 100644 --- a/doc/nrf/glossary.rst +++ b/doc/nrf/glossary.rst @@ -1076,7 +1076,7 @@ Glossary Wi-Fi Protected Access® (WPA) A security protocol developed by Wi-Fi Alliance. - It comes in three flavours WPA, WPA2 and WPA3 respectively, with each offering higher security compared to its predecessor. + It comes in three flavors WPA, WPA2 and WPA3 respectively, with each offering higher security compared to its predecessor. Wireshark A free software tool that captures wireless traffic and reproduces it in a readable format. diff --git a/doc/nrf/libraries/bluetooth/services/fast_pair/core.rst b/doc/nrf/libraries/bluetooth/services/fast_pair/core.rst index 48ef4219792e..cf56bd3697ed 100644 --- a/doc/nrf/libraries/bluetooth/services/fast_pair/core.rst +++ b/doc/nrf/libraries/bluetooth/services/fast_pair/core.rst @@ -96,7 +96,7 @@ With the :kconfig:option:`CONFIG_BT_FAST_PAIR` Kconfig option enabled, the follo * :kconfig:option:`CONFIG_BT_FAST_PAIR_FMDN_CLOCK_NVM_UPDATE_TIME` - The option configures the time interval (in minutes) of periodic beacon clock writes to the non-volatile memory. * :kconfig:option:`CONFIG_BT_FAST_PAIR_FMDN_CLOCK_NVM_UPDATE_RETRY_TIME` - The option configures the retry time (in seconds) when the beacon clock write to the non-volatile memory fails. -* :kconfig:option:`CONFIG_BT_FAST_PAIR_USE_CASE_UNKNOWN`, :kconfig:option:`CONFIG_BT_FAST_PAIR_USE_CASE_INPUT_DEVICE`, :kconfig:option:`CONFIG_BT_FAST_PAIR_USE_CASE_LOCATOR_TAG` and :kconfig:option:`CONFIG_BT_FAST_PAIR_USE_CASE_MOUSE` - These options are used to select the Fast Pair use case and configure the Fast Pair library according to the `Fast Pair Device Feature Requirements`_ for the chosen use case. +* :kconfig:option:`CONFIG_BT_FAST_PAIR_USE_CASE_UNKNOWN`, :kconfig:option:`CONFIG_BT_FAST_PAIR_USE_CASE_INPUT_DEVICE`, :kconfig:option:`CONFIG_BT_FAST_PAIR_USE_CASE_LOCATOR_TAG`, and :kconfig:option:`CONFIG_BT_FAST_PAIR_USE_CASE_MOUSE` - These options are used to select the Fast Pair use case and configure the Fast Pair library according to the `Fast Pair Device Feature Requirements`_ for the chosen use case. The :kconfig:option:`CONFIG_BT_FAST_PAIR_USE_CASE_UNKNOWN` Kconfig option is used by default. * :kconfig:option:`CONFIG_BT_FAST_PAIR_ADV_MANAGER` - The option enables the :ref:`bt_fast_pair_adv_manager_readme` module. See the :ref:`bt_fast_pair_adv_manager_config` section to learn more about the remaining Kconfig options of this module. diff --git a/doc/nrf/libraries/debug/cpu_load.rst b/doc/nrf/libraries/debug/cpu_load.rst index d5d1e89b4c19..54c1f4f5eda5 100644 --- a/doc/nrf/libraries/debug/cpu_load.rst +++ b/doc/nrf/libraries/debug/cpu_load.rst @@ -28,14 +28,11 @@ To use the module, enable the :kconfig:option:`CONFIG_NRF_CPU_LOAD` Kconfig opti The module allows you to configure the following options in Kconfig: -* :kconfig:option:`CONFIG_NRF_CPU_LOAD_CMDS` - to enable shell commands -* :kconfig:option:`CONFIG_NRF_CPU_LOAD_LOG_PERIODIC` - to enable periodic logging of the - CPU load. You can use the :kconfig:option:`CONFIG_NRF_CPU_LOAD_LOG_INTERVAL` Kconfig option - to configure the interval of the logging. -* :kconfig:option:`CONFIG_NRF_CPU_LOAD_ALIGNED_CLOCKS` - to enable the alignment of the clock sources - for more accurate measurement. -* ``CONFIG_NRF_CPU_LOAD_TIMER_*`` - to choose the TIMER instance for the load measurement (for example, :kconfig:option:`CONFIG_NRF_CPU_LOAD_TIMER_0`) - +* :kconfig:option:`CONFIG_NRF_CPU_LOAD_CMDS` - To enable shell commands. +* :kconfig:option:`CONFIG_NRF_CPU_LOAD_LOG_PERIODIC` - To enable periodic logging of the CPU load. + You can use the :kconfig:option:`CONFIG_NRF_CPU_LOAD_LOG_INTERVAL` Kconfig option to configure the interval of the logging. +* :kconfig:option:`CONFIG_NRF_CPU_LOAD_ALIGNED_CLOCKS` - To enable the alignment of the clock sources for more accurate measurement. +* ``CONFIG_NRF_CPU_LOAD_TIMER_*`` - To choose the TIMER instance for the load measurement (for example, :kconfig:option:`CONFIG_NRF_CPU_LOAD_TIMER_0`). Usage ***** diff --git a/doc/nrf/libraries/dfu/dfu_multi_image.rst b/doc/nrf/libraries/dfu/dfu_multi_image.rst index 919044185606..f426445d4b90 100644 --- a/doc/nrf/libraries/dfu/dfu_multi_image.rst +++ b/doc/nrf/libraries/dfu/dfu_multi_image.rst @@ -53,9 +53,9 @@ To use this option, you must also set the following Kconfig options: * :kconfig:option:`CONFIG_NVS` (the nRF52 and nRF53 Series) or :kconfig:option:`CONFIG_ZMS` (the nRF54L and nRF54H Series) - Enables the settings backend to store data in NVM. .. note:: - Enabling this option uses space in the settings area in NVM to store the progress information. - Data is stored on every call to :c:func:`dfu_multi_image_write`. - Make sure that the settings area is large enough to accommodate this additional data. + Enabling this option uses space in the settings area in NVM to store the progress information. + Data is stored on every call to :c:func:`dfu_multi_image_write`. + Make sure that the settings area is large enough to accommodate this additional data. Dependencies ************ diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index 9658ccda6d4d..59dc313fee3b 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -560,13 +560,10 @@ .. _`Repositories and revisions for v2.9.0-nRF54H20-1`: https://docs.nordicsemi.com/bundle/ncs-2.9.0-nRF54H20-1/page/nrf/releases_and_maturity/repository_revisions.html .. _`Repositories and revisions for v2.9.0`: https://docs.nordicsemi.com/bundle/ncs-2.9.0/page/nrf/releases_and_maturity/repository_revisions.html .. _`Repositories and revisions for v2.8.0`: https://docs.nordicsemi.com/bundle/ncs-2.8.0/page/nrf/releases_and_maturity/repository_revisions.html -.. _`Repositories and revisions for v2.7.99-cs2`: https://docs.nordicsemi.com/bundle/ncs-2.7.99-cs2/page/nrf/releases_and_maturity/repository_revisions.html -.. _`Repositories and revisions for v2.7.99-cs1`: https://docs.nordicsemi.com/bundle/ncs-2.7.99-cs1/page/nrf/releases_and_maturity/repository_revisions.html .. _`Repositories and revisions for v2.7.0`: https://docs.nordicsemi.com/bundle/ncs-2.7.0/page/nrf/releases_and_maturity/repository_revisions.html .. _`Repositories and revisions for v2.6.4`: https://docs.nordicsemi.com/bundle/ncs-2.6.4/page/nrf/releases_and_maturity/repository_revisions.html .. _`Repositories and revisions for v2.6.3`: https://docs.nordicsemi.com/bundle/ncs-2.6.3/page/nrf/releases_and_maturity/repository_revisions.html .. _`Repositories and revisions for v2.6.2`: https://docs.nordicsemi.com/bundle/ncs-2.6.2/page/nrf/releases_and_maturity/repository_revisions.html -.. _`Repositories and revisions for v2.6.99-cs1`: https://docs.nordicsemi.com/bundle/ncs-2.6.99-cs1/page/nrf/releases_and_maturity/repository_revisions.html .. _`Repositories and revisions for v2.6.1`: https://docs.nordicsemi.com/bundle/ncs-2.6.1/page/nrf/releases_and_maturity/repository_revisions.html .. _`Repositories and revisions for v2.6.0`: https://docs.nordicsemi.com/bundle/ncs-2.6.0/page/nrf/releases_and_maturity/repository_revisions.html .. _`Repositories and revisions for v2.5.3`: https://docs.nordicsemi.com/bundle/ncs-2.5.3/page/nrf/releases_and_maturity/repository_revisions.html diff --git a/doc/nrf/protocols/matter/getting_started/low_power_configuration.rst b/doc/nrf/protocols/matter/getting_started/low_power_configuration.rst index 4142b328feab..55c7122e2f48 100644 --- a/doc/nrf/protocols/matter/getting_started/low_power_configuration.rst +++ b/doc/nrf/protocols/matter/getting_started/low_power_configuration.rst @@ -7,7 +7,7 @@ Reducing power consumption in Matter :local: :depth: 2 -The Matter protocol can be used in various device types that are designed to be battery supplied, where a low power consumption is of critical importance. +The Matter protocol can be used in various device types that are designed to be battery supplied, where low power consumption is of critical importance. There are many ways to reduce the power consumption in your application, including methods related to the adopted network technology, disabling specific modules, or configuring features meant for optimizing power consumption. See the following sections for more information. @@ -204,7 +204,7 @@ Configure Bluetooth LE advertising duration A Matter device uses Bluetooth® Low Energy (LE) to advertise its service for device commissioning purposes. The duration of this advertising is configurable and can last up to 15 minutes in the standard mode and up to 48 hours in the Extended Announcement mode. -An extended advertising duration may improve the user experience, as it gives more time for the user to setup the device, but it also increases the energy consumption. +An extended advertising duration may improve the user experience, as it gives more time for the user to set up the device, but it also increases the energy consumption. Selecting the optimal advertising duration is a compromise and depends on the specific application use case. Use the following Kconfig options to configure the advertising and reduce the consumed energy: diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.7.99-cs1.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.7.99-cs1.rst index d633c2cc7191..f0e60f67eca0 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.7.99-cs1.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.7.99-cs1.rst @@ -36,7 +36,7 @@ Check the :file:`west.yml` file for the corresponding tags in the project reposi To use this release, check out the tag in the manifest repository and run ``west update``. See :ref:`cloning_the_repositories` and :ref:`gs_updating_repos_examples` for more information. -For information on the included repositories and revisions, see `Repositories and revisions for v2.7.99-cs1`_. +For information on the included repositories and revisions, see Repositories and revisions for v2.7.99-cs1. IDE and tool support ******************** diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.7.99-cs2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.7.99-cs2.rst index 5f24142359c1..017ecf5fa69a 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.7.99-cs2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.7.99-cs2.rst @@ -49,7 +49,7 @@ Check the :file:`west.yml` file for the corresponding tags in the project reposi To use this release, check out the tag in the manifest repository and run ``west update``. See :ref:`cloning_the_repositories` and :ref:`gs_updating_repos_examples` for more information. -For information on the included repositories and revisions, see `Repositories and revisions for v2.7.99-cs2`_. +For information on the included repositories and revisions, see Repositories and revisions for v2.7.99-cs2. IDE and tool support ******************** diff --git a/samples/bluetooth/direct_test_mode/README.rst b/samples/bluetooth/direct_test_mode/README.rst index 846cf58b9cdc..79cfef3fd47a 100644 --- a/samples/bluetooth/direct_test_mode/README.rst +++ b/samples/bluetooth/direct_test_mode/README.rst @@ -188,7 +188,7 @@ Antenna matrix configuration To use this sample to test the Bluetooth Direction Finding feature, additional configuration of GPIOs is required to control the antenna array. An example of such configuration is provided in a devicetree overlay file :file:`nrf5340dk_nrf5340_cpunet.overlay`. -The overlay file provides the information about of the GPIOs to be used by the Radio peripheral to switch between antenna patches during the Constant Tone Extension (CTE) reception or transmission. +The overlay file provides the information of the GPIOs to be used by the Radio peripheral to switch between antenna patches during the Constant Tone Extension (CTE) reception or transmission. At least one GPIO must be provided to enable antenna switching. The GPIOs are used by the radio peripheral in the order provided by the ``dfegpio#-gpios`` properties. diff --git a/samples/dfu/ab/README.rst b/samples/dfu/ab/README.rst index cf93370469c5..a372821cc560 100644 --- a/samples/dfu/ab/README.rst +++ b/samples/dfu/ab/README.rst @@ -59,7 +59,7 @@ The following conditions decide which slot will be booted (active) on the next r #. If both slots are valid and none is marked as "preferred," the slot with the higher version number is selected as active. #. If none of the above conditions is met, slot A is selected as active. -You can set the preferred slot using the ``boot_request_set_preferred_slot`` function. +You can set the preferred slot using the ``boot_request_set_preferred_slot()`` function. If the :kconfig:option:`CONFIG_NRF_MCUBOOT_BOOT_REQUEST_PREFERENCE_KEEP` option is enabled, the slot preference remains persistent across reboots. Otherwise, the slot preference is cleared on reboot. To enable the persistence of a preferred slot, define a backup region for the bootloader request area by using the ``nrf,bootloader-request-backup`` chosen node in the devicetree. diff --git a/samples/dfu/dfu_target/README.rst b/samples/dfu/dfu_target/README.rst index f49fbeb4ca69..d1d737df6f36 100644 --- a/samples/dfu/dfu_target/README.rst +++ b/samples/dfu/dfu_target/README.rst @@ -55,7 +55,7 @@ After programming the sample to your development kit, perform the following step ``Starting dfu_target sample, build time: `` ```` indicates the build time. - Iit will be used later to verify the update. + It will be used later to verify the update. #. Build a second version of the sample. For simplicity, it is assumed to be built in the :file:`build_v2` directory. diff --git a/samples/ironside_se/protectedmem_periphconf/README.rst b/samples/ironside_se/protectedmem_periphconf/README.rst index 7e9ed17e3dbe..83b91a4e9103 100644 --- a/samples/ironside_se/protectedmem_periphconf/README.rst +++ b/samples/ironside_se/protectedmem_periphconf/README.rst @@ -7,7 +7,7 @@ Protected Memory with PERIPHCONF Partition :local: :depth: 2 -This sample demonstrates how to protect the PERIPHCONF Partition using UICR.PROTECTEDMEM. +This sample demonstrates how to protect the PERIPHCONF partition using UICR.PROTECTEDMEM. Requirements ************ diff --git a/samples/matter/light_bulb/README.rst b/samples/matter/light_bulb/README.rst index 19d84598fb6d..3eb283ccca87 100644 --- a/samples/matter/light_bulb/README.rst +++ b/samples/matter/light_bulb/README.rst @@ -39,7 +39,7 @@ IPv6 network support The development kits for this sample offer the following IPv6 network support for Matter: -* Matter over Thread is supported for ``nrf52840dk/nrf52840``, ``nrf5340dk/nrf5340/cpuapp``, ``nrf21540dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp`` and ``nrf54lm20dk/nrf54lm20a/cpuapp``. +* Matter over Thread is supported for ``nrf52840dk/nrf52840``, ``nrf5340dk/nrf5340/cpuapp``, ``nrf21540dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp``, and ``nrf54lm20dk/nrf54lm20a/cpuapp``. * Matter over Wi-Fi is supported for ``nrf5340dk/nrf5340/cpuapp`` with the ``nrf7002ek`` shield attached, ``nrf7002dk/nrf5340/cpuapp``, or ``nrf54lm20dk/nrf54lm20a/cpuapp`` with the ``nrf7002eb2`` shield attached. Overview diff --git a/samples/matter/light_switch/README.rst b/samples/matter/light_switch/README.rst index 737a679887f8..4a4cafed3b31 100644 --- a/samples/matter/light_switch/README.rst +++ b/samples/matter/light_switch/README.rst @@ -43,7 +43,7 @@ IPv6 network support The development kits for this sample offer the following IPv6 network support for Matter: -* Matter over Thread is supported for ``nrf52840dk/nrf52840``, ``nrf5340dk/nrf5340/cpuapp``, ``nrf21540dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp`` and ``nrf54lm20dk/nrf54lm20a/cpuapp``. +* Matter over Thread is supported for ``nrf52840dk/nrf52840``, ``nrf5340dk/nrf5340/cpuapp``, ``nrf21540dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp``, and ``nrf54lm20dk/nrf54lm20a/cpuapp``. * Matter over Wi-Fi is supported for ``nrf5340dk/nrf5340/cpuapp`` with the ``nrf7002ek`` shield attached, ``nrf7002dk/nrf5340/cpuapp``, or ``nrf54lm20dk/nrf54lm20a/cpuapp`` with the ``nrf7002eb2`` shield attached. Overview diff --git a/samples/matter/lock/README.rst b/samples/matter/lock/README.rst index a4ed9e735185..e2b3f6ee45ac 100644 --- a/samples/matter/lock/README.rst +++ b/samples/matter/lock/README.rst @@ -43,7 +43,7 @@ IPv6 network support The development kits for this sample offer the following IPv6 network support for Matter: -* Matter over Thread is supported for the ``nrf52840dk/nrf52840``, ``nrf5340dk/nrf5340/cpuapp``, ``nrf21540dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp`` and ``nrf54lm20dk/nrf54lm20a/cpuapp`` board targets. +* Matter over Thread is supported for the ``nrf52840dk/nrf52840``, ``nrf5340dk/nrf5340/cpuapp``, ``nrf21540dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp``, and ``nrf54lm20dk/nrf54lm20a/cpuapp`` board targets. * Matter over Wi-Fi is supported for the ``nrf5340dk/nrf5340/cpuapp`` board target with the ``nrf7002ek`` shield attached, the ``nrf7002dk/nrf5340/cpuapp`` (2.4 GHz and 5 GHz), ``nrf7002dk/nrf5340/cpuapp/nrf7001`` board targets (2.4 GHz only), or the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target with the ``nrf7002eb2`` shield attached. * :ref:`Switching between Matter over Thread and Matter over Wi-Fi ` is supported for ``nrf5340dk/nrf5340/cpuapp`` with the ``nrf7002ek`` shield attached, using the :ref:`switched Thread and Wi-Fi configuration `. diff --git a/samples/matter/manufacturer_specific/README.rst b/samples/matter/manufacturer_specific/README.rst index 1569c3bd5ab5..53cbc32bfee3 100644 --- a/samples/matter/manufacturer_specific/README.rst +++ b/samples/matter/manufacturer_specific/README.rst @@ -32,7 +32,7 @@ IPv6 network support The development kits for this sample offer the following IPv6 network support for Matter: -* Matter over Thread is supported for the ``nrf52840dk/nrf52840``, ``nrf5340dk/nrf5340/cpuapp``, ``nrf21540dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp``, ``nrf54l15dk/nrf54l10/cpuapp`` and ``nrf54lm20dk/nrf54lm20a/cpuapp`` board targets. +* Matter over Thread is supported for the ``nrf52840dk/nrf52840``, ``nrf5340dk/nrf5340/cpuapp``, ``nrf21540dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp``, ``nrf54l15dk/nrf54l10/cpuapp``, and ``nrf54lm20dk/nrf54lm20a/cpuapp`` board targets. * Matter over Wi-Fi is supported for the ``nrf5340dk/nrf5340/cpuapp`` board target with the ``nrf7002ek`` shield attached, ``nrf7002dk/nrf5340/cpuapp`` board target, or ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target with the ``nrf7002eb2`` shield attached. Overview diff --git a/samples/matter/template/README.rst b/samples/matter/template/README.rst index 22d5450b1f1d..0f6f3f42c769 100644 --- a/samples/matter/template/README.rst +++ b/samples/matter/template/README.rst @@ -32,7 +32,7 @@ IPv6 network support The development kits for this sample offer the following IPv6 network support for Matter: -* Matter over Thread is supported for the ``nrf52840dk/nrf52840``, ``nrf5340dk/nrf5340/cpuapp``, ``nrf21540dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp``, ``nrf54l15dk/nrf54l10/cpuapp`` and ``nrf54lm20dk/nrf54lm20a/cpuapp`` board targets. +* Matter over Thread is supported for the ``nrf52840dk/nrf52840``, ``nrf5340dk/nrf5340/cpuapp``, ``nrf21540dk/nrf52840``, ``nrf54l15dk/nrf54l15/cpuapp``, ``nrf54l15dk/nrf54l10/cpuapp``, and ``nrf54lm20dk/nrf54lm20a/cpuapp`` board targets. * Matter over Wi-Fi is supported for the ``nrf5340dk/nrf5340/cpuapp`` board target with the ``nrf7002ek`` shield attached, ``nrf7002dk/nrf5340/cpuapp`` board target, or ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target with the ``nrf7002eb2`` shield attached. Overview diff --git a/samples/nrf5340/empty_app_core/README.rst b/samples/nrf5340/empty_app_core/README.rst index f38ee44743f0..faf7da224ad3 100644 --- a/samples/nrf5340/empty_app_core/README.rst +++ b/samples/nrf5340/empty_app_core/README.rst @@ -55,10 +55,10 @@ Dependencies This sample has the following `nrfx`_ dependencies: -* ``nrfx/nrfx.h`` +* :file:`nrfx/nrfx.h` In addition, it uses the following Zephyr libraries: * :ref:`zephyr:kernel_api`: - * ``include/init.h`` + * :file:`include/init.h` diff --git a/scripts/nrf_profiler/README.rst b/scripts/nrf_profiler/README.rst index 609f71e1ebdb..5a9d78713c06 100644 --- a/scripts/nrf_profiler/README.rst +++ b/scripts/nrf_profiler/README.rst @@ -3,6 +3,10 @@ nRF Profiler host tools ####################### +.. contents:: + :local: + :depth: 2 + The nRF Profiler host tools is a set of Python scripts that you can use to visualize and analyze the nRF Profiler events received over RTT from an embedded device running the :ref:`nrf_profiler` library. You can use the scripts for both :ref:`app_event_manager` events and custom events. diff --git a/snippets/nordic-flpr/README.rst b/snippets/nordic-flpr/README.rst index 187fd4ae6619..a957c22d5aae 100644 --- a/snippets/nordic-flpr/README.rst +++ b/snippets/nordic-flpr/README.rst @@ -3,6 +3,11 @@ Nordic FLPR snippet with execution from SRAM (nordic-flpr) ########################################################## +.. contents:: + :local: + :depth: 2 + + Overview ******** From 1730bf526e99d687ae829a35d918036838752195 Mon Sep 17 00:00:00 2001 From: Aleksandar Stanoev Date: Tue, 2 Dec 2025 23:39:29 +0000 Subject: [PATCH 087/155] =?UTF-8?q?samples:=20bluetooth:=20Replace=20?= =?UTF-8?q?=CE=BCs=20with=20us=20in=20SCI=20sample?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace μs with us to resolve incorrect rendering in CI logs and customer terminals without unicode support. Signed-off-by: Aleksandar Stanoev --- .../shorter_conn_intervals/README.rst | 56 +++++++++---------- .../shorter_conn_intervals/src/main.c | 18 +++--- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/samples/bluetooth/shorter_conn_intervals/README.rst b/samples/bluetooth/shorter_conn_intervals/README.rst index 7eaa9b69d8ed..3ff32e1f4fb5 100644 --- a/samples/bluetooth/shorter_conn_intervals/README.rst +++ b/samples/bluetooth/shorter_conn_intervals/README.rst @@ -139,8 +139,8 @@ The result should look similar to the following output: I: HCI: version 6.2 (0x10) revision 0x3012, manufacturer 0x0059 I: LMP: version 6.2 (0x10) subver 0x3012 I: Bluetooth initialized - I: Local minimum connection interval: 750 μs - I: SCI default connection rate parameters set (min=750 μs, max=10000 μs) + I: Local minimum connection interval: 750 us + I: SCI default connection rate parameters set (min=750 us, max=10000 us) I: Should this device initiate connection interval updates? Type y (yes, this device will initiate) or n (no, peer will initiate): @@ -152,25 +152,25 @@ The result should look similar to the following output: I: Central. Starting scanning I: Scanning successfully started I: Connected as central - I: Conn. interval is 10000 μs + I: Conn. interval is 10000 us I: Security changed: level 2, err: 0 I: Latency service discovery completed I: SCI service discovery completed I: Found SCI min interval characteristic, handle: 0x0013 I: LE PHY updated: TX PHY LE 2M, RX PHY LE 2M - I: Frame space updated: 63 μs, PHYs: 0x02, spacing types: 0x0003, initiator: Local Host - I: Minimum connection intervals: Local: 750 μs, Peer: 750 μs, Common: 750 μs - I: Transmission Latency: 9153 μs - I: Requesting new connection interval: 750 μs - I: Connection rate changed: interval 750 μs, subrate factor 1, peripheral latency 0, continuation number 0, supervision timeout 4000 ms - I: Transmission Latency: 834 μs - I: Transmission Latency: 792 μs - I: Transmission Latency: 747 μs - I: Requesting new connection interval: 1000 μs - I: Connection rate changed: interval 1000 μs, subrate factor 1, peripheral latency 0, continuation number 0, supervision timeout 4000 ms - I: Transmission Latency: 1056 μs - I: Transmission Latency: 838 μs - I: Transmission Latency: 1161 μs + I: Frame space updated: 63 us, PHYs: 0x02, spacing types: 0x0003, initiator: Local Host + I: Minimum connection intervals: Local: 750 us, Peer: 750 us, Common: 750 us + I: Transmission Latency: 9153 us + I: Requesting new connection interval: 750 us + I: Connection rate changed: interval 750 us, subrate factor 1, peripheral latency 0, continuation number 0, supervision timeout 4000 ms + I: Transmission Latency: 834 us + I: Transmission Latency: 792 us + I: Transmission Latency: 747 us + I: Requesting new connection interval: 1000 us + I: Connection rate changed: interval 1000 us, subrate factor 1, peripheral latency 0, continuation number 0, supervision timeout 4000 ms + I: Transmission Latency: 1056 us + I: Transmission Latency: 838 us + I: Transmission Latency: 1161 us * For the device not initiating connection interval updates:: @@ -180,23 +180,23 @@ The result should look similar to the following output: I: Peripheral. Starting advertising I: Advertising successfully started I: Connected as peripheral - I: Conn. interval is 10000 μs + I: Conn. interval is 10000 us I: Security changed: level 2, err: 0 I: Latency service discovery completed I: SCI service discovery completed I: Found SCI min interval characteristic, handle: 0x0013 - I: Minimum connection intervals: Local: 750 μs, Peer: 750 μs, Common: 750 μs + I: Minimum connection intervals: Local: 750 us, Peer: 750 us, Common: 750 us I: LE PHY updated: TX PHY LE 2M, RX PHY LE 2M - I: Frame space updated: 63 μs, PHYs: 0x02, spacing types: 0x0003, initiator: Peer - I: Transmission Latency: 11551 μs - I: Connection rate changed: interval 750 μs, subrate factor 1, peripheral latency 0, continuation number 0, supervision timeout 4000 ms - I: Transmission Latency: 718 μs - I: Transmission Latency: 962 μs - I: Transmission Latency: 804 μs - I: Connection rate changed: interval 1000 μs, subrate factor 1, peripheral latency 0, continuation number 0, supervision timeout 4000 ms - I: Transmission Latency: 630 μs - I: Transmission Latency: 1056 μs - I: Transmission Latency: 838 μs + I: Frame space updated: 63 us, PHYs: 0x02, spacing types: 0x0003, initiator: Peer + I: Transmission Latency: 11551 us + I: Connection rate changed: interval 750 us, subrate factor 1, peripheral latency 0, continuation number 0, supervision timeout 4000 ms + I: Transmission Latency: 718 us + I: Transmission Latency: 962 us + I: Transmission Latency: 804 us + I: Connection rate changed: interval 1000 us, subrate factor 1, peripheral latency 0, continuation number 0, supervision timeout 4000 ms + I: Transmission Latency: 630 us + I: Transmission Latency: 1056 us + I: Transmission Latency: 838 us References diff --git a/samples/bluetooth/shorter_conn_intervals/src/main.c b/samples/bluetooth/shorter_conn_intervals/src/main.c index e8bdc39bc6d9..82c72dab0f5b 100644 --- a/samples/bluetooth/shorter_conn_intervals/src/main.c +++ b/samples/bluetooth/shorter_conn_intervals/src/main.c @@ -349,7 +349,7 @@ static void connected(struct bt_conn *conn, uint8_t err) LOG_INF("Connected as %s", conn_info.role == BT_CONN_ROLE_CENTRAL ? "central" : "peripheral"); - LOG_INF("Conn. interval is %u μs", conn_info.le.interval_us); + LOG_INF("Conn. interval is %u us", conn_info.le.interval_us); #if defined(CONFIG_BT_SMP) if (conn_info.role == BT_CONN_ROLE_PERIPHERAL) { @@ -436,7 +436,7 @@ static int set_conn_rate_defaults(uint32_t interval_min_us, uint32_t interval_ma return err; } - LOG_INF("SCI default connection rate parameters set (min=%u μs, max=%u μs)", + LOG_INF("SCI default connection rate parameters set (min=%u us, max=%u us)", interval_min_us, interval_max_us); return 0; } @@ -491,7 +491,7 @@ static void conn_rate_changed(struct bt_conn *conn, uint8_t status, { if (status == BT_HCI_ERR_SUCCESS) { LOG_INF("Connection rate changed: " - "interval %u μs, " + "interval %u us, " "subrate factor %d, " "peripheral latency %d, " "continuation number %d, " @@ -534,7 +534,7 @@ static void frame_space_updated(struct bt_conn *conn, const struct bt_conn_le_frame_space_updated *params) { if (params->status == BT_HCI_ERR_SUCCESS) { - LOG_INF("Frame space updated: %u μs, PHYs: 0x%02x, spacing types: 0x%04x, " + LOG_INF("Frame space updated: %u us, PHYs: 0x%02x, spacing types: 0x%04x, " "initiator: %s", params->frame_space, params->phys, params->spacing_types, fsu_initiator_to_str(params->initiator)); @@ -599,8 +599,8 @@ static void test_run(void) common_min_interval_us = MAX(local_min_interval_us, remote_min_interval_us); test_intervals[0] = common_min_interval_us; - LOG_INF("Minimum connection intervals: Local: %u μs, Peer: %u μs, " - "Common: %u μs", + LOG_INF("Minimum connection intervals: Local: %u us, Peer: %u us, " + "Common: %u us", local_min_interval_us, remote_min_interval_us, common_min_interval_us); } @@ -621,7 +621,7 @@ static void test_run(void) k_sleep(K_MSEC(200)); /* wait for latency response */ if (latency_response) { - LOG_INF("Transmission Latency: %u μs", latency_response); + LOG_INF("Transmission Latency: %u us", latency_response); } else { LOG_WRN("Did not receive a latency response"); } @@ -636,7 +636,7 @@ static void test_run(void) uint32_t new_interval_us = test_intervals[interval_index]; - LOG_INF("Requesting new connection interval: %u μs", + LOG_INF("Requesting new connection interval: %u us", new_interval_us); /* As a central, the lowest supported interval of the peripheral @@ -694,7 +694,7 @@ int main(void) LOG_WRN("Failed to read min conn interval (err %d)", err); return 0; } - LOG_INF("Local minimum connection interval: %u μs", local_min_interval_us); + LOG_INF("Local minimum connection interval: %u us", local_min_interval_us); /* Set the initial allowed range of parameters that can be requested by the peripheral. * They will be overridden by any calls to bt_conn_le_conn_rate_request(). From 57fd5c089f22af6a19b3d9ca3339b616cebc7003 Mon Sep 17 00:00:00 2001 From: Kapil Bhatt Date: Wed, 3 Dec 2025 08:46:28 +0000 Subject: [PATCH 088/155] snippets: Fix p2p flash overflow for nrf7002dk Fix p2p flash overflow for nrf7002dk. Signed-off-by: Kapil Bhatt --- snippets/wifi-p2p/wifi-p2p.conf | 2 -- 1 file changed, 2 deletions(-) diff --git a/snippets/wifi-p2p/wifi-p2p.conf b/snippets/wifi-p2p/wifi-p2p.conf index a7a4cf6764a2..e28061885ba6 100644 --- a/snippets/wifi-p2p/wifi-p2p.conf +++ b/snippets/wifi-p2p/wifi-p2p.conf @@ -1,7 +1,5 @@ CONFIG_NRF70_P2P_MODE=y CONFIG_NRF70_AP_MODE=y CONFIG_WIFI_NM_WPA_SUPPLICANT_P2P=y -CONFIG_WPA_CLI=y -CONFIG_WIFI_NM_WPA_SUPPLICANT_LOG_LEVEL_INF=y CONFIG_LTO=y CONFIG_ISR_TABLES_LOCAL_DECLARATION=y From eaa56683e9f186483d3ea72e1871ba8754717127 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 3 Dec 2025 07:54:04 +0000 Subject: [PATCH 089/155] kconfig: Do not source shield Kconfigs This should never have been added in the first place and has seemingly been noticed after noticing every shield has been sourced into Kconfig twice Signed-off-by: Jamie McCrae --- Kconfig.nrf | 1 - 1 file changed, 1 deletion(-) diff --git a/Kconfig.nrf b/Kconfig.nrf index 149261c73123..e06122676ed4 100644 --- a/Kconfig.nrf +++ b/Kconfig.nrf @@ -11,7 +11,6 @@ orsource "./$(BOARD_DIR)/Kconfig.board" orsource "./$(BOARD_DIR)/Kconfig" orsource "./cmake/toolchain/$(ZEPHYR_TOOLCHAIN_VARIANT)/Kconfig.defconfig" -rsource "boards/shields/*/Kconfig.shield" rsource "subsys/net/openthread/Kconfig.defconfig" if !TFM_PROFILE_TYPE_MINIMAL From e08627f837c90b36db3c2444a18050d135738950 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 3 Dec 2025 08:29:25 +0000 Subject: [PATCH 090/155] kconfig: Remove sourced of hwmv1 board files Board files are automatically sourced with globs in compliance checks and have been for a very long time, plus this file name indicates hwmv1 which is no longer supported Signed-off-by: Jamie McCrae --- Kconfig.nrf | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Kconfig.nrf b/Kconfig.nrf index e06122676ed4..25c67b41312d 100644 --- a/Kconfig.nrf +++ b/Kconfig.nrf @@ -4,11 +4,6 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -# Usually BOARD_DIR is an absolute path and sourced through '/boards/Kconfig'. -# But for compliance and doc generation it's a glob and this line ensures that -# boards in sdk-nrf are sourced properly in those occasions. -orsource "./$(BOARD_DIR)/Kconfig.board" -orsource "./$(BOARD_DIR)/Kconfig" orsource "./cmake/toolchain/$(ZEPHYR_TOOLCHAIN_VARIANT)/Kconfig.defconfig" rsource "subsys/net/openthread/Kconfig.defconfig" From 80e1a3290d75b0bcd35d3d358d6d39c8c409904a Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Tue, 2 Dec 2025 14:39:10 +0100 Subject: [PATCH 091/155] tests: emds: add hw timer based measuring Commit adds time measuring approach based on hardware timer. System clock granularity is quite huge (31 us). It is not acceptable for precise time measuring. Signed-off-by: Aleksandr Khromykh --- tests/subsys/emds/emds_flash/src/main.c | 82 +++++++++++++++++++------ 1 file changed, 64 insertions(+), 18 deletions(-) diff --git a/tests/subsys/emds/emds_flash/src/main.c b/tests/subsys/emds/emds_flash/src/main.c index 9159363b7efd..c0168c9dfdc6 100644 --- a/tests/subsys/emds/emds_flash/src/main.c +++ b/tests/subsys/emds/emds_flash/src/main.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -31,17 +32,56 @@ #else #define FLASH DT_INST(0, soc_nv_flash) #define EMDS_FLASH_BLOCK_SIZE DT_PROP(FLASH, write_block_size) +#if defined(CONFIG_SOC_NRF5340_CPUAPP) +#define EXPECTED_STORE_TIME_BLOCK_SIZE (48) +#define EXPECTED_STORE_TIME_1024 (11600) +#else /* 32bits word is written maximum 41us (from datasheet) */ -#define EXPECTED_STORE_TIME_BLOCK_SIZE (41) +#define EXPECTED_STORE_TIME_BLOCK_SIZE (46) /* 1024 bytes should take ideally 10496us (really takes about 11000us) */ #define EXPECTED_STORE_TIME_1024 (11500) #endif +#endif #define EMDS_SNAPSHOT_METADATA_MARKER 0x4D444553 #define PARTITIONS_NUM_MAX 2 static struct emds_partition partition[PARTITIONS_NUM_MAX]; +/* Configure for 1MHz (1μs precision) */ +#if defined(CONFIG_SOC_NRF54L15) +#define NORDIC_TIMER_INSTANCE NRF_TIMER20 +#else +#define NORDIC_TIMER_INSTANCE NRF_TIMER2 +#endif + +static void microsecond_timer_init(void) +{ + /* Configure timer for 1 microsecond precision */ + nrf_timer_mode_set(NORDIC_TIMER_INSTANCE, NRF_TIMER_MODE_TIMER); + nrf_timer_bit_width_set(NORDIC_TIMER_INSTANCE, NRF_TIMER_BIT_WIDTH_32); + nrf_timer_prescaler_set(NORDIC_TIMER_INSTANCE, NRF_TIMER_FREQ_1MHz); + + nrf_timer_task_trigger(NORDIC_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); + nrf_timer_task_trigger(NORDIC_TIMER_INSTANCE, NRF_TIMER_TASK_START); + + printk("Timer initialized at 1MHz (1μs resolution)\n"); +} + +static uint32_t get_time_us(void) +{ + nrf_timer_task_trigger(NORDIC_TIMER_INSTANCE, NRF_TIMER_TASK_CAPTURE0); + return nrf_timer_cc_get(NORDIC_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0); +} + +static void microsecond_timer_cleanup(void) +{ + /* Stop and disable timer to prevent system issues */ + nrf_timer_task_trigger(NORDIC_TIMER_INSTANCE, NRF_TIMER_TASK_STOP); + nrf_timer_task_trigger(NORDIC_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR); + printk("Timer stopped and cleaned up\n"); +} + /** Local functions ***********************************************************/ static void *emds_flash_setup(void) { @@ -537,13 +577,11 @@ ZTEST(emds_flash, test_write_speed) static uint8_t data_in[EMDS_FLASH_BLOCK_SIZE]; static uint8_t data_in_big[1024]; static uint8_t read_back[1024] = {0}; - int64_t tic; - int64_t toc; - uint64_t store_time_us; + uint32_t start_us, end_us, elapsed_us; off_t data_off = 0; memset(data_in, 69, sizeof(data_in)); - memset(data_in_big, 69, sizeof(data_in_big)); + memset(data_in_big, 42, sizeof(data_in_big)); (void)dk_leds_init(); (void)dk_set_led(0, false); @@ -553,34 +591,42 @@ ZTEST(emds_flash, test_write_speed) (void)sdc_disable(); mpsl_uninit(); #endif + /* Initialize microsecond timer */ + microsecond_timer_init(); dk_set_led(0, true); - tic = k_uptime_ticks(); + start_us = get_time_us(); emds_flash_write_data(&partition[partition_index], data_off, data_in, sizeof(data_in)); - toc = k_uptime_ticks(); + end_us = get_time_us(); dk_set_led(0, false); - store_time_us = k_ticks_to_us_ceil64(toc - tic); - printk("Storing %d bytes took: %lldus\n", sizeof(data_in), store_time_us); - zassert_true(store_time_us < EXPECTED_STORE_TIME_BLOCK_SIZE, - "Storing %d bytes took to long time", sizeof(data_in)); + elapsed_us = end_us - start_us; + printk("Storing %d bytes took %uus\n", sizeof(data_in), elapsed_us); + + zassert_true(elapsed_us < EXPECTED_STORE_TIME_BLOCK_SIZE, + "Storing %d bytes took too long time", sizeof(data_in)); + /* Verify data integrity */ zassert_ok(flash_area_read(fa, data_off, read_back, sizeof(data_in))); zassert_mem_equal(read_back, data_in, sizeof(data_in)); - (void)memset(read_back, 0, sizeof(data_in)); + /* Large data test */ dk_set_led(0, true); - tic = k_uptime_ticks(); + start_us = get_time_us(); emds_flash_write_data(&partition[partition_index], data_off + sizeof(data_in), data_in_big, sizeof(data_in_big)); - toc = k_uptime_ticks(); + end_us = get_time_us(); dk_set_led(0, false); - store_time_us = k_ticks_to_us_ceil64(toc - tic); - printk("Storing %d bytes took: %lldus\n", sizeof(data_in_big), store_time_us); - zassert_true(store_time_us < EXPECTED_STORE_TIME_1024, - "Storing %d bytes took too long time", sizeof(data_in_big)); + elapsed_us = end_us - start_us; + printk("Storing %d bytes took %uus\n", sizeof(data_in_big), elapsed_us); + zassert_true(elapsed_us < EXPECTED_STORE_TIME_1024, "Storing %d bytes took too long time", + sizeof(data_in_big)); + + /* Verify large data */ zassert_ok(flash_area_read(fa, data_off + sizeof(data_in), read_back, sizeof(data_in_big))); zassert_mem_equal(read_back, data_in_big, sizeof(data_in_big)); + + microsecond_timer_cleanup(); } ZTEST_SUITE(emds_flash, NULL, emds_flash_setup, NULL, emds_flash_partitions_erase, NULL); From e9c5861f9bc16ea6d4a57af00d06eaae67a9f6d2 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Tue, 2 Dec 2025 14:41:36 +0100 Subject: [PATCH 092/155] tests: emds: remove sdc call Commit removes sdc and mpsl calls. Since test is not related to Bluetooth, it does not have sence. With new mpsl scheduler it causes device reset after all tests passed. If to leave device with this test suite eventually will exhost the persistent memory endurance. Signed-off-by: Aleksandr Khromykh --- tests/subsys/emds/emds_flash/prj.conf | 1 - tests/subsys/emds/emds_flash/src/main.c | 5 ----- 2 files changed, 6 deletions(-) diff --git a/tests/subsys/emds/emds_flash/prj.conf b/tests/subsys/emds/emds_flash/prj.conf index b902b8539f83..b90913d8f038 100644 --- a/tests/subsys/emds/emds_flash/prj.conf +++ b/tests/subsys/emds/emds_flash/prj.conf @@ -9,5 +9,4 @@ CONFIG_FLASH=y CONFIG_FLASH_MAP=y CONFIG_DK_LIBRARY=y CONFIG_EMDS=y -CONFIG_BT=y CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/subsys/emds/emds_flash/src/main.c b/tests/subsys/emds/emds_flash/src/main.c index c0168c9dfdc6..a61dbf1c836e 100644 --- a/tests/subsys/emds/emds_flash/src/main.c +++ b/tests/subsys/emds/emds_flash/src/main.c @@ -586,11 +586,6 @@ ZTEST(emds_flash, test_write_speed) (void)dk_leds_init(); (void)dk_set_led(0, false); -#if defined(CONFIG_BT) - /* This is done to turn off mpsl scheduler to speed up storage time. */ - (void)sdc_disable(); - mpsl_uninit(); -#endif /* Initialize microsecond timer */ microsecond_timer_init(); From d0f3f5c43b13d1108b0d14a739c4bd8cc2145231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katarzyna=20Gi=C4=85d=C5=82a?= Date: Wed, 3 Dec 2025 11:47:14 +0100 Subject: [PATCH 093/155] quarantine: Add quarantine for radio_test sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue with `sample.peripheral.radio_test` should be quarantined until fix. Signed-off-by: Katarzyna Giądła --- scripts/quarantine.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/quarantine.yaml b/scripts/quarantine.yaml index 8842e51b6370..5ce6418b371b 100644 --- a/scripts/quarantine.yaml +++ b/scripts/quarantine.yaml @@ -106,3 +106,9 @@ platforms: - nrf5340dk/nrf5340/cpuapp comment: "https://nordicsemi.atlassian.net/browse/NRFX-8480" + +- scenarios: + - sample.peripheral.radio_test + platforms: + - nrf54ls05dk@0.0.0/nrf54ls05b/cpuapp + comment: "https://nordicsemi.atlassian.net/browse/NCSDK-36650" From 2e3a0fa741cd33ecbf0e517d4b88781464dfb16f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katarzyna=20Gi=C4=85d=C5=82a?= Date: Wed, 3 Dec 2025 11:49:59 +0100 Subject: [PATCH 094/155] quarantine: Add quarantine for benchmark tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test configurations `boards.nrf.i2c.i2c_endless.*` will be quarantined until fix. Signed-off-by: Katarzyna Giądła --- scripts/quarantine.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/quarantine.yaml b/scripts/quarantine.yaml index 5ce6418b371b..c15578425357 100644 --- a/scripts/quarantine.yaml +++ b/scripts/quarantine.yaml @@ -112,3 +112,10 @@ platforms: - nrf54ls05dk@0.0.0/nrf54ls05b/cpuapp comment: "https://nordicsemi.atlassian.net/browse/NCSDK-36650" + +- scenarios: + - boards.nrf.i2c.i2c_endless.host + - boards.nrf.i2c.i2c_endless.device + platforms: + - nrf5340dk/nrf5340/cpuapp + comment: "https://nordicsemi.atlassian.net/browse/NCSDK-36649" From f7a59a8630d770ad34fadb539266c5580ebb87e5 Mon Sep 17 00:00:00 2001 From: Robert Robinson Date: Thu, 13 Nov 2025 14:28:23 +0000 Subject: [PATCH 095/155] tests: Update pins to align with Malago FPGA pinset. Some of the tests were not possible to run on previous HFV bitstream and so new bitstream has been generated Updates: I2C - Required pull-ups on SCL/SDA pins NFC as GPIO - Requires specific pins to be part of a loopback UART tests required updates given pin changes Default uart changed from uart00 to uart20 for TF-M sample tests. Signed-off-by: Robert Robinson --- .../nrf7120pdk/nrf7120pdk_nrf7120-pinctrl.dtsi | 8 ++++---- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 10 +++++----- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 12 ++++++------ .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 8 ++++---- .../qdec/boards/nrf7120pdk_nrf7120_common.dtsi | 10 +++++----- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 10 +++++----- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 10 +++++----- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 6 +++--- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 10 +++++----- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 8 ++++---- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 8 ++++---- .../nrf7120pdk_nrf7120_cpuapp_dual_uart.overlay | 8 ++++---- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 8 ++++---- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 16 ++++++++-------- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 8 ++++---- 15 files changed, 70 insertions(+), 70 deletions(-) diff --git a/boards/nordic/nrf7120pdk/nrf7120pdk_nrf7120-pinctrl.dtsi b/boards/nordic/nrf7120pdk/nrf7120pdk_nrf7120-pinctrl.dtsi index f9cd55542ec9..589d75c817b8 100644 --- a/boards/nordic/nrf7120pdk/nrf7120pdk_nrf7120-pinctrl.dtsi +++ b/boards/nordic/nrf7120pdk/nrf7120pdk_nrf7120-pinctrl.dtsi @@ -30,12 +30,12 @@ /omit-if-no-ref/ uart30_default: uart30_default { group1 { psels = , - ; + ; }; group2 { psels = , - ; + ; bias-pull-up; }; }; @@ -44,8 +44,8 @@ group1 { psels = , , - , - ; + , + ; low-power-enable; }; }; diff --git a/samples/zephyr/drivers/i2c/rtio_loopback/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/samples/zephyr/drivers/i2c/rtio_loopback/boards/nrf7120pdk_nrf7120_cpuapp.overlay index 3035cc168c2f..e2cde1e64c84 100644 --- a/samples/zephyr/drivers/i2c/rtio_loopback/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/samples/zephyr/drivers/i2c/rtio_loopback/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -6,7 +6,7 @@ /* * SDA = P1.8 and P1.9 - * SCL = P1.14 and P1.15 + * SCL = P1.2 and P1.3 */ / { @@ -20,7 +20,7 @@ i2c21_default: i2c21_default { group1 { psels = , - ; + ; bias-pull-up; }; }; @@ -28,7 +28,7 @@ i2c21_sleep: i2c21_sleep { group1 { psels = , - ; + ; low-power-enable; }; }; @@ -36,7 +36,7 @@ i2c22_default: i2c22_default { group1 { psels = , - ; + ; bias-pull-up; }; }; @@ -44,7 +44,7 @@ i2c22_sleep: i2c22_sleep { group1 { psels = , - ; + ; low-power-enable; }; }; diff --git a/tests/drivers/gpio/gpio_nfct/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/drivers/gpio/gpio_nfct/boards/nrf7120pdk_nrf7120_cpuapp.overlay index 3c666009ff1d..46e4da08639b 100644 --- a/tests/drivers/gpio/gpio_nfct/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/drivers/gpio/gpio_nfct/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -6,18 +6,18 @@ / { /* Test requirements: - * P1.00 shorted with P1.01; - * P1.02 shorted with P1.03. - * (NFC pins are P1.01 and P1.02) + * P0.00 shorted with P0.03; + * P0.12 shorted with P0.04. + * (NFC pins are P0.03 and P0.04) */ test_gpios { compatible = "gpio-leds"; out_gpios: out_gpios { - gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>, <&gpio1 2 GPIO_ACTIVE_HIGH>; + gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>, <&gpio0 12 GPIO_ACTIVE_HIGH>; }; in_gpios: in_gpios { - gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>, <&gpio1 3 GPIO_ACTIVE_HIGH>; + gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>, <&gpio0 4 GPIO_ACTIVE_HIGH>; }; }; }; @@ -30,6 +30,6 @@ status = "okay"; }; -&gpio1 { +&gpio0 { status = "okay"; }; diff --git a/tests/zephyr/boards/nrf/i2c/i2c_slave/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/zephyr/boards/nrf/i2c/i2c_slave/boards/nrf7120pdk_nrf7120_cpuapp.overlay index e6aaec1a86a1..a592761249e5 100644 --- a/tests/zephyr/boards/nrf/i2c/i2c_slave/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/zephyr/boards/nrf/i2c/i2c_slave/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -8,14 +8,14 @@ i2c21_default_alt: i2c21_default_alt { group1 { psels = , - ; + ; }; }; i2c21_sleep_alt: i2c21_sleep_alt { group1 { psels = , - ; + ; low-power-enable; }; }; @@ -26,7 +26,7 @@ * to configure pins for TWIS with pinctrl. */ psels = , - ; + ; bias-pull-up; }; }; @@ -34,7 +34,7 @@ i2c22_sleep_alt: i2c22_sleep_alt { group1 { psels = , - ; + ; low-power-enable; }; }; diff --git a/tests/zephyr/boards/nrf/qdec/boards/nrf7120pdk_nrf7120_common.dtsi b/tests/zephyr/boards/nrf/qdec/boards/nrf7120pdk_nrf7120_common.dtsi index 1ebe3169eae3..91aeb58ff5e6 100644 --- a/tests/zephyr/boards/nrf/qdec/boards/nrf7120pdk_nrf7120_common.dtsi +++ b/tests/zephyr/boards/nrf/qdec/boards/nrf7120pdk_nrf7120_common.dtsi @@ -7,8 +7,8 @@ /* Required loopbacks * P1.11 <-> P1.12 * P1.13 <-> P1.15 - * P1.2 <-> P1.3 - * P1.4 <-> P2.5 + * P1.02 <-> P1.3 + * P1.00 <-> P1.14 */ / { @@ -24,7 +24,7 @@ gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; }; phase_b1: phase_b1 { - gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; }; }; @@ -60,14 +60,14 @@ qdec_21_pinctrl: qdec_21_pinctrl { group1 { psels = , - ; + ; }; }; qdec_21_sleep_pinctrl: qdec_21_sleep_pinctrl { group1 { psels = , - ; + ; low-power-enable; }; }; diff --git a/tests/zephyr/drivers/i2c/i2c_nrfx_twim/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/zephyr/drivers/i2c/i2c_nrfx_twim/boards/nrf7120pdk_nrf7120_cpuapp.overlay index 0a155c601955..5407e0715184 100644 --- a/tests/zephyr/drivers/i2c/i2c_nrfx_twim/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/zephyr/drivers/i2c/i2c_nrfx_twim/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -6,7 +6,7 @@ /* * SDA = P1.8 and P1.9 - * SCL = P1.14 and P1.15 + * SCL = P1.2 and P1.3 */ / { @@ -20,7 +20,7 @@ i2c21_default: i2c21_default { group1 { psels = , - ; + ; bias-pull-up; }; }; @@ -28,7 +28,7 @@ i2c21_sleep: i2c21_sleep { group1 { psels = , - ; + ; low-power-enable; }; }; @@ -36,7 +36,7 @@ i2c22_default: i2c22_default { group1 { psels = , - ; + ; bias-pull-up; }; }; @@ -44,7 +44,7 @@ i2c22_sleep: i2c22_sleep { group1 { psels = , - ; + ; low-power-enable; }; }; diff --git a/tests/zephyr/drivers/i2c/i2c_target_api/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/zephyr/drivers/i2c/i2c_target_api/boards/nrf7120pdk_nrf7120_cpuapp.overlay index 83b7ecf43ace..5027cf022045 100644 --- a/tests/zephyr/drivers/i2c/i2c_target_api/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/zephyr/drivers/i2c/i2c_target_api/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -1,13 +1,13 @@ /* * SDA = P1.8 and P1.9 - * SCL = P1.14 and P1.15 + * SCL = P1.2 and P1.3 */ &pinctrl { i2c21_default: i2c21_default { group1 { psels = , - ; + ; bias-pull-up; }; }; @@ -15,7 +15,7 @@ i2c21_sleep: i2c21_sleep { group1 { psels = , - ; + ; low-power-enable; }; }; @@ -23,7 +23,7 @@ i2c22_default: i2c22_default { group1 { psels = , - ; + ; bias-pull-up; }; }; @@ -31,7 +31,7 @@ i2c22_sleep: i2c22_sleep { group1 { psels = , - ; + ; low-power-enable; }; }; diff --git a/tests/zephyr/drivers/spi/spi_controller_peripheral/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/zephyr/drivers/spi/spi_controller_peripheral/boards/nrf7120pdk_nrf7120_cpuapp.overlay index 5dea09cb1e7b..85633930b6e6 100644 --- a/tests/zephyr/drivers/spi/spi_controller_peripheral/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/zephyr/drivers/spi/spi_controller_peripheral/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -27,7 +27,7 @@ psels = , , , - ; + ; }; }; @@ -36,7 +36,7 @@ psels = , , , - ; + ; low-power-enable; }; }; @@ -52,7 +52,7 @@ pinctrl-1 = <&spi22_sleep_alt>; pinctrl-names = "default", "sleep"; overrun-character = <0x00>; - cs-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; + cs-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; zephyr,pm-device-runtime-auto; dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; diff --git a/tests/zephyr/drivers/spi/spi_loopback/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/zephyr/drivers/spi/spi_loopback/boards/nrf7120pdk_nrf7120_cpuapp.overlay index ba6bbc58addb..0665e07b24d7 100644 --- a/tests/zephyr/drivers/spi/spi_loopback/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/zephyr/drivers/spi/spi_loopback/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -6,15 +6,15 @@ /* * Test requires following loopback: - * P1.4 - P1.5 + * P1.11 - P1.12 */ &pinctrl { spi20_default: spi20_default { group1 { psels = , - , - ; + , + ; low-power-enable; }; }; @@ -22,8 +22,8 @@ spi20_sleep: spi20_sleep { group1 { psels = , - , - ; + , + ; low-power-enable; }; }; diff --git a/tests/zephyr/drivers/uart/uart_async_api/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/zephyr/drivers/uart/uart_async_api/boards/nrf7120pdk_nrf7120_cpuapp.overlay index cf425f2d2926..20dbf11339bf 100644 --- a/tests/zephyr/drivers/uart/uart_async_api/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/zephyr/drivers/uart/uart_async_api/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -7,15 +7,15 @@ &pinctrl { uart21_default_alt: uart21_default_alt { group1 { - psels = , - ; + psels = , + ; }; }; uart21_sleep_alt: uart21_sleep_alt { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; diff --git a/tests/zephyr/drivers/uart/uart_elementary/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/zephyr/drivers/uart/uart_elementary/boards/nrf7120pdk_nrf7120_cpuapp.overlay index 9e000f530996..fc26bdafc3f8 100644 --- a/tests/zephyr/drivers/uart/uart_elementary/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/zephyr/drivers/uart/uart_elementary/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -7,8 +7,8 @@ &pinctrl { uart21_default: uart21_default { group1 { - psels = , - , + psels = , + , , ; }; @@ -16,8 +16,8 @@ uart21_sleep: uart21_sleep { group1 { - psels = , - , + psels = , + , , ; low-power-enable; diff --git a/tests/zephyr/drivers/uart/uart_elementary/boards/nrf7120pdk_nrf7120_cpuapp_dual_uart.overlay b/tests/zephyr/drivers/uart/uart_elementary/boards/nrf7120pdk_nrf7120_cpuapp_dual_uart.overlay index 0e410fd32141..9099ef29406c 100644 --- a/tests/zephyr/drivers/uart/uart_elementary/boards/nrf7120pdk_nrf7120_cpuapp_dual_uart.overlay +++ b/tests/zephyr/drivers/uart/uart_elementary/boards/nrf7120pdk_nrf7120_cpuapp_dual_uart.overlay @@ -7,7 +7,7 @@ &pinctrl { uart21_default: uart21_default { group1 { - psels = , + psels = , ; bias-pull-up; }; @@ -15,7 +15,7 @@ uart21_sleep: uart21_sleep { group1 { - psels = , + psels = , ; low-power-enable; }; @@ -24,7 +24,7 @@ uart22_default: uart22_default { group1 { psels = , - ; + ; bias-pull-up; }; }; @@ -32,7 +32,7 @@ uart22_sleep: uart22_sleep { group1 { psels = , - ; + ; low-power-enable; }; }; diff --git a/tests/zephyr/drivers/uart/uart_errors/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/zephyr/drivers/uart/uart_errors/boards/nrf7120pdk_nrf7120_cpuapp.overlay index 05cbb25c9716..0f56ec825d87 100644 --- a/tests/zephyr/drivers/uart/uart_errors/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/zephyr/drivers/uart/uart_errors/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -8,14 +8,14 @@ uart21_default: uart21_default { group1 { psels = , - ; + ; }; }; uart21_sleep: uart21_sleep { group1 { psels = , - ; + ; low-power-enable; }; }; @@ -23,7 +23,7 @@ uart22_default: uart22_default { group1 { psels = - ; + ; bias-pull-up; }; group2 { @@ -34,7 +34,7 @@ uart22_sleep: uart22_sleep { group1 { psels = , - ; + ; low-power-enable; }; }; diff --git a/tests/zephyr/drivers/uart/uart_mix_fifo_poll/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/zephyr/drivers/uart/uart_mix_fifo_poll/boards/nrf7120pdk_nrf7120_cpuapp.overlay index 16a9a2702e23..3c8d4b62af23 100644 --- a/tests/zephyr/drivers/uart/uart_mix_fifo_poll/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/zephyr/drivers/uart/uart_mix_fifo_poll/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -7,19 +7,19 @@ &pinctrl { uart21_default: uart21_default { group1 { - psels = , - , - , - ; + psels = , + , + , + ; }; }; uart21_sleep: uart21_sleep { group1 { - psels = , - , - , - ; + psels = , + , + , + ; low-power-enable; }; }; diff --git a/tests/zephyr/drivers/uart/uart_pm/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/zephyr/drivers/uart/uart_pm/boards/nrf7120pdk_nrf7120_cpuapp.overlay index e7f84d0411c8..89f72b1eb9f0 100644 --- a/tests/zephyr/drivers/uart/uart_pm/boards/nrf7120pdk_nrf7120_cpuapp.overlay +++ b/tests/zephyr/drivers/uart/uart_pm/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -7,15 +7,15 @@ &pinctrl { uart21_default: uart21_default { group1 { - psels = , - ; + psels = , + ; }; }; uart21_sleep: uart21_sleep { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; From 2f1d588224ffea582d51231412447f7a60f13e63 Mon Sep 17 00:00:00 2001 From: Robert Robinson Date: Thu, 20 Nov 2025 11:38:07 +0000 Subject: [PATCH 096/155] dts: common: nordic: Correct ngpios on ports for nrf7120_enga ngpios on nRF7120 were incorrect, values updated to align with spec. Signed-off-by: Robert Robinson --- dts/common/nordic/nrf7120_enga.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dts/common/nordic/nrf7120_enga.dtsi b/dts/common/nordic/nrf7120_enga.dtsi index 55ba72123a19..918d1e2fd6db 100644 --- a/dts/common/nordic/nrf7120_enga.dtsi +++ b/dts/common/nordic/nrf7120_enga.dtsi @@ -643,7 +643,7 @@ gpio-controller; #gpio-cells = <2>; port = <1>; - ngpios = <20>; + ngpios = <16>; gpiote-instance = <&gpiote20>; status = "disabled"; }; @@ -654,7 +654,7 @@ gpio-controller; #gpio-cells = <2>; port = <3>; - ngpios = <13>; + ngpios = <12>; gpiote-instance = <&gpiote20>; status = "disabled"; }; @@ -842,7 +842,7 @@ gpio-controller; #gpio-cells = <2>; port = <0>; - ngpios = <10>; + ngpios = <13>; gpiote-instance = <&gpiote30>; status = "disabled"; }; From 7d34aa75fce1618eaee1f8c0cb4725d194c369da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Mon, 1 Dec 2025 15:25:20 +0100 Subject: [PATCH 097/155] doc: security: Correct ISE versions supported by NCS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct the ISE versions supported by NCS. 3.1.x does not support ISE. The main branch is currently using +19 in CI. Signed-off-by: Sebastian Bøe --- doc/nrf/security.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/nrf/security.rst b/doc/nrf/security.rst index fd446a8180a1..68c2f7befafe 100644 --- a/doc/nrf/security.rst +++ b/doc/nrf/security.rst @@ -21,7 +21,7 @@ The |NCS| |release| allows you to develop applications with the following versio - Mbed TLS version * - |release| - v2.2.0 - - v23.0.2+17 + - v23.1.0+19 - 3.6.5 .. security_components_ver_table_end @@ -52,11 +52,11 @@ Expand the following section to see the table listing versions of different secu - 3.6.5 * - v3.2.0 - v2.2.0 - - v23.0.2+17 + - v23.1.0+19 - 3.6.5 * - v3.1.0, v3.1.1 - v2.1.2 - - v20.0.0+1 + - n/a - 3.6.4 * - v3.0.0 (up to v3.0.2) - v2.1.1 From df96a13db92399572cea60eeee43363309b2c7f8 Mon Sep 17 00:00:00 2001 From: Francesco Domenico Servidio Date: Thu, 27 Nov 2025 16:50:51 +0100 Subject: [PATCH 098/155] doc: Misc doc edits pre 3.2.0-rc1 release Miscellaneous doc updates -for the upcoming 3.2.0-rc1 release. Signed-off-by: Francesco Domenico Servidio --- .../nrf54h/ug_nrf54h20_pm_optimization.rst | 159 ++++++++++++++++-- 1 file changed, 144 insertions(+), 15 deletions(-) diff --git a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_pm_optimization.rst b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_pm_optimization.rst index 17af66fd3a43..07ffceebd48e 100644 --- a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_pm_optimization.rst +++ b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_pm_optimization.rst @@ -64,6 +64,88 @@ The power management subsystem in a local domain is responsible for scheduling a The wake-up time scheduled in advance by the power management subsystem is combined with the advance time added by the software module. This approach ensures that the local domain and the software modules anticipating an event have sufficient time to fully restore before the event occurs, allowing the event to be handled without latency. +Logical domains, power domains, and locality +============================================ + +The nRF54H20 SoC groups hardware into logical domains and power domains. +The two domain types are defined as follows: + +Logical domain + A software-visible functional grouping that aggregates cores, memories, and peripherals behind a common isolation or security boundary (for example, application domain, radio domain, global domain). + +Power domain + A granular silicon region that can be clock- or power-gated independently. + Each physical silicon region has its own retention and leakage characteristics as well as voltage and frequency constraints (for example, high-speed instead of low-leakage subregions inside the application logical domain). + +A single logical domain can span multiple power domains. +A logical domain frequently contains a low-leakage power domain (cheap retention, low frequency) and one or more high-speed power domains (higher leakage, higher attainable frequency). +DVFS applies only to high-speed domains. + +Locality principle +------------------ + +Power optimization is driven by keeping execution and data access local: + +* Prefer executing code from local RAM (TCM/local SRAM) within the active core's logical domain. +* Minimize accesses to MRAM (global non-volatile memory) to avoid waking other domains and incurring cache refill energy. +* Batch work: Gather peripheral data locally (auxiliary cores) and hand off larger buffers to high-performance cores for computation, instead of driving peripherals directly from high-performance cores. + +Peripheral access strategy +-------------------------- + +High-performance cores (application, radio main CPUs) are optimized for computation, not low-latency I/O paths. +Accessing peripherals from these cores expands the active footprint by adding additional power domains and interconnected segments, increasing energy for each transaction. + +Recommendations: + +* Use auxiliary or peripheral-oriented cores (for example, PPR- or FLPR-type helper cores) to perform SPI, I2C, ADC, or UART transactions, local preprocessing, and DMA into local RAM. +* Signal (IPC or shared memory flag) the application or radio core only when a batch of data is ready. +* Avoid fine-grained peripheral polling from high-performance cores. + Use the following instead: + + * DMA transfers initiated by auxiliary cores. + * Hardware-trigger chains (PPI/DPPI) where possible to reduce wake-ups. + +* Keep high-speed power domains off unless necessary for bursts of compute. + +DMA locality constraints +------------------------ + +Local DMA controllers are restricted to source/destination addresses within their local RAM range. +Plan buffer placement accordingly: + +* Cross-domain transfers should use the following: + + * IPC messages indicating buffer readiness. + * Explicit software copy (only for infrequent cases). + +Local and global wake-up planning +--------------------------------- + +On local domain wake-ups (suspend-to-RAM/suspend-to-idle), schedule GRTC events early enough to cover the following latencies: + + * Core restore latency (cache, context). + * Software module restore latency (driver reconfiguration). + +Integration checklist +--------------------- + +For optimal power management integration, follow these guidelines: + +* Place time-critical ISR code and frequently used data structures in local RAM sections (see code/data relocation). +* Profile cache miss sources. + Reduce MRAM fetches by relocating hot code paths. +* Disable MRAM latency manager (set :kconfig:option:`CONFIG_MRAM_LATENCY` to ``n`` and :kconfig:option:`CONFIG_MRAM_LATENCY_AUTO_REQ` to ``n``) to allow MRAM power gating. + You can set :kconfig:option:`CONFIG_MRAM_LATENCY` to ``y`` to allow requesting low latency MRAM when needed. + However, avoid setting :kconfig:option:`CONFIG_MRAM_LATENCY_AUTO_REQ` to ``y``, as it causes MRAM to always remain in low latency/higher current mode. +* Ensure DVFS settings are evaluated across workloads. + Higher frequencies often yield best energy/operation for periodic burst tasks (quick wake, work, sleep), while lower or middle frequencies are better suited for long-running continuous workloads. +* Consolidate periodic tasks (sensor sample, radio tick) to a shared 1 ms or coarser schedule to avoid fragmented wake-ups. + +.. note:: + The exact wake-up source list can evolve with silicon revisions. + Always verify against the current SoC datasheet and release notes. + Optimization example ******************** @@ -185,10 +267,14 @@ The following recommendations help optimize memory placement and cache usage to For more information, see the :ref:`zephyr:code_data_relocation` page. * Profile L1 cache usage to minimize MRAM accesses. For more information, see ``nrf_cache_hal`` in the `nrfx API documentation`_. -* Ensure the MRAM latency manager is disabled: +* Configure the MRAM latency manager: + + * :kconfig:option:`CONFIG_MRAM_LATENCY`: - * :kconfig:option:`CONFIG_MRAM_LATENCY` set to ``n`` (default) allows MRAM to power off when idle. - * :kconfig:option:`CONFIG_MRAM_LATENCY_AUTO_REQ` disabled prevents automatic MRAM-on requests. + * ``n`` (default) allows MRAM to power off when idle. + * ``y`` allows requesting low latency MRAM when needed. + + * :kconfig:option:`CONFIG_MRAM_LATENCY_AUTO_REQ` set to ``n`` prevents MRAM from always being in low latency/higher current mode. Peripheral and clock recommendations ==================================== @@ -207,7 +293,8 @@ DVFS on application core ------------------------ The application core supports Dynamic Voltage and Frequency Scaling (DVFS), offering three distinct frequency options. -While the lowest or middle frequencies typically provide the best power efficiency, it is recommended to test each setting to determine the optimal choice for your specific use case. +Higher frequencies typically provide the best power efficiency for periodic burst workloads (minimizing wake time to maximize sleep), while lower or middle frequencies are better suited for long-running continuous tasks where the CPU remains active. +It is recommended to test each setting to determine the optimal choice for your specific use case. Reduction of wake-ups --------------------- @@ -215,8 +302,8 @@ Reduction of wake-ups Waking up the radio core at a 1-ms interval consumes approximately 50 µA of average current. To minimize power consumption, design your application to avoid frequent wake-ups by synchronizing events, such as sensor sampling, or by using the PPI to trigger tasks without CPU intervention. -Single- vs dual-core considerations -=================================== +Single-core and dual-core considerations +======================================== When choosing between single-core and dual-core architectures (using either the application core, the radio core, or both), consider the following trade-offs: @@ -233,21 +320,63 @@ When choosing between single-core and dual-core architectures (using either the return 0; } -Deep-sleep policy -================= +Deep-sleep policy and latency optimization +========================================== -Some peripherals do not schedule an expected wake-up, which can cause Zephyr's power manager to enter and almost immediately exit a deep sleep state. -This consumes a lot of energy and incurs overhead from pre-sleep checks. -This issue often occurs when the system is awakened by an external source, such as an IPC signal from another core, where it is not possible to properly schedule an expected wake-up event. -Additionally, whenever the application attempts to enter a sleep state, the Zephyr subsystem performs numerous operations to determine whether to transition the SoC into a low-power mode. +Most peripherals do not schedule an expected wake-up event, which can cause Zephyr's power manager to enter and almost immediately exit a deep sleep state. +This consumes unnecessary energy due to the overhead of putting the SoC to sleep and waking it up again, where entering a lighter sleep state would have been more efficient. -The minimum sleep durations that justify entering a deep sleep state are the following: +The minimum sleep durations that justify entering a deep sleep state are defined in the devicetree: * Suspend-to-Idle: ≥ 1 ms * Suspend-to-RAM: ≥ 2 ms -To prevent the system from entering deep sleep prematurely, use policy locks. -By acquiring a policy lock, you can disable deep-sleep states when the application is expected to run again in a short period (for example, at a 1 kHz rate). +For sleep durations shorter than these thresholds, an idle sleep state is more efficient. + +.. code-block:: devicetree + + idle_cache_disabled: idle_cache_disabled { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <2>; + min-residency-us = <1000>; + exit-latency-us = <7>; + }; + + s2ram: s2ram { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + min-residency-us = <2000>; + exit-latency-us = <33>; + }; + +To prevent the system from entering a deep sleep state prematurely, the application must inform Zephyr when the next wake-up event is expected to occur. +The following sections describe different approaches for managing sleep states and latency. + +Scheduling expected wake-up events +---------------------------------- + +Using ``pm_policy_event_register()``, the application can define the exact time when the next wake-up event is expected to occur. +Zephyr uses this information, along with other registered events (including ``k_timer`` timeouts and when sleeping threads are expected to wake up), to prevent entering a sleep state that is too deep. +The ``min-residency-us`` values in the devicetree define the minimum sleep durations required to justify entering each sleep state. + +This approach provides optimal power management for all expected wake-up events, with no notable impact on latency since Zephyr takes the ``exit-latency-us`` wake-up latency into account when selecting a sleep state. + +However, unexpected wake-up events, such as a button press, will have unpredictable latency since the system may be in deep sleep when the event occurs. + +Ensuring consistent latency for unexpected events +------------------------------------------------- + +To ensure consistent latency for unexpected events, use the ``pm_policy_latency_request_add()`` API. +This allows the application to define the maximum acceptable latency at any given time, which corresponds to the ``exit-latency-us`` wake-up time from the power sleep state. + +For example, the application can request a maximum latency of 7 microseconds, which prevents the CPU from entering the ``s2ram`` state (with its 33 µs exit latency) in the previously mentioned devicetree example, regardless of when the next event is scheduled. + +Using policy locks +------------------ + +For simpler use cases, you can use policy locks to disable deep-sleep states when the application is expected to run again in a short period (for example, at a 1 kHz rate). +By acquiring a policy lock, you prevent the system from entering specific sleep states. This can save up to 0.5 mA. .. code-block:: c From 739aee7964c756b06780a40edf9ba71428236a76 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Wed, 3 Dec 2025 08:38:04 +0000 Subject: [PATCH 099/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3584 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 3bd6c35e5dad..52d71dae4421 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: fc695cbbf493d4a50e6d6c48fb0d87ebaebba998 + revision: 66cda9da197b27272cd50fbdb788620c70b05bd5 import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From 4af2ba78ad576abf9340575dc34e538a73a5d00d Mon Sep 17 00:00:00 2001 From: Bartlomiej Buczek Date: Wed, 3 Dec 2025 13:01:33 +0100 Subject: [PATCH 100/155] scripts: quarantine: Update quarantine for nrfx examples. Majority of samples are already working fine. Signed-off-by: Bartlomiej Buczek --- scripts/quarantine_zephyr.yaml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/quarantine_zephyr.yaml b/scripts/quarantine_zephyr.yaml index 5ea69b30d338..212991869208 100644 --- a/scripts/quarantine_zephyr.yaml +++ b/scripts/quarantine_zephyr.yaml @@ -595,5 +595,12 @@ comment: "https://nordicsemi.atlassian.net/browse/NRFX-8497" - scenarios: - - examples.nrfx.* - comment: "https://nordicsemi.atlassian.net/browse/NRFX-8588" + - examples.nrfx_spim_spis.advanced_non_blocking + - examples.nrfx_spim_spis.non_blocking + - examples.nrfx_twim_twis.blocking + - examples.nrfx_twim_twis.non_blocking + - examples.nrfx_twim_twis.txrx + - examples.nrfx_twim_twis.txtx + platforms: + - nrf54l15dk/nrf54l15/cpuapp + comment: "https://nordicsemi.atlassian.net/browse/NRFX-8652" From ead1f8061bbedb734f962f766171c8d29ef41f6a Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Wed, 3 Dec 2025 12:31:46 +0100 Subject: [PATCH 101/155] Revert "samples: bluetooth: power profiling disable system off with tfm" This reverts commit 28c76d249759975d0c33735b3be7d1659d7a0bdd. Signed-off-by: Piotr Kosycarz --- samples/bluetooth/peripheral_power_profiling/src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/bluetooth/peripheral_power_profiling/src/main.c b/samples/bluetooth/peripheral_power_profiling/src/main.c index 5ccad49be18b..490218faa6e9 100644 --- a/samples/bluetooth/peripheral_power_profiling/src/main.c +++ b/samples/bluetooth/peripheral_power_profiling/src/main.c @@ -653,7 +653,7 @@ static void reset_reason_print(void) static void system_off(void) { -#if !IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX) && !IS_ENABLED(CONFIG_TFM_EXPERIMENTAL) +#if !IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX) printk("Powering off\n"); /* Clear the reset reason if it didn't do previously. */ @@ -674,7 +674,7 @@ static void system_off(void) } sys_poweroff(); -#endif /* !IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX) && !IS_ENABLED(CONFIG_TFM_EXPERIMENTAL) */ +#endif /* !IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX) */ } static void system_off_work_handler(struct k_work *work) From d8dbb1bd4a77e8f74617d62480ec848f2bee66ea Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Wed, 3 Dec 2025 12:32:56 +0100 Subject: [PATCH 102/155] samples: bluetooth: peripheral_power_profiling: do system off for lv10/ns Enable system off for lv10/ns. Signed-off-by: Piotr Kosycarz --- .../boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/samples/bluetooth/peripheral_power_profiling/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf b/samples/bluetooth/peripheral_power_profiling/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf index 3a6ccd751049..e08859b792a6 100644 --- a/samples/bluetooth/peripheral_power_profiling/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf +++ b/samples/bluetooth/peripheral_power_profiling/boards/nrf54lv10dk_nrf54lv10a_cpuapp_ns.conf @@ -17,3 +17,6 @@ CONFIG_PM_DEVICE_RUNTIME=y # RRAM always on, not needed for basic bluetooth features. CONFIG_MPSL_FORCE_RRAM_ON_ALL_THE_TIME=n + +CONFIG_TFM_SFN=y +CONFIG_TFM_NRF_SYSTEM_OFF_SERVICE=y From 18b7daa38f02df657c96420b20b3f3e211e6f5fb Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Tue, 2 Dec 2025 10:04:56 +0000 Subject: [PATCH 103/155] manifest: Update sdk-nrfxlib revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-nrfxlib/pull/1948 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 52d71dae4421..ec4c9efac18e 100644 --- a/west.yml +++ b/west.yml @@ -143,7 +143,7 @@ manifest: - name: nrfxlib repo-path: sdk-nrfxlib path: nrfxlib - revision: 68e1843243c6719578c3d6680d77d981e9801bf2 + revision: 62ac75ca9a03481b92850fc43f8d04a5a7dea2c7 - name: trusted-firmware-m repo-path: sdk-trusted-firmware-m path: modules/tee/tf-m/trusted-firmware-m From 23987f68c623e42d1c2a60b33e41e115654879ae Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Wed, 3 Dec 2025 10:32:38 +0000 Subject: [PATCH 104/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3587 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index ec4c9efac18e..a3e6ccb95397 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: 66cda9da197b27272cd50fbdb788620c70b05bd5 + revision: 0a6b10d81b424c927ab76fe2e5d3a7bccb4359ad import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From d911cb3d9e1555859e2644f077b69d085078d3e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stine=20=C3=85kredalen?= Date: Tue, 2 Dec 2025 14:58:16 +0100 Subject: [PATCH 105/155] docs: bluetooth: mesh: Add provisioner authentication note MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds provisioning security note to Security toolbox section. The BTM_ECDH_P256_CMAC_AES128_AES_CCM algorithm does not provide protection against MITM attacks during provisioning if OOB public keys are not used. Signed-off-by: Stine Åkredalen --- doc/nrf/protocols/bt/bt_mesh/configuring.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/nrf/protocols/bt/bt_mesh/configuring.rst b/doc/nrf/protocols/bt/bt_mesh/configuring.rst index 94380b4c1f7e..215d8aa9b7c0 100644 --- a/doc/nrf/protocols/bt/bt_mesh/configuring.rst +++ b/doc/nrf/protocols/bt/bt_mesh/configuring.rst @@ -257,6 +257,9 @@ Zephyr's Mesh security toolbox implementation uses third-party crypto library AP * :kconfig:option:`CONFIG_BT_MESH_USES_TFM_PSA` - Enables use of the `Trusted Firmware M`_ PSA API based security toolbox (default option for platforms that support TF-M). Zephyr's Mesh operates with open key values, including storing them in the persistent memory. +.. note:: + For Bluetooth Mesh provisioning, authenticating with the BTM_ECDH_P256_CMAC_AES128_AES_CCM (0x00) algorithm does not provide protection against an active man-in-the-middle (MITM) attacker during the provisioning process if OOB public keys are not used. + The Bluetooth Mesh security toolbox based on the `PSA Certified Crypto API`_ does not operate with open key values. After Bluetooth Mesh receives an open key value, it immediately imports the key into the crypto library and receives the unique key identifier. The key identifiers are used in the security toolbox and stored in the persistent memory. From 3b026b8918d4f2b20d19a1ba6b76879dce3468e7 Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Wed, 3 Dec 2025 09:25:43 +0100 Subject: [PATCH 106/155] samples: common: mcumgr_bt_ota_dfu: Align checks in CMakeLists.txt Align the values used for configuration validation in `CMakeLists.txt` file with new Kconfig defaults to fix the validation. Jira: NCSDK-35623 Signed-off-by: Marek Pieta --- samples/common/mcumgr_bt_ota_dfu/CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/samples/common/mcumgr_bt_ota_dfu/CMakeLists.txt b/samples/common/mcumgr_bt_ota_dfu/CMakeLists.txt index 0edad3ad81ba..c8f57f8d7860 100644 --- a/samples/common/mcumgr_bt_ota_dfu/CMakeLists.txt +++ b/samples/common/mcumgr_bt_ota_dfu/CMakeLists.txt @@ -7,7 +7,7 @@ if(CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_VALIDATION) if(CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_SPEEDUP AND CONFIG_HAS_BT_CTLR) if((NOT (CONFIG_BT_BUF_ACL_TX_SIZE EQUAL 251)) OR - (NOT (CONFIG_BT_BUF_ACL_RX_SIZE EQUAL 502)) OR + (NOT (CONFIG_BT_BUF_ACL_RX_SIZE EQUAL 251)) OR (NOT (CONFIG_BT_CTLR_DATA_LENGTH_MAX EQUAL 251)) ) message(WARNING "MCUmgr Bluetooth OTA DFU: suboptimal configuration " @@ -20,8 +20,8 @@ if(CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_VALIDATION) if(CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_SPEEDUP AND CONFIG_BT_HCI_HOST) if((NOT (CONFIG_BT_BUF_ACL_TX_SIZE EQUAL 251)) OR - (NOT (CONFIG_BT_BUF_ACL_RX_SIZE EQUAL 502)) OR - (NOT (CONFIG_BT_L2CAP_TX_MTU EQUAL 498)) + (NOT (CONFIG_BT_BUF_ACL_RX_SIZE EQUAL 251)) OR + (NOT (CONFIG_BT_L2CAP_TX_MTU EQUAL 247)) ) message(WARNING "MCUmgr Bluetooth OTA DFU: suboptimal configuration " "of Bluetooth Host buffers. Consider using optimal values " @@ -33,7 +33,10 @@ if(CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_VALIDATION) if(CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU) if(CONFIG_MCUMGR_TRANSPORT_BT_REASSEMBLY) - if(NOT (CONFIG_MCUMGR_TRANSPORT_NETBUF_SIZE EQUAL 2475)) + # Allow for using default value specified by `nrf/samples/common/mcumgr_bt_ota_dfu/Kconfig` + # or `nrf/Kconfig.nrf`. + if((NOT (CONFIG_MCUMGR_TRANSPORT_NETBUF_SIZE EQUAL 1230)) AND + (NOT (CONFIG_MCUMGR_TRANSPORT_NETBUF_SIZE EQUAL 2475))) message(WARNING "MCUmgr Bluetooth OTA DFU: suboptimal configuration " "of the MCUmgr buffer with the Reassembly feature support. Consider using" "the optimal value defined in the ${CMAKE_CURRENT_LIST_DIR}/Kconfig " From 1f21492a6463c6c2babb7a60aaac88f7ece17457 Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Wed, 3 Dec 2025 09:29:16 +0100 Subject: [PATCH 107/155] samples: fast_pair: locator_tag: Align Bluetooth buffer sizes Align the CONFIG_BT_BUF_ACL_RX_SIZE with new default value set by the CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_SPEEDUP. Jira: NCSDK-35623 Signed-off-by: Marek Pieta --- .../locator_tag/sysbuild/common/dfu_speedup_fragment.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/bluetooth/fast_pair/locator_tag/sysbuild/common/dfu_speedup_fragment.conf b/samples/bluetooth/fast_pair/locator_tag/sysbuild/common/dfu_speedup_fragment.conf index 510f075d551a..9b88dffb7d92 100644 --- a/samples/bluetooth/fast_pair/locator_tag/sysbuild/common/dfu_speedup_fragment.conf +++ b/samples/bluetooth/fast_pair/locator_tag/sysbuild/common/dfu_speedup_fragment.conf @@ -9,5 +9,5 @@ CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_SPEEDUP=y # Needs to be set explicitly as the CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_SPEEDUP # only sets the defaults which are overwritten by the prj.conf file CONFIG_BT_BUF_ACL_TX_SIZE=251 -CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_RX_SIZE=251 CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 From f6d75debed93d80d0a492927f06d0e53022362c2 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Tue, 2 Dec 2025 16:24:20 +0100 Subject: [PATCH 108/155] doc: nrf54l_ug: document cross domain pin mapping Document cross domain pin mapping and management of it. Signed-off-by: Bjarki Arge Andreasen --- .../app_dev/device_guides/nrf54l/index.rst | 1 + .../app_dev/device_guides/nrf54l/pinmap.rst | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 doc/nrf/app_dev/device_guides/nrf54l/pinmap.rst diff --git a/doc/nrf/app_dev/device_guides/nrf54l/index.rst b/doc/nrf/app_dev/device_guides/nrf54l/index.rst index 70e7b27d3208..6afc6b572262 100644 --- a/doc/nrf/app_dev/device_guides/nrf54l/index.rst +++ b/doc/nrf/app_dev/device_guides/nrf54l/index.rst @@ -91,3 +91,4 @@ This self-paced course introduces the hardware architecture, functionality, capa dfu_config ecies_x25519.rst otp_map_nrf54l + pinmap diff --git a/doc/nrf/app_dev/device_guides/nrf54l/pinmap.rst b/doc/nrf/app_dev/device_guides/nrf54l/pinmap.rst new file mode 100644 index 000000000000..4ea18f4c9b17 --- /dev/null +++ b/doc/nrf/app_dev/device_guides/nrf54l/pinmap.rst @@ -0,0 +1,49 @@ +.. _ug_nrf54l_pinmap: + +nRF54L pin mapping +################## + +.. contents:: + :local: + :depth: 2 + +The nRF54L Series SoCs manage power for peripherals and pins automatically when both are in the same domain. +The SoCs also support mapping pins across different domains, but this requires additional firmware management and periodic use of the Constant Latency sub-power mode. +As a result, this increases both latency and power consumption. + +Mapping pins across power-domains +********************************* + +The following sections explain how to map and manage pins within a single domain and across different domains. + +Understanding cross power-domain pin mapping +============================================ + +For information on possible pin assignments, refer to the *Pin assignments* chapter in the respective device’s datasheet. +The *Dedicated pins* and *Cross power-domain use* subsections document which pins can be connected across different domains. +See :ref:`ug_nrf54l` for a complete list of references. + +Managing cross power-domain pin mapping +======================================= + +To use a peripheral with pins mapped across different domains, you must enable the Constant Latency sub-power mode. +You can do this by setting the :kconfig:option:`CONFIG_NRF_SYS_EVENT` Kconfig option, and calling the :c:func:`nrf_sys_event_request_global_constlat` function in your application. + +See the following example: + +.. code-block:: c + + #include + + int main(void) + { + /* Request constlat. The API is reference counted. */ + nrf_sys_event_request_global_constlat(); + + /* Use peripherals which have pins mapped across power-domains */ + + /* Release constlat */ + nrf_sys_event_release_global_constlat(); + + return 0; + } From b0136081758228c9fceab9af1c9f1403b78a7efd Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Tue, 2 Dec 2025 16:33:40 +0100 Subject: [PATCH 109/155] doc: migration_guide_3.2: mention nrf54l pin cross domain rework Applications built for the nrf54l series SoCs must now manually request constlat if pins are mapped across domains. Mention this in the migration guide for 3.2. Signed-off-by: Bjarki Arge Andreasen --- .../migration/migration_guide_3.2.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst b/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst index 5377fdf632c1..78ec6cf64019 100644 --- a/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst +++ b/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst @@ -24,6 +24,19 @@ Required changes The following changes are mandatory to make your application work in the same way as in previous releases. +nRF54L +====== + +This section describes the changes specific to the nRF54L series SoCs and DKs support in the |NCS|. + +nRF54L pin cross power-domain use +--------------------------------- + +.. toggle:: + + * You must enable the Constant Latency sub-power mode from the application to allow cross power-domain pin mapping. + For details, see the :ref:`ug_nrf54l_pinmap` page. + nRF54H20 ======== From 95473bb86b804e35b70b7754bcf0848299254ace Mon Sep 17 00:00:00 2001 From: Mateusz Kapala Date: Fri, 28 Nov 2025 13:02:44 +0100 Subject: [PATCH 110/155] cmake: sysbuild: Fix slot size for direct-xip image signing Fixed slot size used for signing the images when the MCUboot works in the direct-xip mode. Previously slot size was always taken from the slot0 partition instead of the zephyr,code-partition. Jira: NCSDK-36461 Signed-off-by: Mateusz Kapala --- cmake/sysbuild/image_signing.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/sysbuild/image_signing.cmake b/cmake/sysbuild/image_signing.cmake index de833a9e8121..bb1a35707d07 100644 --- a/cmake/sysbuild/image_signing.cmake +++ b/cmake/sysbuild/image_signing.cmake @@ -90,6 +90,7 @@ function(zephyr_mcuboot_tasks) if(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT OR CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) dt_chosen(code_partition PROPERTY "zephyr,code-partition") dt_partition_addr(code_partition_offset PATH "${code_partition}" REQUIRED) + dt_reg_size(slot_size PATH "${code_partition}" REQUIRED) set(imgtool_rom_command --rom-fixed ${code_partition_offset}) endif() set(imgtool_sign ${PYTHON_EXECUTABLE} ${IMGTOOL} sign --version ${CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION} --align ${write_block_size} --slot-size ${slot_size} --header-size ${CONFIG_ROM_START_OFFSET} ${imgtool_rom_command}) From 615b36b3148b2747610c84300c2e8237b8a8a4c5 Mon Sep 17 00:00:00 2001 From: Jan Zyczkowski Date: Sun, 23 Nov 2025 23:36:21 +0100 Subject: [PATCH 111/155] samples: radio_loader: Add radio core firmware loader Add radio_loader sample for nRF54H20 that implements a two-stage boot process for the radio core. The loader copies firmware from MRAM to TCM (Tightly Coupled Memory) at boot time and jumps to the loaded firmware. The loader uses the following DTS nodelabels: - cpurad_slot0/1_partition - radio loader slot used to determine if the app runs from primary or secondary slot - cpurad_slot2/3 partition - firmware to be loaded into TCM (source) - cpurad_ram0 - radio core TCM RAM (destination for FW) JIRA: NCSDK-36461 Signed-off-by: Jan Zyczkowski Co-authored-by: Mateusz Kapala --- samples/nrf54h20/radio_loader/CMakeLists.txt | 13 ++ samples/nrf54h20/radio_loader/app.overlay | 14 +++ samples/nrf54h20/radio_loader/prj.conf | 94 ++++++++++++++ samples/nrf54h20/radio_loader/src/main.c | 122 +++++++++++++++++++ samples/nrf54h20/radio_loader/testcase.yaml | 12 ++ sysbuild/CMakeLists.txt | 1 + sysbuild/Kconfig.mcuboot | 1 + sysbuild/Kconfig.radio_loader | 30 +++++ sysbuild/Kconfig.sysbuild | 1 + sysbuild/radio_loader.cmake | 27 ++++ 10 files changed, 315 insertions(+) create mode 100644 samples/nrf54h20/radio_loader/CMakeLists.txt create mode 100644 samples/nrf54h20/radio_loader/app.overlay create mode 100644 samples/nrf54h20/radio_loader/prj.conf create mode 100644 samples/nrf54h20/radio_loader/src/main.c create mode 100644 samples/nrf54h20/radio_loader/testcase.yaml create mode 100644 sysbuild/Kconfig.radio_loader create mode 100644 sysbuild/radio_loader.cmake diff --git a/samples/nrf54h20/radio_loader/CMakeLists.txt b/samples/nrf54h20/radio_loader/CMakeLists.txt new file mode 100644 index 000000000000..a3b2753538db --- /dev/null +++ b/samples/nrf54h20/radio_loader/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(radio_loader) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/nrf54h20/radio_loader/app.overlay b/samples/nrf54h20/radio_loader/app.overlay new file mode 100644 index 000000000000..cfbbe44e589d --- /dev/null +++ b/samples/nrf54h20/radio_loader/app.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Use existing node as source partition for demo purposes. */ +&cpuapp_slot0_partition { + reg = <0x92000 DT_SIZE_K(128)>; +}; + +/* Mock the node labels to satisfy the build */ +cpurad_slot2_partition: &cpuapp_slot0_partition {}; +cpurad_slot3_partition: &cpuapp_slot0_partition {}; diff --git a/samples/nrf54h20/radio_loader/prj.conf b/samples/nrf54h20/radio_loader/prj.conf new file mode 100644 index 000000000000..6f57c25fea86 --- /dev/null +++ b/samples/nrf54h20/radio_loader/prj.conf @@ -0,0 +1,94 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# ============================================================================== +# Optimized minimal configuration for radio_loader +# ============================================================================== +# This loader only runs SYS_INIT(load_and_jump_to_firmware, EARLY, 0) which: +# 1. Copies firmware from MRAM to TCM using memcpy() +# 2. Jumps to the loaded firmware's reset handler +# No Zephyr services, threading, or drivers are needed. +# +# Memory footprint target: < 4 KB + +# ============================================================================== +# Power Management +# ============================================================================== +CONFIG_PM=n +CONFIG_PM_DEVICE=n + +# ============================================================================== +# Kernel - Threading Disabled +# ============================================================================== +# We never reach main() or start the scheduler, so disable all threading +CONFIG_MULTITHREADING=n +CONFIG_MAIN_STACK_SIZE=512 +CONFIG_THREAD_STACK_INFO=n + +# Disable kernel features that require threading/scheduler +CONFIG_EVENTS=n +CONFIG_POLL=n +CONFIG_TIMESLICING=n + +# ============================================================================== +# Console, Debug, and Logging +# ============================================================================== +# No console output needed - loader jumps immediately to firmware +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_SERIAL=n +CONFIG_PRINTK=n +CONFIG_EARLY_CONSOLE=n +CONFIG_LOG=n + +# Banners and debug features +CONFIG_NCS_BOOT_BANNER=n +CONFIG_BOOT_BANNER=n +CONFIG_ERRNO=n + +# ============================================================================== +# Device Drivers +# ============================================================================== +# No peripheral drivers needed - we only use memcpy and jump +CONFIG_GPIO=n +CONFIG_PINCTRL=n +CONFIG_I2C=n +CONFIG_SPI=n +CONFIG_WATCHDOG=n + +# ============================================================================== +# Interrupt Management +# ============================================================================== +CONFIG_DYNAMIC_INTERRUPTS=n +CONFIG_IRQ_OFFLOAD=n +CONFIG_GEN_IRQ_VECTOR_TABLE=n +CONFIG_GEN_ISR_TABLES=n +CONFIG_GEN_SW_ISR_TABLE=n + +# ============================================================================== +# Hardware Protection +# ============================================================================== +CONFIG_HW_STACK_PROTECTION=n +CONFIG_ARM_MPU=n + +# ============================================================================== +# Security and Crypto +# ============================================================================== +# No crypto needed for simple memory copy operation +CONFIG_NRF_SECURITY=n +CONFIG_MBEDTLS_PSA_CRYPTO_C=n +CONFIG_PSA_CRYPTO_DRIVER_OBERON=n +CONFIG_PSA_CRYPTO=n +CONFIG_PSA_SSF_CRYPTO_CLIENT=n + +# ============================================================================== +# Memory Optimization +# ============================================================================== +CONFIG_HEAP_MEM_POOL_SIZE=0 +CONFIG_SYS_HEAP_RUNTIME_STATS=n + +# Use nano printf for minimal footprint (only used if PRINTK somehow gets enabled) +CONFIG_CBPRINTF_NANO=y diff --git a/samples/nrf54h20/radio_loader/src/main.c b/samples/nrf54h20/radio_loader/src/main.c new file mode 100644 index 000000000000..47ff6d76fc1f --- /dev/null +++ b/samples/nrf54h20/radio_loader/src/main.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +#define FIXED_PARTITION_ADDRESS(label) \ + (DT_REG_ADDR(DT_NODELABEL(label)) + \ + DT_REG_ADDR(COND_CODE_1(DT_FIXED_SUBPARTITION_EXISTS(DT_NODELABEL(label)), \ + (DT_GPARENT(DT_PARENT(DT_NODELABEL(label)))), \ + (DT_GPARENT(DT_NODELABEL(label)))))) + +#define FIXED_PARTITION_SIZE(label) DT_REG_SIZE(DT_NODELABEL(label)) + +#ifdef CONFIG_USE_DT_CODE_PARTITION +#define FLASH_LOAD_OFFSET DT_REG_ADDR(DT_CHOSEN(zephyr_code_partition)) +#elif defined(CONFIG_FLASH_LOAD_OFFSET) +#define FLASH_LOAD_OFFSET CONFIG_FLASH_LOAD_OFFSET +#endif + +#define PARTITION_IS_RUNNING_APP_PARTITION(label) \ + (DT_REG_ADDR(DT_NODELABEL(label)) <= FLASH_LOAD_OFFSET && \ + DT_REG_ADDR(DT_NODELABEL(label)) + DT_REG_SIZE(DT_NODELABEL(label)) > FLASH_LOAD_OFFSET) + +/* Used to determine the running slot of the radio loader. */ +#define RADIO_LOADER_PRIMARY_SLOT cpurad_slot0_partition +#define RADIO_LOADER_SECONDARY_SLOT cpurad_slot1_partition + +/* Used to determine the loaded firmware source address from NVM and size. */ +#define LOADED_FW_PRIMARY_SLOT cpurad_slot2_partition +#define LOADED_FW_SECONDARY_SLOT cpurad_slot3_partition + +/* Used to determine the running slot of the radio core. */ +#define RUNNING_FW_SLOT cpurad_ram0 +#define RUNNING_FW_SLOT_NODE DT_NODELABEL(RUNNING_FW_SLOT) +#define RUNNING_FW_SLOT_ADDR DT_REG_ADDR(RUNNING_FW_SLOT_NODE) +#define RUNNING_FW_SLOT_SIZE DT_REG_SIZE(RUNNING_FW_SLOT_NODE) + +BUILD_ASSERT(DT_NODE_EXISTS(DT_NODELABEL(RADIO_LOADER_PRIMARY_SLOT)), + "Missing nodelabel: cpurad_slot0_partition"); +BUILD_ASSERT(DT_NODE_EXISTS(DT_NODELABEL(RADIO_LOADER_SECONDARY_SLOT)), + "Missing nodelabel: cpurad_slot1_partition"); + +BUILD_ASSERT(DT_NODE_EXISTS(DT_NODELABEL(LOADED_FW_PRIMARY_SLOT)), + "Missing nodelabel: cpurad_slot2_partition"); +BUILD_ASSERT(DT_NODE_EXISTS(DT_NODELABEL(LOADED_FW_SECONDARY_SLOT)), + "Missing nodelabel: cpurad_slot3_partition"); +BUILD_ASSERT((FIXED_PARTITION_SIZE(LOADED_FW_PRIMARY_SLOT) == + FIXED_PARTITION_SIZE(LOADED_FW_SECONDARY_SLOT)), + "LOADED_FW_PRIMARY_SLOT and LOADED_FW_SECONDARY_SLOT sizes are not equal"); + +BUILD_ASSERT(DT_NODE_EXISTS(DT_NODELABEL(RUNNING_FW_SLOT)), + "Missing nodelabel: cpurad_ram0"); +BUILD_ASSERT((FIXED_PARTITION_SIZE(LOADED_FW_PRIMARY_SLOT) <= RUNNING_FW_SLOT_SIZE), + "LOADED_FW_PRIMARY_SLOT size exceeds RUNNING_FW_SLOT size"); +BUILD_ASSERT((FIXED_PARTITION_SIZE(LOADED_FW_SECONDARY_SLOT) <= RUNNING_FW_SLOT_SIZE), + "LOADED_FW_SECONDARY_SLOT size exceeds RUNNING_FW_SLOT size"); + +/** + * @brief Copy firmware from MRAM to TCM and jump to it + * + * This function runs as SYS_INIT(EARLY, 0) before main() and the scheduler. + * It copies the firmware from MRAM to TCM for optimal performance, then + * transfers execution to the loaded firmware's reset handler. + * + * This function never returns - execution transfers to the loaded firmware. + * + * @return 0 on success (never reached), -1 on failure (never reached) + */ +static int load_and_jump_to_firmware(void) +{ + /* Get the loaded firmware source address from NVM and size */ + void *loaded_fw_nvm_addr = NULL; + size_t loaded_fw_nvm_size = 0; + + /* Get the loaded firmware destination address from RAM and size */ + void *loaded_fw_ram_addr = (void *)(RUNNING_FW_SLOT_ADDR); + + if (PARTITION_IS_RUNNING_APP_PARTITION(RADIO_LOADER_PRIMARY_SLOT)) { + loaded_fw_nvm_addr = (void *)(FIXED_PARTITION_ADDRESS(LOADED_FW_PRIMARY_SLOT)); + loaded_fw_nvm_size = (size_t)(FIXED_PARTITION_SIZE(LOADED_FW_PRIMARY_SLOT)); + } else { + loaded_fw_nvm_addr = (void *)(FIXED_PARTITION_ADDRESS(LOADED_FW_SECONDARY_SLOT)); + loaded_fw_nvm_size = (size_t)(FIXED_PARTITION_SIZE(LOADED_FW_SECONDARY_SLOT)); + } + + /* Copy firmware from MRAM to TCM */ + memcpy(loaded_fw_ram_addr, loaded_fw_nvm_addr, loaded_fw_nvm_size); + + /* Extract reset handler from ARM Cortex-M vector table (entry 1) */ + uint32_t *vector_table = + (uint32_t *)((uint8_t *)loaded_fw_ram_addr + CONFIG_ROM_START_OFFSET); + typedef void reset_handler_t(void); + reset_handler_t *reset_handler = (reset_handler_t *)(vector_table[1]); + + /* Jump to loaded firmware - this never returns */ + reset_handler(); + + /* Should never reach here */ + return -1; +} + +SYS_INIT(load_and_jump_to_firmware, EARLY, 0); + +/** + * @brief Main function - should never be reached + * + * If we reach main(), the firmware load and jump failed. + * This indicates a critical error in the loader. + */ +int main(void) +{ +#ifdef CONFIG_PRINTK + printk("ERROR: Firmware jump failed!\n"); +#endif + while (1) { + /* Hang here if jump fails */ + } + return -1; +} diff --git a/samples/nrf54h20/radio_loader/testcase.yaml b/samples/nrf54h20/radio_loader/testcase.yaml new file mode 100644 index 000000000000..b3583e1fc48a --- /dev/null +++ b/samples/nrf54h20/radio_loader/testcase.yaml @@ -0,0 +1,12 @@ +common: + sysbuild: true + tags: + - ci_build + - ci_samples_nrf54h20 + +tests: + radio_loader.nrf54h20dk_cpurad: + platform_allow: + - nrf54h20dk/nrf54h20/cpurad + integration_platforms: + - nrf54h20dk/nrf54h20/cpurad diff --git a/sysbuild/CMakeLists.txt b/sysbuild/CMakeLists.txt index 37b7c6842d82..b9fef9991106 100644 --- a/sysbuild/CMakeLists.txt +++ b/sysbuild/CMakeLists.txt @@ -1055,6 +1055,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/appcore.cmake) include(${CMAKE_CURRENT_LIST_DIR}/netcore.cmake) include(${CMAKE_CURRENT_LIST_DIR}/flprcore.cmake) include(${CMAKE_CURRENT_LIST_DIR}/pprcore.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/radio_loader.cmake) include(${CMAKE_CURRENT_LIST_DIR}/secureboot.cmake) include(${CMAKE_CURRENT_LIST_DIR}/mcuboot.cmake) include(${CMAKE_CURRENT_LIST_DIR}/firmware_loader_radio.cmake) diff --git a/sysbuild/Kconfig.mcuboot b/sysbuild/Kconfig.mcuboot index 896d37065064..5e603a916600 100644 --- a/sysbuild/Kconfig.mcuboot +++ b/sysbuild/Kconfig.mcuboot @@ -135,6 +135,7 @@ config MCUBOOT_MIN_UPDATEABLE_IMAGES config MCUBOOT_MIN_ADDITIONAL_UPDATEABLE_IMAGES int default 1 if SECURE_BOOT_APPCORE + default 1 if NRF_RADIO_LOADER && !MCUBOOT_SIGN_MERGED_BINARY default 0 config MCUBOOT_UPDATEABLE_IMAGES diff --git a/sysbuild/Kconfig.radio_loader b/sysbuild/Kconfig.radio_loader new file mode 100644 index 000000000000..fccf0dc78885 --- /dev/null +++ b/sysbuild/Kconfig.radio_loader @@ -0,0 +1,30 @@ +# +# Copyright (c) 2025 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +config NRF_RADIO_LOADER + bool "Radio Core Firmware Loader [EXPERIMENTAL]" + depends on SOC_NRF54H20 + select EXPERIMENTAL + help + Enable the radio loader that copies firmware from MRAM to TCM + (Tightly Coupled Memory) at boot time. + + The loader runs from MRAM and: + - Copies firmware from MRAM partition to TCM + - Jumps to the loaded firmware in TCM for optimal performance + + Requires devicetree memory map configuration with partitions + and chosen nodes defined in the project's overlay files. + +if NRF_RADIO_LOADER + +config NRF_RADIO_LOADER_BOARD + string + default "$(BOARD)/nrf54h20/cpurad" + help + Target board for the radio loader application. + +endif # NRF_RADIO_LOADER diff --git a/sysbuild/Kconfig.sysbuild b/sysbuild/Kconfig.sysbuild index cd1893bb275a..f7f2a8ef667a 100644 --- a/sysbuild/Kconfig.sysbuild +++ b/sysbuild/Kconfig.sysbuild @@ -81,6 +81,7 @@ rsource "Kconfig.appcore" rsource "Kconfig.flprcore" rsource "Kconfig.netcore" rsource "Kconfig.pprcore" +rsource "Kconfig.radio_loader" rsource "Kconfig.secureboot" rsource "Kconfig.mcuboot" rsource "Kconfig.dfu" diff --git a/sysbuild/radio_loader.cmake b/sysbuild/radio_loader.cmake new file mode 100644 index 000000000000..7c119a22171c --- /dev/null +++ b/sysbuild/radio_loader.cmake @@ -0,0 +1,27 @@ +# +# Copyright (c) 2025 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# Radio Loader sysbuild integration +# This file handles automatic integration of the radio_loader application + +if(SB_CONFIG_NRF_RADIO_LOADER) + # Add radio_loader as an external Zephyr project + ExternalZephyrProject_Add( + APPLICATION radio_loader + SOURCE_DIR "${ZEPHYR_NRF_MODULE_DIR}/samples/nrf54h20/radio_loader" + BOARD ${SB_CONFIG_NRF_RADIO_LOADER_BOARD} + BOARD_REVISION ${BOARD_REVISION} + ) + + set_target_properties(radio_loader PROPERTIES + IMAGE_CONF_SCRIPT ${ZEPHYR_BASE}/share/sysbuild/image_configurations/MAIN_image_default.cmake + ) + + UpdateableImage_Add(APPLICATION radio_loader) + # Note: Memory map configuration should be provided by the user project + # at the project level in sysbuild directory. + # This overlay should define partitions and nodelabels for the loader +endif() From 0b3140a81c8beb93efa298edd5f1afedea6fff50 Mon Sep 17 00:00:00 2001 From: Jan Zyczkowski Date: Mon, 24 Nov 2025 08:28:09 +0100 Subject: [PATCH 112/155] sysbuild: Adapt build system to support nRF54H radio code reloc to TCM Adapt the build system to support the nRF54H radio code relocation from NVM to TCM RAM using the CONFIG_XIP=n option. The CMake script of the variant image (secondary slot image for images compatible with MCUboot direct-xip mode) needs to be modified to properly pass correct addresses to the CONFIG_BUILD_OUTPUT_ADJUST_LMA Kconfig option. It is a workaround and needs to be aligned in the future. JIRA: NCSDK-36461 Signed-off-by: Jan Zyczkowski Co-authored-by: Mateusz Kapala --- cmake/modules/kconfig.cmake | 18 ++++++++++++++++++ soc/nordic/nrf54h/Kconfig.defconfig | 10 ++++++++++ .../nrf54h/Kconfig.defconfig.nrf54h20_cpurad | 16 ++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 soc/nordic/nrf54h/Kconfig.defconfig create mode 100644 soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad diff --git a/cmake/modules/kconfig.cmake b/cmake/modules/kconfig.cmake index b84cef0a9fcd..7235878c0ac1 100644 --- a/cmake/modules/kconfig.cmake +++ b/cmake/modules/kconfig.cmake @@ -39,6 +39,16 @@ if(CONFIG_NCS_IS_VARIANT_IMAGE) file(STRINGS ${preload_autoconf_h} autoconf_content) file(STRINGS ${preload_dotconfig} dotconfig_content) + # Needed for the correct CONFIG_BUILD_OUTPUT_ADJUST_LMA calculation in the variant image + # .config and autoconf.h files for nRF54H20 CPURAD. + dt_partition_addr(code_partition_abs_addr PATH "${code_partition}" REQUIRED ABSOLUTE) + dt_chosen(sram_property PROPERTY "zephyr,sram") + dt_reg_addr(sram_addr PATH "${sram_property}" REQUIRED) + set(soc_nrf54h20_cpurad 0) + if("${dotconfig_content}" MATCHES "CONFIG_SOC_NRF54H20_CPURAD=y") + set(soc_nrf54h20_cpurad 1) + endif() + # Modify the CONFIG_FLASH_LOAD_OFFSET and CONFIG_FLASH_LOAD_SIZE for both the .config and autoconf.h files. # If partition manager is not used, these values should be taken from the device tree. # Additionally, convert primary slot dependencies to secondary slot dependencies. @@ -56,6 +66,10 @@ if(CONFIG_NCS_IS_VARIANT_IMAGE) string(REGEX REPLACE "primary" "secondary" line ${line}) endif() + if(soc_nrf54h20_cpurad AND "${line}" MATCHES "^CONFIG_BUILD_OUTPUT_ADJUST_LMA=.*$") + string(REGEX REPLACE "CONFIG_BUILD_OUTPUT_ADJUST_LMA=(.*)" "CONFIG_BUILD_OUTPUT_ADJUST_LMA=\"${code_partition_abs_addr}-${sram_addr}\"" line ${line}) + endif() + list(APPEND dotconfig_variant_content "${line}\n") endforeach() @@ -73,6 +87,10 @@ if(CONFIG_NCS_IS_VARIANT_IMAGE) string(REGEX REPLACE "primary" "secondary" line ${line}) endif() + if(soc_nrf54h20_cpurad AND "${line}" MATCHES "^#define CONFIG_BUILD_OUTPUT_ADJUST_LMA .*$") + string(REGEX REPLACE "#define CONFIG_BUILD_OUTPUT_ADJUST_LMA (.*)" "#define CONFIG_BUILD_OUTPUT_ADJUST_LMA \"${code_partition_abs_addr}-${sram_addr}\"" line ${line}) + endif() + list(APPEND autoconf_variant_content "${line}\n") endforeach() diff --git a/soc/nordic/nrf54h/Kconfig.defconfig b/soc/nordic/nrf54h/Kconfig.defconfig new file mode 100644 index 000000000000..f116209dec67 --- /dev/null +++ b/soc/nordic/nrf54h/Kconfig.defconfig @@ -0,0 +1,10 @@ +# Nordic Semiconductor nRF54H MCU line + +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if SOC_NRF54H20_CPURAD + +rsource "Kconfig.defconfig.nrf54h20_cpurad" + +endif # SOC_NRF54H20_CPURAD diff --git a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad new file mode 100644 index 000000000000..c3608609326d --- /dev/null +++ b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad @@ -0,0 +1,16 @@ +# Nordic Semiconductor nRF54H20 Radio MCU + +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +if SOC_NRF54H20_CPURAD + +DT_CHOSEN_Z_CODE = zephyr,code-partition +DT_CHOSEN_Z_SRAM = zephyr,sram + +config BUILD_OUTPUT_ADJUST_LMA + depends on !XIP + default "$(dt_chosen_partition_addr_hex,$(DT_CHOSEN_Z_CODE)) - \ + $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_SRAM))" + +endif # SOC_NRF54H20_CPURAD From 78d196a261de521b312820fb316a61a12c380e76 Mon Sep 17 00:00:00 2001 From: Jan Zyczkowski Date: Mon, 24 Nov 2025 08:30:00 +0100 Subject: [PATCH 113/155] samples: idle_relocated_tcm: Add demo sample for nRF54H TCM radio loader Introduce a new sample demonstrating a multicore idle test with firmware relocated to the radio core's TCM. The test showcases the radio loader pattern, where firmware is loaded from MRAM to TCM at runtime, ensuring efficient execution. JIRA: NCSDK-36461 Signed-off-by: Jan Zyczkowski Co-authored-by: Mateusz Kapala --- CODEOWNERS | 3 + doc/nrf/samples/other.rst | 1 + .../idle_relocated_tcm/CMakeLists.txt | 19 ++ .../idle_relocated_tcm/Kconfig.sysbuild | 23 +++ .../nrf54h20/idle_relocated_tcm/README.rst | 185 ++++++++++++++++++ .../nrf54h20/idle_relocated_tcm/app.overlay | 13 ++ .../idle_relocated_tcm/common/memory_map.dtsi | 147 ++++++++++++++ .../common/memory_map_ram_cpurad.dtsi | 13 ++ samples/nrf54h20/idle_relocated_tcm/prj.conf | 12 ++ .../idle_relocated_tcm/remote/CMakeLists.txt | 13 ++ .../idle_relocated_tcm/remote/prj.conf | 9 + .../idle_relocated_tcm/remote/src/main.c | 43 ++++ .../nrf54h20/idle_relocated_tcm/src/main.c | 29 +++ .../nrf54h20/idle_relocated_tcm/sysbuild.conf | 16 ++ .../sysbuild/mcuboot.overlay | 13 ++ .../sysbuild/radio_loader.overlay | 17 ++ .../sysbuild/remote.overlay | 17 ++ .../nrf54h20/idle_relocated_tcm/testcase.yaml | 20 ++ 18 files changed, 593 insertions(+) create mode 100644 samples/nrf54h20/idle_relocated_tcm/CMakeLists.txt create mode 100644 samples/nrf54h20/idle_relocated_tcm/Kconfig.sysbuild create mode 100644 samples/nrf54h20/idle_relocated_tcm/README.rst create mode 100644 samples/nrf54h20/idle_relocated_tcm/app.overlay create mode 100644 samples/nrf54h20/idle_relocated_tcm/common/memory_map.dtsi create mode 100644 samples/nrf54h20/idle_relocated_tcm/common/memory_map_ram_cpurad.dtsi create mode 100644 samples/nrf54h20/idle_relocated_tcm/prj.conf create mode 100644 samples/nrf54h20/idle_relocated_tcm/remote/CMakeLists.txt create mode 100644 samples/nrf54h20/idle_relocated_tcm/remote/prj.conf create mode 100644 samples/nrf54h20/idle_relocated_tcm/remote/src/main.c create mode 100644 samples/nrf54h20/idle_relocated_tcm/src/main.c create mode 100644 samples/nrf54h20/idle_relocated_tcm/sysbuild.conf create mode 100644 samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot.overlay create mode 100644 samples/nrf54h20/idle_relocated_tcm/sysbuild/radio_loader.overlay create mode 100644 samples/nrf54h20/idle_relocated_tcm/sysbuild/remote.overlay create mode 100644 samples/nrf54h20/idle_relocated_tcm/testcase.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 89ec0934b547..782daddbfcee 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -525,6 +525,8 @@ /samples/nrf5340/empty_app_core/ @nrfconnect/ncs-si-muffin /samples/nrf5340/extxip_smp_svr/ @nrfconnect/ncs-eris /samples/nrf54h20/empty_app_core/ @nrfconnect/ncs-aurora +/samples/nrf54h20/idle_relocated_tcm/ @nrfconnect/ncs-si-muffin +/samples/nrf54h20/radio_loader/ @nrfconnect/ncs-si-muffin /samples/ironside_se/ @nrfconnect/ncs-aurora /samples/nrf_compress/ @nordicjm /samples/nrf_profiler/ @nrfconnect/ncs-si-bluebagel @@ -651,6 +653,7 @@ /samples/net/**/*.rst @nrfconnect/ncs-cia-doc /samples/net/coap_client/*.rst @nrfconnect/ncs-iot-oulu-tampere-doc /samples/nfc/**/*.rst @nrfconnect/ncs-si-muffin-doc +/samples/nrf54h20/idle_relocated_tcm/*.rst @nrfconnect/ncs-si-muffin-doc /samples/nrf5340/empty_app_core/*.rst @nrfconnect/ncs-si-muffin-doc /samples/nrf5340/extxip_smp_svr/*.rst @nrfconnect/ncs-eris-doc /samples/nrf5340/netboot/*.rst @nrfconnect/ncs-eris-doc diff --git a/doc/nrf/samples/other.rst b/doc/nrf/samples/other.rst index 24514ab43182..8feff8f1a4aa 100644 --- a/doc/nrf/samples/other.rst +++ b/doc/nrf/samples/other.rst @@ -26,3 +26,4 @@ This section lists single |NCS| samples for various uses that are not part of ot ../../../samples/zephyr/smp_svr_mini_boot/README ../../../samples/dfu/mcuboot_with_encryption/README ../../../samples/basic/*/README + ../../../samples/nrf54h20/*/README diff --git a/samples/nrf54h20/idle_relocated_tcm/CMakeLists.txt b/samples/nrf54h20/idle_relocated_tcm/CMakeLists.txt new file mode 100644 index 000000000000..163cfe990a2f --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +if(NOT SYSBUILD) + message(FATAL_ERROR + " This is a multi-image application that should be built using sysbuild.\n" + " Add --sysbuild argument to west build command to prepare all the images.") +endif() + +project(idle_relocated_tcm) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/nrf54h20/idle_relocated_tcm/Kconfig.sysbuild b/samples/nrf54h20/idle_relocated_tcm/Kconfig.sysbuild new file mode 100644 index 000000000000..00421a021359 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/Kconfig.sysbuild @@ -0,0 +1,23 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +choice NETCORE + default NETCORE_REMOTE + +config NETCORE_REMOTE + bool "Remote radio" + help + Use remote radio. + +endchoice + +config NETCORE_IMAGE_NAME + default "remote" if NETCORE_REMOTE + +config NETCORE_IMAGE_PATH + default "$(ZEPHYR_NRF_MODULE_DIR)/samples/nrf54h20/idle_relocated_tcm/remote" if NETCORE_REMOTE + +source "share/sysbuild/Kconfig" diff --git a/samples/nrf54h20/idle_relocated_tcm/README.rst b/samples/nrf54h20/idle_relocated_tcm/README.rst new file mode 100644 index 000000000000..ac6129de2971 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/README.rst @@ -0,0 +1,185 @@ +.. _idle_relocated_tcm_sample: + +Multicore idle test with firmware relocated to radio core TCM +############################################################# + +.. contents:: + :local: + :depth: 2 + +The test benchmarks the idle behavior of an application that runs on multiple cores. +It demonstrates a radio loader pattern where the radio core firmware is loaded from MRAM into Tightly Coupled Memory (TCM) at runtime. + +Requirements +************ + +The test supports the following development kit: + +.. table-from-rows:: /includes/sample_board_rows.txt + :header: heading + :rows: nrf54h20dk_nrf54h20_cpuapp + +Overview +******** + +This test demonstrates how to build a multicore idle application with :ref:`configuration_system_overview_sysbuild` using a two-stage boot process for the radio core: + +* Radio Loader - A small bootloader that runs on the radio core, copies firmware from MRAM to TCM, and jumps to it. +* Remote Firmware - The actual application that runs from TCM after being loaded. + +The test automatically relocates the remote firmware binary to the correct MRAM address during build time, ensuring it can be loaded by the radio loader. + +Architecture +============ + +The system uses the memory layout compatible with the MCUboot bootloader. +By default, the system uses the MCUboot in the direct-xip mode in the merged slot configuration (no file suffix used). + +Memory map configuration +======================== + +The memory maps are defined in the :file:`common` directory and are shared between all images to ensure consistency. + +The following changes are included in the project overlay files: + +1. Entire Radio TCM RAM region is used for the remote firmware (:file:`common/memory_map_ram_cpurad.dtsi`). +#. A small part of Global RAM is used for the radio loader for the firmware relocation time (:file:`common/memory_map.dtsi`). +#. The MRAM is partitioned for the MCUboot, application, and radio core images (:file:`common/memory_map.dtsi`). + +Enabling the Radio Loader +************************* + +The radio loader is automatically added to the build when you enable it in sysbuild configuration. + +Set the :kconfig:option:`SB_CONFIG_NRF_RADIO_LOADER` Kconfig option to ``y`` in the :file:`sysbuild.conf` file. +This single configuration option automatically adds the ``radio_loader`` application located in the :file:`nrf/samples/nrf54h20/radio_loader` folder and builds it for the CPURAD core. +No manual ``ExternalZephyrProject_Add()`` is needed in sysbuild. + +You must provide the DTS overlay file for the radio loader that includes the following DTS node labels: + +* ``cpurad_slot0_partition`` - The primary slot of the radio loader code. +* ``cpurad_slot1_partition`` - The secondary slot of the radio loader code. +* ``cpurad_slot2_partition`` - The primary slot of the remote firmware code to be relocated to TCM. +* ``cpurad_slot3_partition`` - The secondary slot of the remote firmware code to be relocated to TCM. +* ``cpurad_ram0`` - The radio core TCM RAM region to be used for the remote firmware. + +Automatic firmware relocation +***************************** + +The remote firmware is linked against the target memory partition (TCM) and must be relocated to match the MRAM partition address where it will be initially stored. +This is automatically done by the :kconfig:option:`CONFIG_BUILD_OUTPUT_ADJUST_LMA` Kconfig option when the devicetree chosen nodes are configured correctly. + +How it works +============ + +Firmware relocation is handled automatically by Zephyr's build system using the :kconfig:option:`CONFIG_BUILD_OUTPUT_ADJUST_LMA` Kconfig option, which is configured in the :file:`nrf/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad` file for all nRF54H20 CPURAD projects. + +The configuration automatically detects if the :kconfig:option:`CONFIG_XIP` is enabled in the remote firmware project. +When this option is enabled, the remote firmware runs directly from the ``zephyr,code-partition`` location and no relocation is needed. +When this option is disabled, the remote firmware will run from the ``zephyr,sram`` location but the image is first stored in the MRAM in the ``zephyr,code-partition`` location. +The build system calculates the LMA adjustment to relocate the firmware from TCM to MRAM. + +Zephyr automatically calculates the Load Memory Address (LMA) adjustment based on the chosen nodes: + +.. code-block:: text + + LMA_adjustment = zephyr,code-partition address - zephyr,sram address + +The build system adjusts the hex file so that the code is loaded from MRAM (``0xe000000`` address space), but runs from TCM (``0x23000000`` address space). + +Configuration of remote radio firmware +====================================== + +To use the radio loader pattern, you must configure the remote radio firmware in the following way: + +* Disable the :kconfig:option:`CONFIG_XIP` option in the remote firmware project. +* Assign the TCM RAM region to the remote firmware code using the ``zephyr,sram`` chosen node. +* Assign the MRAM partition to the remote firmware code using the ``zephyr,code-partition`` chosen node. + +Building and running +******************** + +.. |test path| replace:: :file:`samples/nrf54h20/idle_relocated_tcm` + +.. include:: /includes/build_and_run_test.txt + +Testing +======= + +After programming the test to your development kit, complete the following steps to test it: + +1. |connect_terminal| +#. Reset the kit. +#. Observe the console output for both cores: + + * For the application core, the output should be as follows: + + .. code-block:: console + + *** Booting MCUboot v2.3.0-dev-0d9411f5dda3 *** + *** Using nRF Connect SDK v3.1.99-329079d0237c *** + *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** + I: Starting Direct-XIP bootloader + I: Primary slot: version=0.0.0+0 + I: Image 0 Secondary slot: Image not found + I: Image 0 loaded from the primary slot + I: Bootloader chainload address offset: 0x40000 + I: Image version: v0.0.0 + I: Jumping to the image slot + *** Booting nRF Connect SDK v3.1.99-329079d0237c *** + *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** + [00:00:00.336,735] idle: Multicore idle test on nrf54h20dk@0.9.0/nrf54h20/cpuapp + [00:00:00.336,742] idle: build time: Dec 2 2025 08:52:18 + [00:00:00.336,745] idle: Multicore idle test iteration 0 + [00:00:02.336,834] idle: Multicore idle test iteration 1 + ... + + * For the radio core, the output should be as follows: + + .. code-block:: console + + *** Booting nRF Connect SDK v3.1.99-329079d0237c *** + *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** + [00:00:00.512,002] idle: Multicore idle test on nrf54h20dk@0.9.0/nrf54h20/cpurad + [00:00:00.512,004] idle: Original code partition start address: 0xe094000 + [00:00:00.512,006] idle: Running from the SRAM, start address: 0x23000000, size: 0x30000 + [00:00:00.512,007] idle: Current PC (program counter) address: 0x23000a90 + [00:00:00.512,009] idle: build time: Dec 2 2025 08:52:24 + [00:00:00.512,012] idle: Multicore idle test iteration 0 + [00:00:02.512,072] idle: Multicore idle test iteration 1 + ... + + The radio loader first loads the firmware from MRAM to TCM and then jumps to the loaded firmware. + This process is transparent and happens during the early boot stage. + +#. Verify the DFU process: + + a. Build the firmware for the secondary app slot, increase the version number in the :file:`prj.conf` file (uncomment the line): + + .. code-block:: kconfig + + CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="0.0.1+0" + + #. Build the firmware: + + .. code-block:: console + + west build -p -b nrf54h20dk/nrf54h20/cpuapp + + #. Program the firmware to the secondary application slot: + + .. code-block:: console + + nrfutil device program --firmware build/zephyr_secondary_app.merged.hex --options chip_erase_mode=ERASE_NONE + + #. Reset the development kit. + + .. code-block:: console + + nrfutil device reset + + #. Observe the following changes in the console output: + + * The application core boots from the secondary application slot. + * The radio core boots from the secondary radio slot. + * The build time changes. diff --git a/samples/nrf54h20/idle_relocated_tcm/app.overlay b/samples/nrf54h20/idle_relocated_tcm/app.overlay new file mode 100644 index 000000000000..dc561921d6e8 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/app.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "common/memory_map.dtsi" + +&cpuapp_data { + reg = <0x2f000000 0x39000>; +}; + +secondary_app_partition: &cpuapp_slot1_partition {}; diff --git a/samples/nrf54h20/idle_relocated_tcm/common/memory_map.dtsi b/samples/nrf54h20/idle_relocated_tcm/common/memory_map.dtsi new file mode 100644 index 000000000000..049033626837 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/common/memory_map.dtsi @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + soc { + /* Small piece of Global RAM for the radio loader to use during FW relocation. */ + cpurad_loader_ram: sram@2f039000 { + compatible = "mmio-sram"; + reg = <0x2f039000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x2f039000 0x1000>; + }; + }; +}; + +&mram1x { + /delete-node/ partitions; + + /* Redefine the "partitions" DTS node. */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + cpuapp_boot_partition: boot_partition: partition@30000 { + reg = <0x30000 0x10000>; + label = "mcuboot"; + }; + + /* Image 0, slot 0 (primary slot): merged application and radio core images. */ + slot0_partition: partition@40000 { + reg = <0x40000 DT_SIZE_K(656)>; + }; + + /* Application code for cpuapp core. */ + cpuapp_slot0_partition: partition@40800 { + label = "image-0"; + reg = <0x40800 DT_SIZE_K(326)>; + }; + + /* Radio core firmware loader code for cpurad core. */ + cpurad_slot0_partition: cpurad_loader_partition: partition@92000 { + label = "cpurad_loader_partition"; + reg = <0x92000 DT_SIZE_K(8)>; /* 8 KB allocated (~4 KB actual) */ + }; + + /* Radio core application code initially stored in MRAM that will be loaded to TCM + * by radio loader for cpurad core. + */ + cpurad_slot2_partition: cpurad_loaded_fw: partition@94000 { + label = "cpurad_loaded_fw"; + reg = <0x94000 DT_SIZE_K(192)>; + }; + + /* Remaining space in the slot 0. */ + cpurad_slot0_partition_container: partition@c4000 { + reg = <0xc4000 DT_SIZE_K(128)>; + }; + + cpuppr_code_partition: partition@e4000 { + reg = <0xe4000 DT_SIZE_K(64)>; + }; + + cpuflpr_code_partition: partition@f4000 { + reg = <0xf4000 DT_SIZE_K(48)>; + }; + + /* Image 0, slot 1 (secondary slot): merged application and radio core images. */ + slot1_partition: partition@100000 { + reg = <0x100000 DT_SIZE_K(656)>; + }; + + /* Application code for cpuapp core. */ + cpuapp_slot1_partition: partition@100800 { + reg = <0x100800 DT_SIZE_K(326)>; + }; + + /* Radio core firmware loader code for cpurad core. */ + cpurad_slot1_partition: cpurad_loader_partition_slot1: partition@152000 { + label = "cpurad_loader_partition_slot1"; + reg = <0x152000 DT_SIZE_K(8)>; /* 8 KB allocated (~4 KB actual) */ + }; + + + /* Radio core application code initially stored in MRAM that will be loaded to TCM + * by radio loader for cpurad core. + */ + cpurad_slot3_partition: cpurad_loaded_fw_slot1: partition@154000 { + label = "cpurad_loaded_fw_slot1"; + reg = <0x154000 DT_SIZE_K(192)>; + }; + + /* Remaining space in the slot 1. */ + cpurad_slot1_partition_container: partition@184000 { + reg = <0x184000 DT_SIZE_K(128)>; + }; + + storage_partition: partition@1a4000 { + reg = <0x1a4000 DT_SIZE_K(40)>; + }; + + periphconf_partition: partition@1ae000 { + reg = <0x1ae000 DT_SIZE_K(8)>; + }; + + secondary_partition: partition@1b0000 { + reg = <0x1b0000 DT_SIZE_K(64)>; + }; + + secondary_periphconf_partition: partition@1c0000 { + reg = <0x1c0000 DT_SIZE_K(8)>; + }; + + /* NB: A gap has been left here for future partitions */ + + /* 0x1fd000 was chosen for secure_storage_partition such that + * there is no more space after secure_storage_partition. + */ + secure_storage_partition: partition@1fd000 { + compatible = "fixed-subpartitions"; + reg = <0x1fd000 DT_SIZE_K(12)>; + ranges = <0x0 0x1fd000 0x3000>; + #address-cells = <1>; + #size-cells = <1>; + + cpuapp_crypto_partition: partition@0 { + reg = <0x0 DT_SIZE_K(4)>; + }; + + cpurad_crypto_partition: partition@1000 { + reg = <0x1000 DT_SIZE_K(4)>; + }; + + cpuapp_its_partition: partition@2000 { + reg = <0x2000 DT_SIZE_K(2)>; + }; + + cpurad_its_partition: partition@2800 { + reg = <0x2800 DT_SIZE_K(2)>; + }; + }; + }; +}; diff --git a/samples/nrf54h20/idle_relocated_tcm/common/memory_map_ram_cpurad.dtsi b/samples/nrf54h20/idle_relocated_tcm/common/memory_map_ram_cpurad.dtsi new file mode 100644 index 000000000000..80bce10237d7 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/common/memory_map_ram_cpurad.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Use the whole TCM region for the remote firmware. */ +&cpurad_ram0 { + compatible = "mmio-sram"; + /delete-property/ reg; + reg = <0x23000000 0x30000>; + ranges = <0x0 0x23000000 0x30000>; +}; diff --git a/samples/nrf54h20/idle_relocated_tcm/prj.conf b/samples/nrf54h20/idle_relocated_tcm/prj.conf new file mode 100644 index 000000000000..d8e41511b6f7 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/prj.conf @@ -0,0 +1,12 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_LOG=y + +CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y + +# Set the version number for the firmware to verify dfu process +#CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="0.0.1+0" diff --git a/samples/nrf54h20/idle_relocated_tcm/remote/CMakeLists.txt b/samples/nrf54h20/idle_relocated_tcm/remote/CMakeLists.txt new file mode 100644 index 000000000000..81220c38da13 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/remote/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(idle_relocated_tcm_remote) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/nrf54h20/idle_relocated_tcm/remote/prj.conf b/samples/nrf54h20/idle_relocated_tcm/remote/prj.conf new file mode 100644 index 000000000000..be2e7240bd9b --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/remote/prj.conf @@ -0,0 +1,9 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_LOG=y + +CONFIG_XIP=n diff --git a/samples/nrf54h20/idle_relocated_tcm/remote/src/main.c b/samples/nrf54h20/idle_relocated_tcm/remote/src/main.c new file mode 100644 index 000000000000..c07d05bdc87b --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/remote/src/main.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include + +LOG_MODULE_REGISTER(idle); + +#define CODE_PARTITION_NODE DT_CHOSEN(zephyr_code_partition) +#define CODE_PARTITION_START_ADDR DT_FIXED_PARTITION_ADDR(CODE_PARTITION_NODE) + +#define SRAM_NODE DT_CHOSEN(zephyr_sram) +#define SRAM_START_ADDR DT_REG_ADDR(SRAM_NODE) +#define SRAM_SIZE DT_REG_SIZE(SRAM_NODE) + +int main(void) +{ + unsigned int cnt = 0; + uintptr_t pc; + + __asm__ volatile("adr %0, ." : "=r"(pc)); + LOG_INF("Multicore idle test on %s", CONFIG_BOARD_TARGET); + LOG_INF("Original code partition start address: 0x%lx", + (unsigned long)CODE_PARTITION_START_ADDR); + LOG_INF("Running from the SRAM, start address: 0x%lx, size: 0x%lx", + (unsigned long)SRAM_START_ADDR, (unsigned long)SRAM_SIZE); + LOG_INF("Current PC (program counter) address: 0x%lx", (unsigned long)pc); + + /* Using __TIME__ ensure that a new binary will be built on every + * compile which is convenient when testing firmware upgrade. + */ + LOG_INF("build time: " __DATE__ " " __TIME__); + + while (1) { + LOG_INF("Multicore idle test iteration %u", cnt++); + k_msleep(2000); + } + + return 0; +} diff --git a/samples/nrf54h20/idle_relocated_tcm/src/main.c b/samples/nrf54h20/idle_relocated_tcm/src/main.c new file mode 100644 index 000000000000..7acdf97ffb5d --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/src/main.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include + +LOG_MODULE_REGISTER(idle); + +int main(void) +{ + unsigned int cnt = 0; + + LOG_INF("Multicore idle test on %s", CONFIG_BOARD_TARGET); + + /* Using __TIME__ ensure that a new binary will be built on every + * compile which is convenient when testing firmware upgrade. + */ + LOG_INF("build time: " __DATE__ " " __TIME__); + + while (1) { + LOG_INF("Multicore idle test iteration %u", cnt++); + k_msleep(2000); + } + + return 0; +} diff --git a/samples/nrf54h20/idle_relocated_tcm/sysbuild.conf b/samples/nrf54h20/idle_relocated_tcm/sysbuild.conf new file mode 100644 index 000000000000..0546bdd7dd2f --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/sysbuild.conf @@ -0,0 +1,16 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# This automatically adds the radio_loader application to the build +SB_CONFIG_NRF_RADIO_LOADER=y +SB_CONFIG_NETCORE_REMOTE=y + +SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_MCUBOOT_MODE_DIRECT_XIP=y +SB_CONFIG_BOOT_SIGNATURE_TYPE_ED25519=y +SB_CONFIG_BOOT_SIGNATURE_TYPE_PURE=y +# Reserve space for MCUboot trailer in CPURAD slots +SB_CONFIG_MCUBOOT_IMAGES_ROM_END_OFFSET_AUTO="remote;remote_secondary_app" diff --git a/samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot.overlay b/samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot.overlay new file mode 100644 index 000000000000..844690c2f623 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "../common/memory_map.dtsi" + +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/samples/nrf54h20/idle_relocated_tcm/sysbuild/radio_loader.overlay b/samples/nrf54h20/idle_relocated_tcm/sysbuild/radio_loader.overlay new file mode 100644 index 000000000000..94a04c7ec65e --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/sysbuild/radio_loader.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "../common/memory_map.dtsi" +#include "../common/memory_map_ram_cpurad.dtsi" + +/{ + chosen { + zephyr,code-partition = &cpurad_loader_partition; + zephyr,sram = &cpurad_loader_ram; + }; +}; + +secondary_app_partition: &cpurad_loader_partition_slot1 {}; diff --git a/samples/nrf54h20/idle_relocated_tcm/sysbuild/remote.overlay b/samples/nrf54h20/idle_relocated_tcm/sysbuild/remote.overlay new file mode 100644 index 000000000000..1e64044d384c --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/sysbuild/remote.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "../common/memory_map.dtsi" +#include "../common/memory_map_ram_cpurad.dtsi" + +/{ + chosen { + zephyr,code-partition = &cpurad_loaded_fw; + zephyr,sram = &cpurad_ram0; + }; +}; + +secondary_app_partition: &cpurad_loaded_fw_slot1 {}; diff --git a/samples/nrf54h20/idle_relocated_tcm/testcase.yaml b/samples/nrf54h20/idle_relocated_tcm/testcase.yaml new file mode 100644 index 000000000000..1d9f040f9131 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/testcase.yaml @@ -0,0 +1,20 @@ +common: + sysbuild: true + tags: + - ci_build + - ci_samples_nrf54h20 + harness_config: + type: multi_line + ordered: true + regex: + - "Multicore idle test on" + - "Multicore idle test iteration 0" + - "Multicore idle test iteration 1" + +tests: + benchmarks.multicore.idle_relocated_tcm.nrf54h20dk_cpuapp_cpurad.direct_xip.merged_slot: + harness: console + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp From 8c322085d77808fe42f8e8c32554bafebc49fbcf Mon Sep 17 00:00:00 2001 From: Mateusz Kapala Date: Mon, 1 Dec 2025 16:30:47 +0100 Subject: [PATCH 114/155] samples: idle_relocated_tcm: Add split slot configuration Added configurations for the application with MCUboot in the direct-xip mode with split slots (each image has their slots independent from other images). Jira: NCSDK-36461 Signed-off-by: Mateusz Kapala Co-authored-by: Jan Zyczkowski --- .../nrf54h20/idle_relocated_tcm/README.rst | 174 +++++++++++++----- .../idle_relocated_tcm/app_split_slot.overlay | 13 ++ .../common/memory_map_ram_pm_cpurad.dtsi | 26 +++ .../common/memory_map_split_slot.dtsi | 135 ++++++++++++++ .../sysbuild/mcuboot_split_slot.conf | 8 + .../sysbuild/mcuboot_split_slot.overlay | 13 ++ .../sysbuild/radio_loader_split_slot.overlay | 17 ++ .../sysbuild/remote_split_slot.overlay | 18 ++ .../sysbuild_split_slot.conf | 20 ++ .../nrf54h20/idle_relocated_tcm/testcase.yaml | 8 + 10 files changed, 389 insertions(+), 43 deletions(-) create mode 100644 samples/nrf54h20/idle_relocated_tcm/app_split_slot.overlay create mode 100644 samples/nrf54h20/idle_relocated_tcm/common/memory_map_ram_pm_cpurad.dtsi create mode 100644 samples/nrf54h20/idle_relocated_tcm/common/memory_map_split_slot.dtsi create mode 100644 samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot_split_slot.conf create mode 100644 samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot_split_slot.overlay create mode 100644 samples/nrf54h20/idle_relocated_tcm/sysbuild/radio_loader_split_slot.overlay create mode 100644 samples/nrf54h20/idle_relocated_tcm/sysbuild/remote_split_slot.overlay create mode 100644 samples/nrf54h20/idle_relocated_tcm/sysbuild_split_slot.conf diff --git a/samples/nrf54h20/idle_relocated_tcm/README.rst b/samples/nrf54h20/idle_relocated_tcm/README.rst index ac6129de2971..6a4197d0b2ce 100644 --- a/samples/nrf54h20/idle_relocated_tcm/README.rst +++ b/samples/nrf54h20/idle_relocated_tcm/README.rst @@ -34,6 +34,7 @@ Architecture The system uses the memory layout compatible with the MCUboot bootloader. By default, the system uses the MCUboot in the direct-xip mode in the merged slot configuration (no file suffix used). +To configure the system to use the MCUboot in the direct-xip mode in the split slot configuration, build the test with the ``split_slot`` file suffix. Memory map configuration ======================== @@ -42,9 +43,20 @@ The memory maps are defined in the :file:`common` directory and are shared betwe The following changes are included in the project overlay files: -1. Entire Radio TCM RAM region is used for the remote firmware (:file:`common/memory_map_ram_cpurad.dtsi`). -#. A small part of Global RAM is used for the radio loader for the firmware relocation time (:file:`common/memory_map.dtsi`). -#. The MRAM is partitioned for the MCUboot, application, and radio core images (:file:`common/memory_map.dtsi`). +.. tabs:: + + .. group-tab:: Merged slot configuration + + 1. Entire Radio TCM RAM region is used for the remote firmware (:file:`common/memory_map_ram_cpurad.dtsi`). + #. A small part of Global RAM is used for the radio loader for the firmware relocation time (:file:`common/memory_map.dtsi`). + #. The MRAM is partitioned for the MCUboot, application, and radio core images (:file:`common/memory_map.dtsi`). + + .. group-tab:: Split slot configuration + + 1. Entire Radio TCM RAM region is used for the remote firmware (:file:`common/memory_map_ram_cpurad.dtsi`). + #. A small part of Global RAM is used for the radio loader for the firmware relocation time (:file:`common/memory_map_split_slot.dtsi`). + #. The MRAM is partitioned for the MCUboot, application, and radio core images (:file:`common/memory_map_split_slot.dtsi`). + #. The ``pm_ramfunc`` DTS node is relocated to the end of the RAM block but before the MCUboot trailer (:file:`common/memory_map_ram_pm_cpurad.dtsi`) to make the image link properly. Enabling the Radio Loader ************************* @@ -112,42 +124,96 @@ After programming the test to your development kit, complete the following steps #. Reset the kit. #. Observe the console output for both cores: - * For the application core, the output should be as follows: - - .. code-block:: console - - *** Booting MCUboot v2.3.0-dev-0d9411f5dda3 *** - *** Using nRF Connect SDK v3.1.99-329079d0237c *** - *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** - I: Starting Direct-XIP bootloader - I: Primary slot: version=0.0.0+0 - I: Image 0 Secondary slot: Image not found - I: Image 0 loaded from the primary slot - I: Bootloader chainload address offset: 0x40000 - I: Image version: v0.0.0 - I: Jumping to the image slot - *** Booting nRF Connect SDK v3.1.99-329079d0237c *** - *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** - [00:00:00.336,735] idle: Multicore idle test on nrf54h20dk@0.9.0/nrf54h20/cpuapp - [00:00:00.336,742] idle: build time: Dec 2 2025 08:52:18 - [00:00:00.336,745] idle: Multicore idle test iteration 0 - [00:00:02.336,834] idle: Multicore idle test iteration 1 - ... - - * For the radio core, the output should be as follows: - - .. code-block:: console - - *** Booting nRF Connect SDK v3.1.99-329079d0237c *** - *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** - [00:00:00.512,002] idle: Multicore idle test on nrf54h20dk@0.9.0/nrf54h20/cpurad - [00:00:00.512,004] idle: Original code partition start address: 0xe094000 - [00:00:00.512,006] idle: Running from the SRAM, start address: 0x23000000, size: 0x30000 - [00:00:00.512,007] idle: Current PC (program counter) address: 0x23000a90 - [00:00:00.512,009] idle: build time: Dec 2 2025 08:52:24 - [00:00:00.512,012] idle: Multicore idle test iteration 0 - [00:00:02.512,072] idle: Multicore idle test iteration 1 - ... + .. tabs:: + + .. group-tab:: Merged slot configuration + + * For the application core, the output should be as follows: + + .. code-block:: console + + *** Booting MCUboot v2.3.0-dev-0d9411f5dda3 *** + *** Using nRF Connect SDK v3.1.99-329079d0237c *** + *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** + I: Starting Direct-XIP bootloader + I: Primary slot: version=0.0.0+0 + I: Image 0 Secondary slot: Image not found + I: Image 0 loaded from the primary slot + I: Bootloader chainload address offset: 0x40000 + I: Image version: v0.0.0 + I: Jumping to the image slot + *** Booting nRF Connect SDK v3.1.99-329079d0237c *** + *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** + [00:00:00.336,735] idle: Multicore idle test on nrf54h20dk@0.9.0/nrf54h20/cpuapp + [00:00:00.336,742] idle: build time: Dec 2 2025 08:52:18 + [00:00:00.336,745] idle: Multicore idle test iteration 0 + [00:00:02.336,834] idle: Multicore idle test iteration 1 + ... + + * For the radio core, the output should be as follows: + + .. code-block:: console + + *** Booting nRF Connect SDK v3.1.99-329079d0237c *** + *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** + [00:00:00.512,002] idle: Multicore idle test on nrf54h20dk@0.9.0/nrf54h20/cpurad + [00:00:00.512,004] idle: Original code partition start address: 0xe094000 + [00:00:00.512,006] idle: Running from the SRAM, start address: 0x23000000, size: 0x30000 + [00:00:00.512,007] idle: Current PC (program counter) address: 0x23000a90 + [00:00:00.512,009] idle: build time: Dec 2 2025 08:52:24 + [00:00:00.512,012] idle: Multicore idle test iteration 0 + [00:00:02.512,072] idle: Multicore idle test iteration 1 + ... + + .. group-tab:: Split slot configuration + + * For the application core, the output should be as follows: + + .. code-block:: console + + *** Booting MCUboot v2.3.0-dev-0d9411f5dda3 *** + *** Using nRF Connect SDK v3.1.99-b9ff3eff5eb7 *** + *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** + I: Starting Direct-XIP bootloader + I: Primary slot: version=0.0.0+0 + I: Image 0 Secondary slot: Image not found + I: Primary slot: version=0.0.0+0 + I: Image 1 Secondary slot: Image not found + I: Primary slot: version=0.0.0+0 + I: Image 2 Secondary slot: Image not found + I: Loading image 0 from slot 0 + I: bootutil_img_validate: slot 0 manifest verified + I: Try to validate images using manifest in slot 0 + I: Loading image 1 from slot 0 + I: Loading image 2 from slot 0 + I: Image 0 loaded from the primary slot + I: Image 1 loaded from the primary slot + I: Image 2 loaded from the primary slot + I: Bootloader chainload address offset: 0x40000 + I: Image version: v0.0.0 + I: Jumping to the image slot + *** Booting nRF Connect SDK v3.1.99-b9ff3eff5eb7 *** + *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** + [00:00:00.116,189] idle: Multicore idle test on nrf54h20dk@0.9.0/nrf54h20/cpuapp + [00:00:00.116,196] idle: build time: Dec 2 2025 09:01:59 + [00:00:00.116,198] idle: Multicore idle test iteration 0 + [00:00:02.116,271] idle: Multicore idle test iteration 1 + ... + + * For the radio core, the output should be as follows: + + .. code-block:: console + + *** Booting nRF Connect SDK v3.1.99-b9ff3eff5eb7 *** + *** Using Zephyr OS v4.2.99-56fbb4f3c7bb *** + [00:00:00.291,381] idle: Multicore idle test on nrf54h20dk@0.9.0/nrf54h20/cpurad + [00:00:00.291,383] idle: Original code partition start address: 0xe096000 + [00:00:00.291,385] idle: Running from the SRAM, start address: 0x23000000, size: 0x30000 + [00:00:00.291,386] idle: Current PC (program counter) address: 0x23001290 + [00:00:00.291,388] idle: build time: Dec 2 2025 09:01:44 + [00:00:00.291,391] idle: Multicore idle test iteration 0 + [00:00:02.291,443] idle: Multicore idle test iteration 1 + ... The radio loader first loads the firmware from MRAM to TCM and then jumps to the loaded firmware. This process is transparent and happens during the early boot stage. @@ -162,15 +228,37 @@ After programming the test to your development kit, complete the following steps #. Build the firmware: - .. code-block:: console + .. tabs:: + + .. group-tab:: Merged slot configuration + + .. code-block:: console + + west build -p -b nrf54h20dk/nrf54h20/cpuapp - west build -p -b nrf54h20dk/nrf54h20/cpuapp + .. group-tab:: Split slot configuration + + .. code-block:: console + + west build -p -b nrf54h20dk/nrf54h20/cpuapp -- -DFILE_SUFFIX=split_slot #. Program the firmware to the secondary application slot: - .. code-block:: console + .. tabs:: + + .. group-tab:: Merged slot configuration + + .. code-block:: console + + nrfutil device program --firmware build/zephyr_secondary_app.merged.hex --options chip_erase_mode=ERASE_NONE + + .. group-tab:: Split slot configuration + + .. code-block:: console - nrfutil device program --firmware build/zephyr_secondary_app.merged.hex --options chip_erase_mode=ERASE_NONE + nrfutil device program --firmware build/mcuboot_secondary_app/zephyr/zephyr.signed.hex --options chip_erase_mode=ERASE_NONE + nrfutil device program --firmware build/radio_loader_secondary_app/zephyr/zephyr.signed.hex --options chip_erase_mode=ERASE_NONE + nrfutil device program --firmware build/remote_rad_secondary_app/zephyr/zephyr.signed.hex --options chip_erase_mode=ERASE_NONE #. Reset the development kit. diff --git a/samples/nrf54h20/idle_relocated_tcm/app_split_slot.overlay b/samples/nrf54h20/idle_relocated_tcm/app_split_slot.overlay new file mode 100644 index 000000000000..8e20296a9d4d --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/app_split_slot.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "common/memory_map_split_slot.dtsi" + +&cpuapp_data { + reg = <0x2f000000 0x39000>; +}; + +secondary_app_partition: &cpuapp_slot1_partition {}; diff --git a/samples/nrf54h20/idle_relocated_tcm/common/memory_map_ram_pm_cpurad.dtsi b/samples/nrf54h20/idle_relocated_tcm/common/memory_map_ram_pm_cpurad.dtsi new file mode 100644 index 000000000000..09e14db3acda --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/common/memory_map_ram_pm_cpurad.dtsi @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Power Management relocates the key functions to TCM under the address + * from the pm_ramfunc DTS node. + * It is done at the zephyr/soc/nordic/nrf54h/CMakeLists.txt file. + * Theoretically it would not be necessary to relocate it if the whole code is in TCM. + * The changes in Zephyr would be required to allow it. + * As a workaround, relocate the pm_ramfunc to the end of the RAM block but before + * the MCUboot trailer. + */ +/delete-node/ &pm_ramfunc; + +/ { + soc { + /* cache control functions - must be executed from RAM */ + pm_ramfunc: cpurad_s2ram@2302df40 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2302df40 192>; + zephyr,memory-region = "PMLocalRamfunc"; + }; + }; +}; diff --git a/samples/nrf54h20/idle_relocated_tcm/common/memory_map_split_slot.dtsi b/samples/nrf54h20/idle_relocated_tcm/common/memory_map_split_slot.dtsi new file mode 100644 index 000000000000..e270df2cc335 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/common/memory_map_split_slot.dtsi @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + soc { + /* Small piece of Global RAM for the radio loader to use during FW relocation. */ + cpurad_loader_ram: sram@2f039000 { + compatible = "mmio-sram"; + reg = <0x2f039000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x2f039000 0x1000>; + }; + }; +}; + +&mram1x { + /delete-node/ partitions; + + /* Redefine the "partitions" DTS node. */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + cpuapp_boot_partition: boot_partition: partition@30000 { + label = "mcuboot"; + reg = <0x30000 0x10000>; + }; + + /* Image 0, slot 0 (primary slot) - Application code for cpuapp core. */ + slot0_partition: cpuapp_slot0_partition: partition@40000 { + reg = <0x40000 DT_SIZE_K(326)>; + }; + + /* Image 2, slot 0 (primary slot) - radio loader code for cpurad core. */ + slot4_partition: cpurad_slot0_partition: cpurad_loader_partition: + partition@92000 { + label = "cpurad_loader_partition"; + reg = <0x92000 DT_SIZE_K(16)>; + /* size: radio loader + 2KB trailer MCUboot + * (imgtool assumes that the swap mode is used always) + */ + }; + + /* Image 1, slot 0 (primary slot) - radio core application code initially stored + * in MRAM that will be loaded to TCM by radio loader for cpurad core. + */ + slot2_partition: cpurad_slot2_partition: cpurad_loaded_fw: partition@96000 { + label = "cpurad_loaded_fw"; + reg = <0x96000 (DT_SIZE_K(192))>; + /* size: application + 192B for s2ram + 2KB trailer MCUboot */ + }; + + cpuppr_code_partition: partition@e4000 { + reg = <0xe4000 DT_SIZE_K(64)>; + }; + + cpuflpr_code_partition: partition@f4000 { + reg = <0xf4000 DT_SIZE_K(48)>; + }; + + /* Image 0, slot 1 (secondary slot) - Application code for cpuapp core. */ + slot1_partition: cpuapp_slot1_partition: partition@100000 { + reg = <0x100000 DT_SIZE_K(326)>; + }; + + /* Image 2, slot 1 (secondary slot) - radio loader code for cpurad core. */ + slot5_partition: cpurad_slot1_partition: cpurad_loader_partition_slot1: + partition@152000 { + label = "cpurad_loader_partition_slot1"; + reg = <0x152000 DT_SIZE_K(16)>; + /* size: radio loader + 2KB trailer MCUboot + * (imgtool assumes that the swap mode is used always) + */ + }; + + /* Image 1, slot 1 (secondary slot) - radio core application code initially stored + * in MRAM that will be loaded to TCM by radio loader for cpurad core. + */ + slot3_partition: cpurad_slot3_partition: cpurad_loaded_fw_slot1: partition@156000 { + label = "cpurad_loaded_fw_slot1"; + reg = <0x156000 (DT_SIZE_K(192))>; + /* size: application + 192B for s2ram + 2KB trailer MCUboot */ + }; + + storage_partition: partition@1a4000 { + reg = <0x1a4000 DT_SIZE_K(40)>; + }; + + periphconf_partition: partition@1ae000 { + reg = <0x1ae000 DT_SIZE_K(8)>; + }; + + secondary_partition: partition@1b0000 { + reg = <0x1b0000 DT_SIZE_K(64)>; + }; + + secondary_periphconf_partition: partition@1c0000 { + reg = <0x1c0000 DT_SIZE_K(8)>; + }; + + /* NB: A gap has been left here for future partitions */ + + /* 0x1fd000 was chosen for secure_storage_partition such that + * there is no more space after secure_storage_partition. + */ + secure_storage_partition: partition@1fd000 { + compatible = "fixed-subpartitions"; + reg = <0x1fd000 DT_SIZE_K(12)>; + ranges = <0x0 0x1fd000 0x3000>; + #address-cells = <1>; + #size-cells = <1>; + + cpuapp_crypto_partition: partition@0 { + reg = <0x0 DT_SIZE_K(4)>; + }; + + cpurad_crypto_partition: partition@1000 { + reg = <0x1000 DT_SIZE_K(4)>; + }; + + cpuapp_its_partition: partition@2000 { + reg = <0x2000 DT_SIZE_K(2)>; + }; + + cpurad_its_partition: partition@2800 { + reg = <0x2800 DT_SIZE_K(2)>; + }; + }; + }; +}; diff --git a/samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot_split_slot.conf b/samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot_split_slot.conf new file mode 100644 index 000000000000..f1caef92309b --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot_split_slot.conf @@ -0,0 +1,8 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_NRF_SECURITY=y +CONFIG_MULTITHREADING=y diff --git a/samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot_split_slot.overlay b/samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot_split_slot.overlay new file mode 100644 index 000000000000..096d587025eb --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/sysbuild/mcuboot_split_slot.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "../common/memory_map_split_slot.dtsi" + +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/samples/nrf54h20/idle_relocated_tcm/sysbuild/radio_loader_split_slot.overlay b/samples/nrf54h20/idle_relocated_tcm/sysbuild/radio_loader_split_slot.overlay new file mode 100644 index 000000000000..028f915a2c12 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/sysbuild/radio_loader_split_slot.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "../common/memory_map_split_slot.dtsi" +#include "../common/memory_map_ram_cpurad.dtsi" + +/{ + chosen { + zephyr,code-partition = &cpurad_loader_partition; + zephyr,sram = &cpurad_loader_ram; + }; +}; + +secondary_app_partition: &cpurad_loader_partition_slot1 {}; diff --git a/samples/nrf54h20/idle_relocated_tcm/sysbuild/remote_split_slot.overlay b/samples/nrf54h20/idle_relocated_tcm/sysbuild/remote_split_slot.overlay new file mode 100644 index 000000000000..795813aa927e --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/sysbuild/remote_split_slot.overlay @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "../common/memory_map_split_slot.dtsi" +#include "../common/memory_map_ram_cpurad.dtsi" +#include "../common/memory_map_ram_pm_cpurad.dtsi" + +/{ + chosen { + zephyr,code-partition = &cpurad_loaded_fw; + zephyr,sram = &cpurad_ram0; + }; +}; + +secondary_app_partition: &cpurad_loaded_fw_slot1 {}; diff --git a/samples/nrf54h20/idle_relocated_tcm/sysbuild_split_slot.conf b/samples/nrf54h20/idle_relocated_tcm/sysbuild_split_slot.conf new file mode 100644 index 000000000000..327ab856e235 --- /dev/null +++ b/samples/nrf54h20/idle_relocated_tcm/sysbuild_split_slot.conf @@ -0,0 +1,20 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# This automatically adds the radio_loader application to the build +SB_CONFIG_NRF_RADIO_LOADER=y +SB_CONFIG_NETCORE_REMOTE=y + +SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_MCUBOOT_MODE_DIRECT_XIP=y +SB_CONFIG_BOOT_SIGNATURE_TYPE_ED25519=y +SB_CONFIG_BOOT_SIGNATURE_TYPE_PURE=y + +# Disable merging of slots -> use separate slots for each image +SB_CONFIG_MCUBOOT_SIGN_MERGED_BINARY=n + +# Enable manifest-based updates +SB_CONFIG_MCUBOOT_MANIFEST_UPDATES=y diff --git a/samples/nrf54h20/idle_relocated_tcm/testcase.yaml b/samples/nrf54h20/idle_relocated_tcm/testcase.yaml index 1d9f040f9131..76d90466f7c5 100644 --- a/samples/nrf54h20/idle_relocated_tcm/testcase.yaml +++ b/samples/nrf54h20/idle_relocated_tcm/testcase.yaml @@ -18,3 +18,11 @@ tests: - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf54h20dk/nrf54h20/cpuapp + benchmarks.multicore.idle_relocated_tcm.nrf54h20dk_cpuapp_cpurad.direct_xip.split_slot: + harness: console + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + - FILE_SUFFIX=split_slot From c4da5bd00a678f9ef1301274a7ffeaff3e8e0ddb Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Mon, 1 Dec 2025 10:47:31 +0000 Subject: [PATCH 115/155] manifest: Update sdk-find-my revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-find-my/pull/353 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index a3e6ccb95397..8d5422c03eeb 100644 --- a/west.yml +++ b/west.yml @@ -195,7 +195,7 @@ manifest: compare-by-default: false - name: find-my repo-path: sdk-find-my - revision: 8df233300dcf02bb8737ba8d0360abbf2c9002e5 + revision: bc92a28d63c9c4ce2d0401221d28dfb6a653eed6 groups: - find-my - name: azure-sdk-for-c From a36df2d8d46c9f96da6db71fb014fb24f9c9c882 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Wed, 3 Dec 2025 09:49:44 +0000 Subject: [PATCH 116/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3586 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 8d5422c03eeb..813099b0e928 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: 0a6b10d81b424c927ab76fe2e5d3a7bccb4359ad + revision: 8c2f434f8e6788e542283f98d9f175140f2017a5 import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From eecf8aa62328b13addca0101058ce6e90945803d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Audun=20Kvamtr=C3=B8?= Date: Mon, 24 Nov 2025 08:54:05 +0100 Subject: [PATCH 117/155] CRACEN: Fix PBKDF2 password length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -This fixes an issue on certain ranges of password input where the KDF would generate a wrong value during the KDF. The issue was caused by the using hash length instead of hash block length for the prf output length. -The following table show the affected ranges (all inclusive) for passwords that would cause invalid generated key output: -SHA-1: 21-64 characters long password -SHA-224: 29-64 characters long password -SHA-256: 29-64 characters long password -SHA-384: 49-12 characters long password -SHA-512: 65-128 characters long password -Adding new API pbkdf2_prf_block_length which is used for password input. This API addition prevents usage of the existing API pbkdf2_prf_output_length which reported a too small value causing the aforementioned issues. ref: NCSDK-35975 Signed-off-by: Frank Audun Kvamtrø --- .../drivers/cracen/cracenpsa/src/key_derivation.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_derivation.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_derivation.c index ef7fa73d9d4c..0e2839bfe80a 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_derivation.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_derivation.c @@ -193,6 +193,15 @@ static psa_status_t start_mac_operation(cracen_key_derivation_operation_t *opera #endif #if defined(PSA_NEED_CRACEN_PBKDF2_HMAC) +static size_t pbkdf2_prf_block_length(psa_algorithm_t alg) +{ + if (alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { + return SX_BLKCIPHER_AES_BLK_SZ; + } else { + return PSA_HASH_BLOCK_LENGTH(PSA_ALG_GET_HASH(alg)); + } +} + static size_t pbkdf2_prf_output_length(psa_algorithm_t alg) { if (alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { @@ -439,15 +448,15 @@ cracen_key_derivation_input_bytes_pbkdf2(cracen_key_derivation_operation_t *oper return PSA_ERROR_BAD_STATE; } - size_t output_length = pbkdf2_prf_output_length(operation->alg); + size_t block_length = pbkdf2_prf_block_length(operation->alg); bool aes_cmac_prf = operation->alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128; - if (aes_cmac_prf && data_length != output_length) { + if (aes_cmac_prf && data_length != block_length) { /* Password must be 128-bit (AES Key size) */ return PSA_ERROR_INVALID_ARGUMENT; } - if (data_length > output_length) { + if (data_length > block_length) { size_t hash_length = 0; /* Password needs to be hashed. */ psa_status_t status = cracen_hash_compute( From e8e4586d7d56db386f6f2fa83835317a3e4faf44 Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Wed, 3 Dec 2025 22:50:56 +0100 Subject: [PATCH 118/155] manifest: bump memfault to 1.32 This brings (among others) a fix for the compilation on nRF53 after the recent nrfx update. Signed-off-by: Damian Krolik --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 813099b0e928..9c06c2c31b7f 100644 --- a/west.yml +++ b/west.yml @@ -244,7 +244,7 @@ manifest: remote: throwtheswitch - name: memfault-firmware-sdk path: modules/lib/memfault-firmware-sdk - revision: 1.31.0 + revision: 1.32.0 remote: memfault - name: bsim repo-path: bsim_west From 1169ceb9c347150a14b2a6fe5d6ad4f63d5a8394 Mon Sep 17 00:00:00 2001 From: Bartosz Miller Date: Fri, 7 Nov 2025 14:39:13 +0100 Subject: [PATCH 119/155] tests: drivers: pwm: Test PWM events Test the PWM various events. Signed-off-by: Bartosz Miller --- tests/drivers/pwm/pwm_events/CMakeLists.txt | 8 + .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 19 +++ .../boards/nrf54l15dk_nrf54l15_cpuapp.overlay | 17 +++ .../nrf54lm20dk_nrf54lm20a_cpuapp.overlay | 17 +++ .../nrf54ls05dk_nrf54ls05b_cpuapp.overlay | 17 +++ tests/drivers/pwm/pwm_events/prj.conf | 5 + tests/drivers/pwm/pwm_events/src/main.c | 143 ++++++++++++++++++ tests/drivers/pwm/pwm_events/testcase.yaml | 16 ++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 2 +- 9 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 tests/drivers/pwm/pwm_events/CMakeLists.txt create mode 100644 tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay create mode 100644 tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay create mode 100644 tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay create mode 100644 tests/drivers/pwm/pwm_events/prj.conf create mode 100644 tests/drivers/pwm/pwm_events/src/main.c create mode 100644 tests/drivers/pwm/pwm_events/testcase.yaml diff --git a/tests/drivers/pwm/pwm_events/CMakeLists.txt b/tests/drivers/pwm/pwm_events/CMakeLists.txt new file mode 100644 index 000000000000..9f95b160c6fc --- /dev/null +++ b/tests/drivers/pwm/pwm_events/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(pwm_events) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..0f736b52db0a --- /dev/null +++ b/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +dut_pwm: &pwm130 { + status = "okay"; +}; + +tst_timer: &timer131 { + status = "okay"; +}; + +&dppic133 { + owned-channels = <1>; + sink-channels = <1>; + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 000000000000..de54b0bf3f9c --- /dev/null +++ b/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +dut_pwm: &pwm20 { + status = "okay"; +}; + +tst_timer: &timer20 { + status = "okay"; +}; + +&dppic20 { + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 000000000000..de54b0bf3f9c --- /dev/null +++ b/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +dut_pwm: &pwm20 { + status = "okay"; +}; + +tst_timer: &timer20 { + status = "okay"; +}; + +&dppic20 { + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay new file mode 100644 index 000000000000..de54b0bf3f9c --- /dev/null +++ b/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +dut_pwm: &pwm20 { + status = "okay"; +}; + +tst_timer: &timer20 { + status = "okay"; +}; + +&dppic20 { + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_events/prj.conf b/tests/drivers/pwm/pwm_events/prj.conf new file mode 100644 index 000000000000..66a4e32479e4 --- /dev/null +++ b/tests/drivers/pwm/pwm_events/prj.conf @@ -0,0 +1,5 @@ +CONFIG_NRFX_PWM=y +CONFIG_NRFX_TIMER=y +CONFIG_NRFX_GPPI=y + +CONFIG_ZTEST=y diff --git a/tests/drivers/pwm/pwm_events/src/main.c b/tests/drivers/pwm/pwm_events/src/main.c new file mode 100644 index 000000000000..05c32dd7aa27 --- /dev/null +++ b/tests/drivers/pwm/pwm_events/src/main.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2025, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include +#include + +#define PWM_OUTPUT_PIN NRF_DT_GPIOS_TO_PSEL(DT_NODELABEL(led2), gpios) + +#define SLEEP_TIME_MS 500 + +struct pwm_events_fixture { + nrfx_pwm_t *pwm; + nrf_pwm_sequence_t *pwm_sequence; + nrfx_timer_t *test_timer; + uint32_t timer_task_address; + uint32_t domain_id; + nrfx_gppi_handle_t gppi_handle; +}; + +static void configure_pwm(nrfx_pwm_t *pwm) +{ + nrfx_pwm_config_t pwm_config = + NRFX_PWM_DEFAULT_CONFIG(PWM_OUTPUT_PIN, NRF_PWM_PIN_NOT_CONNECTED, + NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED); + + pwm_config.count_mode = NRF_PWM_MODE_UP_AND_DOWN; + + zassert_ok(nrfx_pwm_init(pwm, &pwm_config, NULL, NULL), "NRFX PWM init failed\n"); +} + +static uint32_t configure_test_timer(nrfx_timer_t *timer) +{ + uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer->p_reg); + nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency); + + timer_config.bit_width = NRF_TIMER_BIT_WIDTH_16; + timer_config.mode = NRF_TIMER_MODE_COUNTER; + + TC_PRINT("Timer base frequency: %d Hz\n", base_frequency); + + zassert_ok(nrfx_timer_init(timer, &timer_config, NULL), "Timer init failed\n"); + nrfx_timer_enable(timer); + + return nrfx_timer_task_address_get(timer, NRF_TIMER_TASK_COUNT); +} + +static void setup_dppi_connection(nrfx_gppi_handle_t *gppi_handle, uint32_t domain_id, + uint32_t timer_task_address, uint32_t pwm_event_address) +{ + zassert_ok(nrfx_gppi_conn_alloc(pwm_event_address, timer_task_address, gppi_handle), + "Failed to allocate DPPI connection\n"); + nrfx_gppi_conn_enable(*gppi_handle); +} + +static void clear_dppi_connection(nrfx_gppi_handle_t *gppi_handle, uint32_t domain_id, + uint32_t timer_task_address, uint32_t pwm_event_address) +{ + nrfx_gppi_conn_disable(*gppi_handle); + nrfx_gppi_conn_free(pwm_event_address, timer_task_address, *gppi_handle); +} + +static void run_pwm_event_test_case(struct pwm_events_fixture *fixture, + nrf_pwm_event_t tested_pwm_event, + uint32_t expected_triggers_count, char *event_name) +{ + uint32_t pwm_event_address; + uint32_t timer_cc_before, timer_cc_after; + + pwm_event_address = nrf_pwm_event_address_get(fixture->pwm->p_reg, tested_pwm_event); + setup_dppi_connection(&fixture->gppi_handle, fixture->domain_id, + fixture->timer_task_address, pwm_event_address); + + nrf_pwm_event_clear(fixture->pwm->p_reg, tested_pwm_event); + timer_cc_before = nrfx_timer_capture(fixture->test_timer, NRF_TIMER_CC_CHANNEL0); + nrfx_pwm_simple_playback(fixture->pwm, fixture->pwm_sequence, 1, NRFX_PWM_FLAG_STOP); + k_msleep(SLEEP_TIME_MS); + timer_cc_after = nrfx_timer_capture(fixture->test_timer, NRF_TIMER_CC_CHANNEL0); + + TC_PRINT("PWM %s events count: %d\n", event_name, timer_cc_after - timer_cc_before); + zassert_equal(timer_cc_after - timer_cc_before, expected_triggers_count, + "PWM %s event triggered count != %u\n", event_name, expected_triggers_count); + + nrf_pwm_event_clear(fixture->pwm->p_reg, tested_pwm_event); + clear_dppi_connection(&fixture->gppi_handle, fixture->domain_id, + fixture->timer_task_address, pwm_event_address); +} + +ZTEST_F(pwm_events, test_pwm_stop_event) +{ + run_pwm_event_test_case(fixture, NRF_PWM_EVENT_STOPPED, 1, "STOP"); +} + +ZTEST_F(pwm_events, test_pwm_seqstarted_event) +{ + run_pwm_event_test_case(fixture, NRF_PWM_EVENT_SEQSTARTED1, 1, "SEQSTARTED1"); +} + +ZTEST_F(pwm_events, test_pwm_seqend_event) +{ + run_pwm_event_test_case(fixture, NRF_PWM_EVENT_SEQEND1, 1, "SEQEND1"); +} + +ZTEST_F(pwm_events, test_pwm_periodend_event) +{ + run_pwm_event_test_case(fixture, NRF_PWM_EVENT_PWMPERIODEND, fixture->pwm_sequence->length, + "PWMPERIODEND"); +} + +ZTEST_F(pwm_events, test_pwm_loopsdone_event) +{ + run_pwm_event_test_case(fixture, NRF_PWM_EVENT_LOOPSDONE, 1, "LOOPSDONE"); +} + +static void *test_setup(void) +{ + static struct pwm_events_fixture fixture; + static nrfx_timer_t test_timer = NRFX_TIMER_INSTANCE(DT_REG_ADDR(DT_NODELABEL(tst_timer))); + static nrfx_pwm_t pwm = NRFX_PWM_INSTANCE(DT_REG_ADDR(DT_NODELABEL(dut_pwm))); + static nrf_pwm_values_common_t pwm_duty_cycle_values[] = {0x500, 0x600}; + static nrf_pwm_sequence_t pwm_sequence = {.values = {pwm_duty_cycle_values}, + .length = ARRAY_SIZE(pwm_duty_cycle_values), + .repeats = 0, + .end_delay = 0}; + + fixture.pwm = &pwm; + fixture.pwm_sequence = &pwm_sequence; + configure_pwm(&pwm); + + fixture.test_timer = &test_timer; + fixture.timer_task_address = configure_test_timer(&test_timer); + + fixture.domain_id = nrfx_gppi_domain_id_get((uint32_t)test_timer.p_reg); + + return &fixture; +} + +ZTEST_SUITE(pwm_events, NULL, test_setup, NULL, NULL, NULL); diff --git a/tests/drivers/pwm/pwm_events/testcase.yaml b/tests/drivers/pwm/pwm_events/testcase.yaml new file mode 100644 index 000000000000..f3d498767ad5 --- /dev/null +++ b/tests/drivers/pwm/pwm_events/testcase.yaml @@ -0,0 +1,16 @@ +common: + tags: + - drivers + - ci_tests_drivers_pwm + harness: ztest + timeout: 20 + +tests: + drivers.pwm.pwm_events: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54ls05dk/nrf54ls05b/cpuapp + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp diff --git a/tests/drivers/spi/spim_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/spi/spim_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 16abf5199ac6..ebf833ee8afc 100644 --- a/tests/drivers/spi/spim_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/spi/spim_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -57,4 +57,4 @@ tst_timer: &timer131 { owned-channels = <1>; sink-channels = <1>; status = "okay"; - }; +}; From 7a0899d305409a0b11124a927aa0e263fb98db1d Mon Sep 17 00:00:00 2001 From: Francesco Domenico Servidio Date: Wed, 3 Dec 2025 10:21:31 +0100 Subject: [PATCH 120/155] doc: Added ISE Counter Service doc Added IronSide SE Counter Service doc. Signed-off-by: Francesco Domenico Servidio --- .../nrf54h/ug_nrf54h20_ironside.rst | 157 ++++++++++++++++-- 1 file changed, 141 insertions(+), 16 deletions(-) diff --git a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst index 7206b1e70a16..824587b9ce12 100644 --- a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst +++ b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst @@ -705,7 +705,7 @@ UICR.SECURESTORAGE :kconfig:option:`CONFIG_GEN_UICR_SECURESTORAGE` enables the secure storage system used by |ISE| for persistent storage of cryptographic keys and trusted data. The secure storage is divided into separate partitions for different services and processor domains. -The total size of all configurations specified in ``UICR.SECURESTORAGE.*`` must be aligned to a 4 KB boundary. +The total size of all configurations specified in UICR.SECURESTORAGE.\* must be aligned to a 4 KB boundary. For more information, see :ref:`ug_nrf54h20_ironside_se_secure_storage`. The UICR.SECURESTORAGE configuration consists of the following sub-registers: @@ -769,10 +769,10 @@ For information on how to configure these UICR settings, see :ref:`ug_nrf54h20_i .. _ug_nrf54h20_ironside_se_boot_report: -IronSide boot report -******************** +|ISE| boot report +***************** -The IronSide boot report contains device state information communicated from |ISE| to the local domains. +The |ISE| boot report contains device state information communicated from |ISE| to the local domains. It is written to a reserved region in RAM20, which is accessible to the local domain in the default system configuration. There is one boot report per processor that is booted, either directly by |ISE| or via the CPUCONF service. @@ -954,7 +954,7 @@ Setting bit 5 in ``CTRLAP.BOOTMODE`` will also trigger secondary firmware. |ISE| automatically triggers the secondary firmware in any of the following situations: * The integrity check of the memory specified in :kconfig:option:`CONFIG_GEN_UICR_PROTECTEDMEM` fails. -* Any boot failure occurs, such as missing primary firmware or failure to apply ``UICR.PERIPHCONF`` configurations. +* Any boot failure occurs, such as missing primary firmware or failure to apply UICR.PERIPHCONF configurations. * If :kconfig:option:`CONFIG_GEN_UICR_SECONDARY_TRIGGER` is enabled, and a UICR-configurable trigger occurs. See the following table for UICR-configurable triggers. @@ -1067,21 +1067,21 @@ To leverage this secure storage functionality, applications must set the key loc The secure storage configuration includes two separate storage regions: -* **UICR.SECURESTORAGE.CRYPTO** - Used for PSA Crypto API operations when storing cryptographic keys -* **UICR.SECURESTORAGE.ITS** - Used for PSA Internal Trusted Storage (ITS) API operations when storing general secure data +* UICR.SECURESTORAGE.CRYPTO - Used for PSA Crypto API operations when storing cryptographic keys +* UICR.SECURESTORAGE.ITS - Used for PSA Internal Trusted Storage (ITS) API operations when storing general secure data Secure Storage through PSA Crypto API ===================================== -When using the PSA Crypto API to operate on keys, the storage region specified by ``UICR.SECURESTORAGE.CRYPTO`` is automatically used if the key attributes are configured with **key location** set to ``PSA_KEY_LOCATION_LOCAL_STORAGE``. +When using the PSA Crypto API to operate on keys, the storage region specified by UICR.SECURESTORAGE.CRYPTO is automatically used if the key attributes are configured with ``key location`` set to ``PSA_KEY_LOCATION_LOCAL_STORAGE``. This ensures that cryptographic keys are stored in the dedicated secure storage region rather than in regular application memory. Secure storage through PSA ITS API ================================== -When using the PSA ITS API for storing general secure data, the storage region specified by ``UICR.SECURESTORAGE.ITS`` is used automatically. +When using the PSA ITS API for storing general secure data, the storage region specified by UICR.SECURESTORAGE.ITS is used automatically. No special configuration is required for PSA ITS operations, as they inherently use the secure storage when available. Security Properties @@ -1092,16 +1092,16 @@ The secure storage provided by |ISE| has the following security characteristics: Access Control -------------- -* **Domain Isolation**: Secure storage regions are not accessible by local domains directly. -* **Ironside Exclusive Access**: Only the Ironside Secure Element can access the secure storage regions. -* **Domain Separation**: Each local domain can only access its own secure storage data, ensuring isolation between different domains. +* *Domain Isolation*: Secure storage regions are not accessible by local domains directly. +* *Ironside Exclusive Access*: Only the |ISE| can access the secure storage regions. +* *Domain Separation*: Each local domain can only access its own secure storage data, ensuring isolation between different domains. Data Protection --------------- -* **Encryption**: All data stored in the secure storage regions is encrypted using device-unique keys. -* **Integrity**: The stored data is protected against tampering through cryptographic integrity checks. -* **Confidentiality**: The encryption ensures that stored data remains confidential even if the storage medium is physically accessed. +* *Encryption*: All data stored in the secure storage regions is encrypted using device-unique keys. +* *Integrity*: The stored data is protected against tampering through cryptographic integrity checks. +* *Confidentiality*: The encryption ensures that stored data remains confidential even if the storage medium is physically accessed. .. note:: The device-unique encryption keys are managed entirely by |ISE| and are not accessible to application code. @@ -1112,7 +1112,7 @@ Configuration Considerations When configuring secure storage, consider the following: -* Ensure sufficient storage space is allocated in both ``UICR.SECURESTORAGE.CRYPTO`` and ``UICR.SECURESTORAGE.ITS`` regions based on your application's requirements +* Ensure sufficient storage space is allocated in both UICR.SECURESTORAGE.CRYPTO and UICR.SECURESTORAGE.ITS regions based on your application's requirements * The sum of these two regions must be 4kB aligned. * The secure storage regions should be properly sized to accommodate the expected number of keys and data items * Access to secure storage is only available when the key location is explicitly set to ``PSA_KEY_LOCATION_LOCAL_STORAGE`` @@ -1292,3 +1292,128 @@ This prevents the CPU from executing any instructions until the CPUWAIT register Use this command to begin debugging at the very first instruction or to program flash memory safely without concurrent CPU access. The ``DEBUGWAIT`` command does not define any command-specific values for the CTRLAP.BOOTSTATUS.CMDERROR field. + +.. _ug_nrf54h20_ironside_se_spu_mramc_feature_configuration: + +|ISE| SPU MRAMC feature configuration +************************************* + +|ISE| configures the SPU.FEATURES.MRAMC registers with default settings for both MRAMC110 and MRAMC111. +Local domains have access to the READY/READYNEXT status registers for monitoring the status of the MRAM controller. +All other MRAMC features (like WAITSTATES and AUTODPOWERDOWN) are managed by |ISE|, with all configurations locked at boot time. + +.. _ug_nrf54h20_ironside_se_counter_service: + +|ISE| Counter service +********************* + +The |ISE| Counter service provides secure monotonic counters for rollback protection, version tracking, and other security-critical applications that require strictly increasing values. + +The header file for this service is :file:`sdk-zephyr/soc/nordic/ironside/include/nrf_ironside/counter.h`. + +It provides four independent 32-bit monotonic counters (``IRONSIDE_COUNTER_0`` through ``IRONSIDE_COUNTER_3``). +Each counter can only be set to a value greater than or equal to its current value, which ensures that counter values never decrease. + +The counters have the following properties: + +.. list-table:: + :header-rows: 1 + + * - Property + - Description + * - Monotonic + - Counter values can only increase or stay the same; they cannot decrease. + * - Persistent + - Counter values are stored in secure storage and survive reboots. + * - Per-boot locking + - Counters can be locked for the current boot session to prevent further modifications. + * - Automatic initialization + - Counters are initialized to 0 during the first boot with an unlocked UICR. + +Operations +========== + +The Counter service provides three primary operations applicable to the counters: ``set``, ``get``, and ``lock``. + +Set +--- + +The ``ironside_counter_set()`` function sets a counter to a specified value. +The new value must be greater than or equal to the current counter value. + +The function takes the following parameters: + +* ``counter_id`` - Counter identifier (``IRONSIDE_COUNTER_0`` through ``IRONSIDE_COUNTER_3``). +* ``value`` - New counter value. + It must be greater than or equal to the current value. + +The function returns the following values: + +* ``0`` on success. +* ``-IRONSIDE_COUNTER_ERROR_INVALID_ID`` if the counter ID is invalid. +* ``-IRONSIDE_COUNTER_ERROR_TOO_LOW`` if the specified value is lower than the current value. +* ``-IRONSIDE_COUNTER_ERROR_LOCKED`` if the counter is locked for this boot session. +* ``-IRONSIDE_COUNTER_ERROR_STORAGE_FAILURE`` if the storage operation failed. + +Get +--- + +The ``ironside_counter_get()`` function retrieves the current value of a counter. + +The function takes the following parameters: + +* ``counter_id`` - Counter identifier (``IRONSIDE_COUNTER_0`` through ``IRONSIDE_COUNTER_3``). +* ``value`` - Pointer to store the retrieved counter value. + +The function returns the following values: + +* ``0`` on success. +* ``-IRONSIDE_COUNTER_ERROR_INVALID_ID`` if the counter ID is invalid. +* ``-IRONSIDE_COUNTER_ERROR_STORAGE_FAILURE`` if the storage operation failed or the counter is not initialized. + +Lock +---- + +The ``ironside_counter_lock()`` function locks a counter for the current boot session, which prevents any further modifications until the next reboot. +Lock states are non-persistent and are cleared on reboot. + +The function takes the following parameter: + +* ``counter_id`` - Counter identifier (``IRONSIDE_COUNTER_0`` through ``IRONSIDE_COUNTER_3``). + +The function returns the following values: + +* ``0`` on success. +* ``-IRONSIDE_COUNTER_ERROR_INVALID_ID`` if the counter ID is invalid. + +Usage +===== + +The Counter service is typically used for the following purposes: + +* *Firmware version tracking* - Store the current firmware version and prevent rollback to older versions. +* *Anti-rollback protection* - Ensure that security-critical updates cannot be reverted. +* *Nonce generation* - Generate unique, strictly increasing values for cryptographic operations. + +The following example demonstrates how to use the Counter service to track firmware versions and prevent rollback: + +.. code-block:: c + + #include + + /* Read the current firmware version counter */ + uint32_t current_version; + int err = ironside_counter_get(IRONSIDE_COUNTER_0, ¤t_version); + if (err != 0) { + /* Handle error */ + } + + /* Update to the new firmware version */ + uint32_t new_version = 42; + err = ironside_counter_set(IRONSIDE_COUNTER_0, new_version); + if (err == -IRONSIDE_COUNTER_ERROR_TOO_LOW) { + /* Firmware rollback detected - reject update */ + } + + /* Lock the counter to prevent tampering during this boot session */ + ironside_counter_lock(IRONSIDE_COUNTER_0); From 3fc4fcf2eb920541ae82313cb9f52466723edf75 Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Tue, 2 Dec 2025 14:34:00 +0100 Subject: [PATCH 121/155] doc: nrf: migration notes: add nrfx 4.0 entry Provide migration notes for nrfx 4.0 in NCS context. Signed-off-by: Marcin Szymczyk --- doc/nrf/links.txt | 2 +- .../migration/migration_guide_3.2.rst | 242 ++++++++++++++++++ 2 files changed, 243 insertions(+), 1 deletion(-) diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index 59dc313fee3b..5083ace8a432 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -124,7 +124,7 @@ .. _`Changelog for nrfx 2.3.0`: https://github.com/NordicSemiconductor/nrfx/blob/master/CHANGELOG.md#user-content-230---2020-08-19 .. _`Changelog for nrfx 2.4.0`: https://github.com/NordicSemiconductor/nrfx/blob/master/CHANGELOG.md#user-content-240---2020-11-13 .. _`Changelog for nrfx 2.5.0`: https://github.com/NordicSemiconductor/nrfx/blob/master/CHANGELOG.md#250---2021-05-05 - +.. _`nrfx 4.0 migration note`: https://github.com/NordicSemiconductor/nrfx/wiki/nrfx-3.14.0-to-4.0.0 .. _`HIDAPI library`: https://github.com/libusb/hidapi .. _`HIDAPI releases`: https://github.com/libusb/hidapi/releases diff --git a/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst b/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst index 78ec6cf64019..7f105a1e2889 100644 --- a/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst +++ b/doc/nrf/releases_and_maturity/migration/migration_guide_3.2.rst @@ -469,3 +469,245 @@ Memfault integration * :kconfig:option:`CONFIG_MEMFAULT_NCS_DEVICE_ID_RUNTIME` - Use a runtime-applied device ID, commonly used when the serial number of the device is written into settings at manufacturing time, for example. * :kconfig:option:`CONFIG_MEMFAULT_NCS_DEVICE_ID_IMEI` (deprecated) - Use the LTE modem IMEI as the device ID. * :kconfig:option:`CONFIG_MEMFAULT_NCS_DEVICE_ID_NET_MAC` (deprecated) - Use the network interface MAC address as the device ID. + +Drivers +======= + +This section provides detailed lists of changes by drivers. + +nrfx +---- + +.. toggle:: + + * nrfx version has been updated to 4.0. + For nrfx changes see `nrfx 4.0 migration note`_. + + Additionally, to migrate a Zephyr build system application that uses nrfx API directly, complete the following steps: + + #. Kconfig options: + + * Replace: + + * Use :kconfig:option:`CONFIG_NRFX_GPPI` instead of the following: + + * ``CONFIG_NRFX_DPPI`` + * ``CONFIG_NRFX_DPPI0`` + * ``CONFIG_NRFX_DPPI00`` + * ``CONFIG_NRFX_DPPI10`` + * ``CONFIG_NRFX_DPPI20`` + * ``CONFIG_NRFX_DPPI30`` + * ``CONFIG_NRFX_DPPI020`` + * ``CONFIG_NRFX_DPPI120`` + * ``CONFIG_NRFX_DPPI130`` + * ``CONFIG_NRFX_DPPI131`` + * ``CONFIG_NRFX_DPPI132`` + * ``CONFIG_NRFX_DPPI133`` + * ``CONFIG_NRFX_DPPI134`` + * ``CONFIG_NRFX_DPPI135`` + * ``CONFIG_NRFX_DPPI136`` + * ``CONFIG_NRFX_PPI`` + + * Use :kconfig:option:`CONFIG_NRFX_I2S` instead of the following: + + * ``CONFIG_NRFX_I2S0`` + * ``CONFIG_NRFX_I2S20`` + + * Use :kconfig:option:`CONFIG_NRFX_PDM` instead of the following: + + * ``CONFIG_NRFX_PDM0`` + * ``CONFIG_NRFX_PDM20`` + * ``CONFIG_NRFX_PDM21`` + + * Use :kconfig:option:`CONFIG_NRFX_PWM` instead of the following: + + * ``CONFIG_NRFX_PWM0`` + * ``CONFIG_NRFX_PWM1`` + * ``CONFIG_NRFX_PWM2`` + * ``CONFIG_NRFX_PWM3`` + * ``CONFIG_NRFX_PWM20`` + * ``CONFIG_NRFX_PWM21`` + * ``CONFIG_NRFX_PWM22`` + * ``CONFIG_NRFX_PWM120`` + * ``CONFIG_NRFX_PWM130`` + * ``CONFIG_NRFX_PWM131`` + * ``CONFIG_NRFX_PWM132`` + * ``CONFIG_NRFX_PWM133`` + + * Use :kconfig:option:`CONFIG_NRFX_QDEC` instead of the following: + + * ``CONFIG_NRFX_QDEC0`` + * ``CONFIG_NRFX_QDEC1`` + * ``CONFIG_NRFX_QDEC20`` + * ``CONFIG_NRFX_QDEC21`` + * ``CONFIG_NRFX_QDEC130`` + * ``CONFIG_NRFX_QDEC131`` + + * Use :kconfig:option:`CONFIG_NRFX_SPIM` instead of the following: + + * ``CONFIG_NRFX_SPIM0`` + * ``CONFIG_NRFX_SPIM1`` + * ``CONFIG_NRFX_SPIM2`` + * ``CONFIG_NRFX_SPIM3`` + * ``CONFIG_NRFX_SPIM4`` + * ``CONFIG_NRFX_SPIM00`` + * ``CONFIG_NRFX_SPIM01`` + * ``CONFIG_NRFX_SPIM20`` + * ``CONFIG_NRFX_SPIM21`` + * ``CONFIG_NRFX_SPIM22`` + * ``CONFIG_NRFX_SPIM23`` + * ``CONFIG_NRFX_SPIM24`` + * ``CONFIG_NRFX_SPIM30`` + * ``CONFIG_NRFX_SPIM120`` + * ``CONFIG_NRFX_SPIM121`` + * ``CONFIG_NRFX_SPIM130`` + * ``CONFIG_NRFX_SPIM131`` + * ``CONFIG_NRFX_SPIM132`` + * ``CONFIG_NRFX_SPIM133`` + * ``CONFIG_NRFX_SPIM134`` + * ``CONFIG_NRFX_SPIM135`` + * ``CONFIG_NRFX_SPIM136`` + * ``CONFIG_NRFX_SPIM137`` + + * Use :kconfig:option:`CONFIG_NRFX_SPIS` instead of the following: + + * ``CONFIG_NRFX_SPIS0`` + * ``CONFIG_NRFX_SPIS1`` + * ``CONFIG_NRFX_SPIS2`` + * ``CONFIG_NRFX_SPIS3`` + * ``CONFIG_NRFX_SPIS00`` + * ``CONFIG_NRFX_SPIS01`` + * ``CONFIG_NRFX_SPIS20`` + * ``CONFIG_NRFX_SPIS21`` + * ``CONFIG_NRFX_SPIS22`` + * ``CONFIG_NRFX_SPIS23`` + * ``CONFIG_NRFX_SPIS24`` + * ``CONFIG_NRFX_SPIS30`` + * ``CONFIG_NRFX_SPIS120`` + * ``CONFIG_NRFX_SPIS130`` + * ``CONFIG_NRFX_SPIS131`` + * ``CONFIG_NRFX_SPIS132`` + * ``CONFIG_NRFX_SPIS133`` + * ``CONFIG_NRFX_SPIS134`` + * ``CONFIG_NRFX_SPIS135`` + * ``CONFIG_NRFX_SPIS136`` + * ``CONFIG_NRFX_SPIS137`` + + * Use :kconfig:option:`CONFIG_NRFX_TIMER` instead of the following: + + * ``CONFIG_NRFX_TIMER0`` + * ``CONFIG_NRFX_TIMER1`` + * ``CONFIG_NRFX_TIMER2`` + * ``CONFIG_NRFX_TIMER3`` + * ``CONFIG_NRFX_TIMER4`` + * ``CONFIG_NRFX_TIMER00`` + * ``CONFIG_NRFX_TIMER10`` + * ``CONFIG_NRFX_TIMER20`` + * ``CONFIG_NRFX_TIMER21`` + * ``CONFIG_NRFX_TIMER22`` + * ``CONFIG_NRFX_TIMER23`` + * ``CONFIG_NRFX_TIMER24`` + * ``CONFIG_NRFX_TIMER020`` + * ``CONFIG_NRFX_TIMER021`` + * ``CONFIG_NRFX_TIMER022`` + * ``CONFIG_NRFX_TIMER120`` + * ``CONFIG_NRFX_TIMER121`` + * ``CONFIG_NRFX_TIMER130`` + * ``CONFIG_NRFX_TIMER131`` + * ``CONFIG_NRFX_TIMER132`` + * ``CONFIG_NRFX_TIMER133`` + * ``CONFIG_NRFX_TIMER134`` + * ``CONFIG_NRFX_TIMER135`` + * ``CONFIG_NRFX_TIMER136`` + * ``CONFIG_NRFX_TIMER137`` + + * Use :kconfig:option:`CONFIG_NRFX_TWIM` instead of the following: + + * ``CONFIG_NRFX_TWIM0`` + * ``CONFIG_NRFX_TWIM1`` + * ``CONFIG_NRFX_TWIM2`` + * ``CONFIG_NRFX_TWIM3`` + * ``CONFIG_NRFX_TWIM20`` + * ``CONFIG_NRFX_TWIM21`` + * ``CONFIG_NRFX_TWIM22`` + * ``CONFIG_NRFX_TWIM23`` + * ``CONFIG_NRFX_TWIM24`` + * ``CONFIG_NRFX_TWIM30`` + * ``CONFIG_NRFX_TWIM120`` + * ``CONFIG_NRFX_TWIM130`` + * ``CONFIG_NRFX_TWIM131`` + * ``CONFIG_NRFX_TWIM132`` + * ``CONFIG_NRFX_TWIM133`` + * ``CONFIG_NRFX_TWIM134`` + * ``CONFIG_NRFX_TWIM135`` + * ``CONFIG_NRFX_TWIM136`` + * ``CONFIG_NRFX_TWIM137`` + + * Use :kconfig:option:`CONFIG_NRFX_TWIS` instead of the following: + + * ``CONFIG_NRFX_TWIS0`` + * ``CONFIG_NRFX_TWIS1`` + * ``CONFIG_NRFX_TWIS2`` + * ``CONFIG_NRFX_TWIS3`` + * ``CONFIG_NRFX_TWIS20`` + * ``CONFIG_NRFX_TWIS21`` + * ``CONFIG_NRFX_TWIS22`` + * ``CONFIG_NRFX_TWIS23`` + * ``CONFIG_NRFX_TWIS24`` + * ``CONFIG_NRFX_TWIS30`` + * ``CONFIG_NRFX_TWIS120`` + * ``CONFIG_NRFX_TWIS130`` + * ``CONFIG_NRFX_TWIS131`` + * ``CONFIG_NRFX_TWIS132`` + * ``CONFIG_NRFX_TWIS133`` + * ``CONFIG_NRFX_TWIS134`` + * ``CONFIG_NRFX_TWIS135`` + * ``CONFIG_NRFX_TWIS136`` + * ``CONFIG_NRFX_TWIS137`` + + * Use :kconfig:option:`CONFIG_NRFX_UARTE` instead of the following: + + * ``CONFIG_NRFX_UARTE0`` + * ``CONFIG_NRFX_UARTE1`` + * ``CONFIG_NRFX_UARTE2`` + * ``CONFIG_NRFX_UARTE3`` + * ``CONFIG_NRFX_UARTE00`` + * ``CONFIG_NRFX_UARTE20`` + * ``CONFIG_NRFX_UARTE21`` + * ``CONFIG_NRFX_UARTE22`` + * ``CONFIG_NRFX_UARTE23`` + * ``CONFIG_NRFX_UARTE24`` + * ``CONFIG_NRFX_UARTE30`` + * ``CONFIG_NRFX_UARTE120`` + * ``CONFIG_NRFX_UARTE130`` + * ``CONFIG_NRFX_UARTE131`` + * ``CONFIG_NRFX_UARTE132`` + * ``CONFIG_NRFX_UARTE133`` + * ``CONFIG_NRFX_UARTE134`` + * ``CONFIG_NRFX_UARTE135`` + * ``CONFIG_NRFX_UARTE136`` + * ``CONFIG_NRFX_UARTE137`` + + * Use :kconfig:option:`CONFIG_NRFX_WDT` instead of the following: + + * ``CONFIG_NRFX_WDT0`` + * ``CONFIG_NRFX_WDT1`` + * ``CONFIG_NRFX_WDT30`` + * ``CONFIG_NRFX_WDT31`` + * ``CONFIG_NRFX_WDT010`` + * ``CONFIG_NRFX_WDT011`` + * ``CONFIG_NRFX_WDT130`` + * ``CONFIG_NRFX_WDT131`` + * ``CONFIG_NRFX_WDT132`` + + * Remove: + + * ``CONFIG_NRFX_PPIB`` + * ``CONFIG_NRFX_PPIB00`` + * ``CONFIG_NRFX_PPIB01`` + * ``CONFIG_NRFX_PPIB10`` + * ``CONFIG_NRFX_PPIB11`` + * ``CONFIG_NRFX_PPIB20`` + * ``CONFIG_NRFX_PPIB21`` + * ``CONFIG_NRFX_PPIB22`` + * ``CONFIG_NRFX_PPIB30`` From 06cb035db2653f4bacc7d25fa6cf6351a7df9e49 Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Wed, 3 Dec 2025 15:26:12 +0100 Subject: [PATCH 122/155] doc: Updated memory requirements for Matter Updated values for memory requirements for Matter. Signed-off-by: Kamil Kasperczyk --- .../getting_started/hw_requirements.rst | 324 +++++++++++------- 1 file changed, 193 insertions(+), 131 deletions(-) diff --git a/doc/nrf/protocols/matter/getting_started/hw_requirements.rst b/doc/nrf/protocols/matter/getting_started/hw_requirements.rst index 1b0db3f8582b..d79fbdd055e1 100644 --- a/doc/nrf/protocols/matter/getting_started/hw_requirements.rst +++ b/doc/nrf/protocols/matter/getting_started/hw_requirements.rst @@ -66,35 +66,47 @@ Values are provided in kilobytes (KB). +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | +============================================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Light Bulb ` (Debug) | 28 | 784 | 4 | 32 | 848 | 168 | + | :ref:`Closure ` (Debug) | 28 | 767 | 4 | 32 | 831 | 173 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Release) | 28 | 629 | 4 | 32 | 693 | 167 | + | :ref:`Closure ` (Release) | 28 | 620 | 4 | 32 | 684 | 170 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Debug) | 28 | 748 | 4 | 32 | 812 | 155 | + | :ref:`Contact Sensor ` (Debug) | 28 | 740 | 4 | 32 | 804 | 161 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Release) | 28 | 589 | 4 | 32 | 653 | 153 | + | :ref:`Contact Sensor ` (Release) | 28 | 589 | 4 | 32 | 653 | 159 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Debug) | 28 | 761 | 4 | 32 | 825 | 158 | + | :ref:`Light Bulb ` (Debug) | 28 | 791 | 4 | 32 | 855 | 173 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Release) | 28 | 591 | 4 | 32 | 655 | 158 | + | :ref:`Light Bulb ` (Release) | 28 | 637 | 4 | 32 | 701 | 171 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Smoke CO Alarm ` (Debug) | 28 | 739 | 4 | 32 | 803 | 156 | + | :ref:`Light Switch ` (Debug) | 28 | 757 | 4 | 32 | 821 | 161 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Smoke CO Alarm ` (Release) | 28 | 584 | 4 | 32 | 648 | 156 | + | :ref:`Light Switch ` (Release) | 28 | 599 | 4 | 32 | 663 | 157 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Debug) | 28 | 700 | 4 | 32 | 764 | 153 | + | :ref:`Lock ` (Debug) | 28 | 770 | 4 | 32 | 834 | 164 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release) | 28 | 556 | 4 | 32 | 620 | 152 | + | :ref:`Lock ` (Release) | 28 | 601 | 4 | 32 | 665 | 161 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Debug) | 28 | 756 | 4 | 32 | 820 | 154 | + | :ref:`Smoke CO Alarm ` (Debug) | 28 | 747 | 4 | 32 | 811 | 162 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Release) | 28 | 590 | 4 | 32 | 654 | 153 | + | :ref:`Smoke CO Alarm ` (Release) | 28 | 592 | 4 | 32 | 656 | 159 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Debug) | 28 | 732 | 4 | 32 | 796 | 153 | + | :ref:`Temperature Sensor ` (Debug) | 28 | 739 | 4 | 32 | 803 | 161 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Release) | 28 | 579 | 4 | 32 | 643 | 153 | + | :ref:`Temperature Sensor ` (Release) | 28 | 589 | 4 | 32 | 653 | 159 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Manufacturer Specific ` (Debug) | 28 | 701 | 4 | 32 | 765 | 149 | + | :ref:`Template ` (Debug) | 28 | 707 | 4 | 32 | 771 | 158 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Release) | 28 | 563 | 4 | 32 | 627 | 155 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Debug) | 28 | 766 | 4 | 32 | 830 | 160 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Release) | 28 | 601 | 4 | 32 | 665 | 157 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Debug) | 28 | 741 | 4 | 32 | 805 | 159 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Release) | 28 | 588 | 4 | 32 | 652 | 157 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Manufacturer Specific ` (Debug) | 28 | 709 | 4 | 32 | 773 | 160 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ .. note:: @@ -107,39 +119,51 @@ Values are provided in kilobytes (KB). +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | +============================================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Bridge ` (Debug) | 32 | 645 | 4 | 32 | 713 | 195 | + | :ref:`Bridge ` (Debug) | 32 | 654 | 4 | 32 | 722 | 197 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Bridge ` (Release) | 32 | 581 | 4 | 32 | 649 | 194 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Closure ` (Debug) | 32 | 696 | 4 | 32 | 764 | 183 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Bridge ` (Release) | 32 | 567 | 4 | 32 | 635 | 193 | + | :ref:`Closure ` (Release) | 32 | 547 | 4 | 32 | 615 | 180 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Debug) | 32 | 709 | 4 | 32 | 777 | 177 | + | :ref:`Contact Sensor ` (Debug) | 32 | 668 | 4 | 32 | 736 | 172 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Release) | 32 | 553 | 4 | 32 | 621 | 176 | + | :ref:`Contact Sensor ` (Release) | 32 | 516 | 4 | 32 | 584 | 169 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Debug) | 32 | 673 | 4 | 32 | 741 | 165 | + | :ref:`Light Bulb ` (Debug) | 32 | 719 | 4 | 32 | 787 | 184 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Release) | 32 | 513 | 4 | 32 | 581 | 163 | + | :ref:`Light Bulb ` (Release) | 32 | 565 | 4 | 32 | 633 | 180 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Debug) | 32 | 686 | 4 | 32 | 754 | 168 | + | :ref:`Light Switch ` (Debug) | 32 | 685 | 4 | 32 | 753 | 172 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Release) | 32 | 515 | 4 | 32 | 583 | 167 | + | :ref:`Light Switch ` (Release) | 32 | 526 | 4 | 32 | 594 | 167 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Smoke CO Alarm ` (Debug) | 32 | 663 | 4 | 32 | 731 | 166 | + | :ref:`Lock ` (Debug) | 32 | 698 | 4 | 32 | 766 | 174 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Smoke CO Alarm ` (Release) | 32 | 508 | 4 | 32 | 576 | 165 | + | :ref:`Lock ` (Release) | 32 | 528 | 4 | 32 | 596 | 171 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Debug) | 32 | 624 | 4 | 32 | 692 | 163 | + | :ref:`Smoke CO Alarm ` (Debug) | 32 | 675 | 4 | 32 | 743 | 172 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release) | 32 | 480 | 4 | 32 | 548 | 161 | + | :ref:`Smoke CO Alarm ` (Release) | 32 | 519 | 4 | 32 | 587 | 169 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Debug) | 32 | 681 | 4 | 32 | 749 | 164 | + | :ref:`Temperature Sensor ` (Debug) | 32 | 667 | 4 | 32 | 735 | 172 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Release) | 32 | 514 | 4 | 32 | 582 | 162 | + | :ref:`Temperature Sensor ` (Release) | 32 | 516 | 4 | 32 | 584 | 169 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Debug) | 32 | 657 | 4 | 32 | 725 | 163 | + | :ref:`Template ` (Debug) | 32 | 636 | 4 | 32 | 704 | 169 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Release) | 32 | 502 | 4 | 32 | 570 | 162 | + | :ref:`Template ` (Release) | 32 | 491 | 4 | 32 | 559 | 165 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Manufacturer-Specific ` (Debug) | 32 | 626 | 4 | 32 | 694 | 159 | + | :ref:`Thermostat ` (Debug) | 32 | 694 | 4 | 32 | 762 | 170 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Release) | 32 | 528 | 4 | 32 | 596 | 167 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Debug) | 32 | 669 | 4 | 32 | 737 | 170 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Release) | 32 | 515 | 4 | 32 | 583 | 166 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Manufacturer Specific ` (Debug) | 32 | 638 | 4 | 32 | 706 | 170 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ .. note:: @@ -152,9 +176,9 @@ Values are provided in kilobytes (KB). +---------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | +===============================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Weather Station ` (Debug) | 64 | 722 | 16 | 48 | 850 | 203 | + | :ref:`Weather Station ` (Debug) | 64 | 739 | 16 | 48 | 867 | 209 | +---------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Weather Station ` (Release) | 64 | 530 | 16 | 48 | 658 | 183 | + | :ref:`Weather Station ` (Release) | 64 | 542 | 16 | 48 | 670 | 187 | +---------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ .. tab:: nRF7002 DK @@ -164,31 +188,31 @@ Values are provided in kilobytes (KB). +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | +============================================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Bridge ` (Debug) | 48 | 879 | 4 | 32 | 963 | 303 | + | :ref:`Bridge ` (Debug) | 32 | 808 | 4 | 32 | 876 | 314 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Bridge ` (Release) | 48 | 811 | 4 | 32 | 895 | 300 | + | :ref:`Bridge ` (Release) | 32 | 743 | 4 | 32 | 811 | 311 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Debug) | 48 | 883 | 4 | 32 | 967 | 295 | + | :ref:`Light Bulb ` (Debug) | 32 | 811 | 4 | 32 | 879 | 307 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Release) | 48 | 795 | 4 | 32 | 879 | 289 | + | :ref:`Light Bulb ` (Release) | 32 | 724 | 4 | 32 | 792 | 300 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Debug) | 48 | 890 | 4 | 32 | 974 | 298 | + | :ref:`Light Switch ` (Debug) | 32 | 819 | 4 | 32 | 887 | 310 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Release) | 48 | 800 | 4 | 32 | 884 | 290 | + | :ref:`Light Switch ` (Release) | 32 | 731 | 4 | 32 | 799 | 302 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Debug) | 48 | 904 | 4 | 32 | 988 | 297 | + | :ref:`Lock ` (Debug) | 32 | 833 | 4 | 32 | 901 | 309 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Release) | 48 | 801 | 4 | 32 | 885 | 291 | + | :ref:`Lock ` (Release) | 32 | 731 | 4 | 32 | 799 | 303 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Debug) | 48 | 852 | 4 | 32 | 936 | 294 | + | :ref:`Template ` (Debug) | 32 | 780 | 4 | 32 | 848 | 306 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release) | 48 | 770 | 4 | 32 | 854 | 288 | + | :ref:`Template ` (Release) | 32 | 699 | 4 | 32 | 767 | 299 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Debug) | 48 | 898 | 4 | 32 | 982 | 295 | + | :ref:`Thermostat ` (Debug) | 32 | 828 | 4 | 32 | 896 | 307 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Release) | 48 | 801 | 4 | 32 | 885 | 289 | + | :ref:`Thermostat ` (Release) | 32 | 733 | 4 | 32 | 801 | 300 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Manufacturer Specific ` (Debug) | 48 | 854 | 4 | 32 | 938 | 294 | + | :ref:`Manufacturer Specific ` (Debug) | 32 | 783 | 4 | 32 | 851 | 306 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ @@ -202,37 +226,49 @@ Values are provided in kilobytes (KB). +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | +============================================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Light Bulb ` (Debug) | 52 | 777 | 4 | 40 | 873 | 176 | + | :ref:`Closure ` (Debug) | 52 | 765 | 4 | 40 | 861 | 179 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Closure ` (Release) | 52 | 613 | 4 | 40 | 709 | 175 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Contact Sensor ` (Debug) | 52 | 736 | 4 | 40 | 832 | 167 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Contact Sensor ` (Release) | 52 | 582 | 4 | 40 | 678 | 164 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Debug) | 52 | 788 | 4 | 40 | 884 | 179 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Release) | 52 | 617 | 4 | 40 | 713 | 172 | + | :ref:`Light Bulb ` (Release) | 52 | 631 | 4 | 40 | 727 | 175 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Debug) | 52 | 741 | 4 | 40 | 837 | 164 | + | :ref:`Light Switch ` (Debug) | 52 | 754 | 4 | 40 | 850 | 167 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Release) | 52 | 577 | 4 | 40 | 673 | 159 | + | :ref:`Light Switch ` (Release) | 52 | 592 | 4 | 40 | 688 | 162 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Debug) | 52 | 753 | 4 | 40 | 849 | 167 | + | :ref:`Lock ` (Debug) | 52 | 766 | 4 | 40 | 862 | 170 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Release) | 52 | 578 | 4 | 40 | 674 | 162 | + | :ref:`Lock ` (Release) | 52 | 593 | 4 | 40 | 689 | 165 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Smoke CO Alarm ` (Debug) | 52 | 731 | 4 | 40 | 827 | 165 | + | :ref:`Smoke CO Alarm ` (Debug) | 52 | 743 | 4 | 40 | 839 | 168 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Smoke CO Alarm ` (Release) | 52 | 572 | 4 | 40 | 668 | 161 | + | :ref:`Smoke CO Alarm ` (Release) | 52 | 585 | 4 | 40 | 681 | 164 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Debug) | 52 | 694 | 4 | 40 | 790 | 161 | + | :ref:`Temperature Sensor ` (Debug) | 52 | 736 | 4 | 40 | 832 | 167 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release) | 52 | 545 | 4 | 40 | 641 | 157 | + | :ref:`Temperature Sensor ` (Release) | 52 | 582 | 4 | 40 | 678 | 164 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release Internal Memory) | 52 | 539 | 4 | 40 | 635 | 158 | + | :ref:`Template ` (Debug) | 52 | 705 | 4 | 40 | 801 | 164 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Debug) | 52 | 749 | 4 | 40 | 845 | 162 | + | :ref:`Template ` (Release Internal Memory) | 52 | 551 | 4 | 40 | 647 | 160 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Release) | 52 | 579 | 4 | 40 | 675 | 158 | + | :ref:`Template ` (Release) | 52 | 557 | 4 | 40 | 653 | 160 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Debug) | 52 | 724 | 4 | 40 | 820 | 162 | + | :ref:`Thermostat ` (Debug) | 52 | 763 | 4 | 40 | 859 | 166 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Release) | 52 | 566 | 4 | 40 | 662 | 158 | + | :ref:`Thermostat ` (Release) | 52 | 594 | 4 | 40 | 690 | 161 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Manufacturer Specific ` (Debug) | 52 | 696 | 4 | 40 | 792 | 158 | + | :ref:`Window Covering ` (Debug) | 52 | 738 | 4 | 40 | 834 | 165 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Release) | 52 | 581 | 4 | 40 | 677 | 161 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Manufacturer Specific ` (Debug) | 52 | 707 | 4 | 40 | 803 | 165 | +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ @@ -246,21 +282,21 @@ Values are provided in kilobytes (KB). +----------------------------------------------------------------------------+---------------+------------+-------------------+----------------+------------+----------------+-------------+---------------------------------+ | Sample | MCUboot ROM | TF-M ROM | Application ROM | Factory data | Settings | TF-M Storage | Total ROM | Total RAM (incl. static HEAP) | +============================================================================+===============+============+===================+================+============+================+=============+=================================+ - | :ref:`Light Bulb ` (Debug) | 52 | 126 | 746 | 4 | 40 | 32 | 1000 | 223 | + | :ref:`Light Bulb ` (Debug) | 52 | 126 | 757 | 4 | 40 | 32 | 1011 | 226 | +----------------------------------------------------------------------------+---------------+------------+-------------------+----------------+------------+----------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Debug) | 52 | 126 | 710 | 4 | 40 | 32 | 964 | 210 | + | :ref:`Light Switch ` (Debug) | 52 | 126 | 723 | 4 | 40 | 32 | 977 | 214 | +----------------------------------------------------------------------------+---------------+------------+-------------------+----------------+------------+----------------+-------------+---------------------------------+ - | :ref:`Lock ` (Debug) | 52 | 126 | 723 | 4 | 40 | 32 | 977 | 213 | + | :ref:`Lock ` (Debug) | 52 | 126 | 735 | 4 | 40 | 32 | 989 | 216 | +----------------------------------------------------------------------------+---------------+------------+-------------------+----------------+------------+----------------+-------------+---------------------------------+ - | :ref:`Template ` (Debug) | 52 | 126 | 663 | 4 | 40 | 32 | 917 | 208 | + | :ref:`Template ` (Debug) | 52 | 126 | 674 | 4 | 40 | 32 | 928 | 211 | +----------------------------------------------------------------------------+---------------+------------+-------------------+----------------+------------+----------------+-------------+---------------------------------+ - | :ref:`Template ` (Release) | 52 | 126 | 522 | 4 | 40 | 32 | 776 | 204 | + | :ref:`Template ` (Release) | 52 | 126 | 534 | 4 | 40 | 32 | 788 | 207 | +----------------------------------------------------------------------------+---------------+------------+-------------------+----------------+------------+----------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Debug) | 52 | 126 | 719 | 4 | 40 | 32 | 973 | 209 | + | :ref:`Thermostat ` (Debug) | 52 | 126 | 732 | 4 | 40 | 32 | 986 | 212 | +----------------------------------------------------------------------------+---------------+------------+-------------------+----------------+------------+----------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Debug) | 52 | 126 | 694 | 4 | 40 | 32 | 948 | 209 | + | :ref:`Window Covering ` (Debug) | 52 | 126 | 707 | 4 | 40 | 32 | 961 | 212 | +----------------------------------------------------------------------------+---------------+------------+-------------------+----------------+------------+----------------+-------------+---------------------------------+ - | :ref:`Manufacturer Specific ` (Debug) | 52 | 126 | 665 | 4 | 40 | 32 | 919 | 204 | + | :ref:`Manufacturer Specific ` (Debug) | 52 | 126 | 676 | 4 | 40 | 32 | 930 | 212 | +----------------------------------------------------------------------------+---------------+------------+-------------------+----------------+------------+----------------+-------------+---------------------------------+ .. note:: @@ -270,71 +306,97 @@ Values are provided in kilobytes (KB). The following table lists memory requirements for samples running on the :zephyr:board:`nrf54lm20dk`. - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | - +====================================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Light Bulb ` (Debug) | 52 | 780 | 4 | 48 | 884 | 177 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Release) | 52 | 619 | 4 | 48 | 723 | 172 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Debug) | 52 | 743 | 4 | 48 | 847 | 164 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Release) | 52 | 579 | 4 | 48 | 683 | 159 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Debug) | 52 | 756 | 4 | 48 | 860 | 167 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Release) | 52 | 580 | 4 | 48 | 684 | 163 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Smoke CO Alarm ` (Debug) | 52 | 732 | 4 | 48 | 836 | 165 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Smoke CO Alarm ` (Release) | 52 | 572 | 4 | 48 | 676 | 161 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Debug) | 52 | 697 | 4 | 48 | 801 | 162 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release) | 52 | 547 | 4 | 48 | 651 | 158 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release Internal Memory) | 40 | 541 | 4 | 48 | 633 | 158 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Debug) | 52 | 752 | 4 | 48 | 856 | 163 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Release) | 52 | 581 | 4 | 48 | 685 | 158 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Debug) | 52 | 727 | 4 | 48 | 831 | 163 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Window Covering ` (Release) | 52 | 568 | 4 | 48 | 672 | 158 | - +--------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | + +============================================================================+===============+===================+================+============+=============+=================================+ + | :ref:`Bridge ` (Debug) | 52 | 789 | 4 | 48 | 893 | 206 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Bridge ` (Release) | 52 | 654 | 4 | 48 | 758 | 205 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Closure ` (Debug) | 52 | 765 | 4 | 48 | 869 | 179 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Closure ` (Release Internal Memory) | 40 | 608 | 4 | 48 | 700 | 175 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Closure ` (Release) | 52 | 613 | 4 | 48 | 717 | 175 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Contact Sensor ` (Debug) | 52 | 736 | 4 | 48 | 840 | 167 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Contact Sensor ` (Release) | 52 | 582 | 4 | 48 | 686 | 164 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Debug) | 52 | 789 | 4 | 48 | 893 | 179 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Release) | 52 | 631 | 4 | 48 | 735 | 175 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Debug) | 52 | 754 | 4 | 48 | 858 | 167 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Release) | 52 | 592 | 4 | 48 | 696 | 162 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Debug) | 52 | 767 | 4 | 48 | 871 | 170 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Release) | 52 | 593 | 4 | 48 | 697 | 166 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Smoke CO Alarm ` (Debug) | 52 | 744 | 4 | 48 | 848 | 168 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Smoke CO Alarm ` (Release) | 52 | 585 | 4 | 48 | 689 | 164 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Temperature Sensor ` (Debug) | 52 | 736 | 4 | 48 | 840 | 167 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Temperature Sensor ` (Release) | 52 | 582 | 4 | 48 | 686 | 164 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Debug) | 52 | 705 | 4 | 48 | 809 | 164 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Release Internal Memory) | 40 | 551 | 4 | 48 | 643 | 161 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Release) | 52 | 557 | 4 | 48 | 661 | 160 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Debug) | 52 | 764 | 4 | 48 | 868 | 166 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Release) | 52 | 594 | 4 | 48 | 698 | 161 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Debug) | 52 | 738 | 4 | 48 | 842 | 165 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Window Covering ` (Release) | 52 | 581 | 4 | 48 | 685 | 161 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Manufacturer Specific ` (Debug) | 52 | 707 | 4 | 48 | 811 | 166 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ .. tab:: nRF54LM20 DK with nRF7002-EB II The following table lists memory requirements for samples running on the :zephyr:board:`nrf54lm20dk` with the nRF7002-EB II. - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | - +============================================================+===============+===================+================+============+=============+=================================+ - | :ref:`Bridge ` (Debug) | 52 | 922 | 4 | 48 | 1026 | 332 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Bridge ` (Release) | 52 | 857 | 4 | 48 | 961 | 330 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Debug) | 52 | 1013 | 4 | 48 | 1117 | 312 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Bulb ` (Release) | 52 | 840 | 4 | 48 | 944 | 306 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Debug) | 52 | 1021 | 4 | 48 | 1125 | 315 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Light Switch ` (Release) | 52 | 845 | 4 | 48 | 949 | 308 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Debug) | 52 | 1036 | 4 | 48 | 1140 | 314 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Lock ` (Release) | 52 | 846 | 4 | 48 | 950 | 309 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Debug) | 52 | 979 | 4 | 48 | 1083 | 311 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Template ` (Release) | 52 | 816 | 4 | 48 | 920 | 306 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Debug) | 52 | 1031 | 4 | 48 | 1135 | 312 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ - | :ref:`Thermostat ` (Release) | 52 | 847 | 4 | 48 | 951 | 306 | - +------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | Sample | MCUboot ROM | Application ROM | Factory data | Settings | Total ROM | Total RAM (incl. static HEAP) | + +============================================================================+===============+===================+================+============+=============+=================================+ + | :ref:`Bridge ` (Debug) | 52 | 1026 | 4 | 48 | 1130 | 335 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Bridge ` (Release) | 52 | 876 | 4 | 48 | 980 | 333 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Closure ` (Debug) | 52 | 1003 | 4 | 48 | 1107 | 312 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Closure ` (Release) | 52 | 835 | 4 | 48 | 939 | 307 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Debug) | 52 | 1024 | 4 | 48 | 1128 | 313 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Bulb ` (Release) | 52 | 850 | 4 | 48 | 954 | 307 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Debug) | 52 | 1033 | 4 | 48 | 1137 | 316 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Light Switch ` (Release) | 52 | 856 | 4 | 48 | 960 | 309 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Debug) | 52 | 1047 | 4 | 48 | 1151 | 315 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Lock ` (Release) | 52 | 857 | 4 | 48 | 961 | 310 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Debug) | 52 | 988 | 4 | 48 | 1092 | 312 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Template ` (Release) | 52 | 825 | 4 | 48 | 929 | 306 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Debug) | 52 | 1044 | 4 | 48 | 1148 | 313 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Thermostat ` (Release) | 52 | 859 | 4 | 48 | 963 | 308 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ + | :ref:`Manufacturer Specific ` (Debug) | 52 | 990 | 4 | 48 | 1094 | 312 | + +----------------------------------------------------------------------------+---------------+-------------------+----------------+------------+-------------+---------------------------------+ .. _ug_matter_hw_requirements_layouts: From 572d4e372ffdeccc2d81d03198c37b429cb70dd0 Mon Sep 17 00:00:00 2001 From: divya pillai Date: Wed, 3 Dec 2025 14:06:16 +0100 Subject: [PATCH 123/155] doc: Updates to OS firmware table for the 3.2 release Updates to OS firware table for the 3.2 release Signed-off-by: divya pillai --- doc/nrf/installation/recommended_versions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/nrf/installation/recommended_versions.rst b/doc/nrf/installation/recommended_versions.rst index 60a57126dd71..62030967f973 100644 --- a/doc/nrf/installation/recommended_versions.rst +++ b/doc/nrf/installation/recommended_versions.rst @@ -30,7 +30,7 @@ For OS support for additional software tools from Nordic Semiconductor, see :ref * - Operating System - x64 - ARM64 - * - `Windows 10`_ + * - `Windows 11`_ - Built and tested with :ref:`Twister `. - Not supported. * - `Linux - Ubuntu 24.04 LTS`_ From 17fd650a29e54053e3a8a8307b6054946d387807 Mon Sep 17 00:00:00 2001 From: Tommi Kangas Date: Thu, 4 Dec 2025 10:13:34 +0200 Subject: [PATCH 124/155] lib: ntn: Remove %LOCATION subscription warning logs The library may be enabled in applications which are used with both NTN and non-NTN modem firmware. Removed warning logs which were printed with non-NTN firwmare when %LOCATION notification subscription failed. Signed-off-by: Tommi Kangas --- lib/ntn/ntn.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/ntn/ntn.c b/lib/ntn/ntn.c index 58e0ab6d79b5..b3564fd4dbcb 100644 --- a/lib/ntn/ntn.c +++ b/lib/ntn/ntn.c @@ -194,13 +194,11 @@ static void at_handler_location(const char *notif) static void location_ntf_subscribe(void) { - int err; - - err = nrf_modem_at_printf("AT%%LOCATION=1"); - if (err) { - LOG_WRN("Enabling location notifications failed, error: %d", err); - LOG_WRN("Modem firmware with NTN support required"); - } + /* Error is ignored because this basically only fails when the firmware does not have + * NTN support. There are applications which support both NTN and non-NTN modem + * firmware, so we don't want to log an error here with non-NTN firmware. + */ + (void)nrf_modem_at_printf("AT%%LOCATION=1"); } #if defined(CONFIG_UNITY) From a6dc848a3e09d7602ab955e11eec36b3a36de5b3 Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Tue, 2 Dec 2025 15:40:42 +0100 Subject: [PATCH 125/155] applications: nrf_desktop: doc: describe MCUboot RAM load mode Updated the nRF Desktop documentation page related to the bootloaders and DFU to describe the MCUboot RAM load mode. Ref: NCSDK-36374 Signed-off-by: Kamil Piszczek --- applications/nrf_desktop/bootloader_dfu.rst | 71 +++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/applications/nrf_desktop/bootloader_dfu.rst b/applications/nrf_desktop/bootloader_dfu.rst index 6ce917b3164e..58c3323a049e 100644 --- a/applications/nrf_desktop/bootloader_dfu.rst +++ b/applications/nrf_desktop/bootloader_dfu.rst @@ -189,6 +189,77 @@ For an example of a bootloader Kconfig configuration file defined by the applica Both mentioned firmware upgrade methods are not used simultaneously by any of the configurations. For example, the ``nrf52840dk/nrf52840`` board in ``mcuboot_smp`` file suffix uses only the background DFU and does not enable the serial recovery feature. +RAM load mode +~~~~~~~~~~~~~ + +The RAM load mode is used for the :ref:`background DFU `. +In this mode, the MCUboot bootloader uses the same NVM partitioning as the direct-xip mode (the dual-bank DFU solution). +Similarly to the direct-xip mode, the RAM load mode also relies on the image version to select the application image slot to be booted. +However, instead of booting the image from the NVM slot, the bootloader in the RAM load mode copies the image from the non-volatile memory (NVM) to the RAM and boots it from there. +The application image is always built for the RAM address space in only one variant. + +.. caution:: + The RAM load mode of the MCUboot bootloader is not officially supported in |NCS|. + However, the mode is available in the |NCS| as the support for this feature has been developed as part of the Zephyr RTOS project. + This feature is only used in a limited context for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target configuration to improve performance. + +You can use the RAM load mode of the MCUboot bootloader to speed up the code execution for the application image, as code execution from the RAM is generally faster than from the NVM. +This can improve the device performance during the activities that require high CPU usage. +As an example, the nRF Desktop application uses the RAM load mode for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target to achieve 8 kHz report rate over USB in the ``release_ram_load`` configuration variant (the second configuration variant - ``ram_load`` - is used for debugging purposes only). + +To set the MCUboot mode of operations to the RAM load mode, enable the :kconfig:option:`SB_CONFIG_MCUBOOT_MODE_RAM_LOAD` Kconfig option in the sysbuild configuration. + +To support the RAM load mode, you must use DTS as the partitioning method, as the Partition Manager (PM) is not supported in this mode. +To satisfy this requirement, disable explicitly the :kconfig:option:`SB_CONFIG_PARTITION_MANAGER` Kconfig option in your sysbuild configuration. +Additionally, you must define the custom memory layout for the RAM in your target board configuration. +Your RAM layout must define the following DTS child nodes as part of the ``cpuapp_sram`` DTS node in the address order listed below: + +* ``cpuapp_sram_app_rxm_region`` - This DTS node defines the hard limits for the executable ROM section (with the application image) and must be aligned with the :kconfig:option:`CONFIG_BOOT_IMAGE_EXECUTABLE_RAM_START` and the :kconfig:option:`CONFIG_BOOT_IMAGE_EXECUTABLE_RAM_SIZE` Kconfig options that are set in the MCUboot image configuration. + This DTS node describes the region in which the build system places the executable ROM section (code) and RAM section (data) of the application image. + The RAM section is located right after the ROM section - the RAM section may overflow the ``cpuapp_sram_app_rxm_region`` region and spill into the subsequent ``cpuapp_sram_mcuboot_ram_region`` region or even be entirely contained in this subsequent region. + The ``cpuapp_sram_mcuboot_ram_region`` region can be filled with the RAM section of the application image, as the application and bootloader code cannot run simultaneously. +* ``cpuapp_sram_mcuboot_ram_region`` - This DTS node defines the RAM region for the MCUboot image and must be assigned to the MCUboot image as its chosen SRAM DTS node. + +For an example of the custom RAM layout that satisfies these requirements, see the :file:`nrf/applications/nrf_desktop/configuration/nrf54lm20dk_nrf54lm20a_cpuapp/memory_map_ram_load.dtsi` file. +For an example of the RAM layout usage in the MCUboot bootloader image, see the :file:`nrf/applications/nrf_desktop/configuration/nrf54lm20dk_nrf54lm20a_cpuapp/images/mcuboot/app_ram_load.overlay` file. + +.. note:: + The application image and the MCUboot image configuration must use the same memory layout. + +The RAM load mode requires using the Zephyr retention subsystem with the bootloader information sharing system. +This subsystem is used by the MCUboot bootloader to provide image metadata to the application image. +To enable the Zephyr retention subsystem, enable the following Kconfig options in your application image configuration and the MCUboot image configuration: + +* :kconfig:option:`CONFIG_RETENTION` +* :kconfig:option:`CONFIG_RETAINED_MEM` +* :kconfig:option:`CONFIG_RETAINED_MEM_ZEPHYR_RAM` + +In the application image configuration, enable the following Kconfig options: + +* :kconfig:option:`CONFIG_RETENTION_BOOTLOADER_INFO` +* :kconfig:option:`CONFIG_RETENTION_BOOTLOADER_INFO_TYPE_MCUBOOT` +* :kconfig:option:`CONFIG_RETENTION_BOOTLOADER_INFO_OUTPUT_FUNCTION` + +In the MCUboot image configuration, enable the following Kconfig options: + +* :kconfig:option:`CONFIG_BOOT_SHARE_DATA` +* :kconfig:option:`CONFIG_BOOT_SHARE_DATA_BOOTINFO` +* :kconfig:option:`CONFIG_BOOT_SHARE_BACKEND_RETENTION` + +The Zephyr retention subsystem requires the retention partition to be defined in the devicetree. +For an example of the retention partition definition, see the :file:`nrf/applications/nrf_desktop/configuration/nrf54lm20dk_nrf54lm20a_cpuapp/memory_map_ram_load.dtsi` file. +You must also assign the retention partition to the chosen DTS node ``zephyr,bootloader-info`` in both the application image configuration and the MCUboot image configuration. + +.. note:: + If your board target uses the Key Management Unit (KMU) feature (:kconfig:option:`CONFIG_CRACEN_LIB_KMU`), you must additionally define the ``nrf_kmu_reserved_push_area`` DTS node in your custom memory layout. + Place this RAM section at the very beginning of the physical RAM due to the dependency on the ``nrfutil device`` tool and its KMU provisioning functionality. + For an example of the ``nrf_kmu_reserved_push_area`` DTS node definition, see the :file:`nrf/applications/nrf_desktop/configuration/nrf54lm20dk_nrf54lm20a_cpuapp/memory_map_ram_load.dtsi` file. + + The KMU feature (:kconfig:option:`CONFIG_CRACEN_LIB_KMU`) is enabled by default for the nRF54L series. + +.. note:: + The RAM load mode of the MCUboot bootloader is not yet integrated in the :ref:`nrf_desktop_dfu_mcumgr`. + MCUboot bootloader on nRF54 --------------------------- From 0258c997d101e009bebe1b28968822cd652190f5 Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Tue, 2 Dec 2025 16:00:48 +0100 Subject: [PATCH 126/155] applications: nrf_desktop: doc: update nRF54LM20 DK board configuration Updated the nRF54LM20 DK entry in board configuration documentation of the nRF Desktop application to describe support for the RAM load mode configurations that improve the HID report rate over USB. Ref: NCSDK-36374 Signed-off-by: Kamil Piszczek --- applications/nrf_desktop/board_configuration.rst | 12 ++++++++---- applications/nrf_desktop/bootloader_dfu.rst | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/applications/nrf_desktop/board_configuration.rst b/applications/nrf_desktop/board_configuration.rst index 33f97c84782b..17edde178a99 100644 --- a/applications/nrf_desktop/board_configuration.rst +++ b/applications/nrf_desktop/board_configuration.rst @@ -176,15 +176,19 @@ Sample mouse (``nrf54lm20dk/nrf54lm20a/cpuapp``) * Bluetooth LE and USB High-Speed transports are enabled. Bluetooth LE is configured to use Nordic Semiconductor's SoftDevice Link Layer and Low Latency Packet Mode (LLPM). USB High-Speed is configured to use the USB next stack (:kconfig:option:`CONFIG_USB_DEVICE_STACK_NEXT`). - The :option:`CONFIG_DESKTOP_BLE_ADV_CTRL_ENABLE` and :option:`CONFIG_DESKTOP_BLE_ADV_CTRL_SUSPEND_ON_USB` Kconfig options are enabled in mouse configurations to improve the USB High-Speed report rate. - * In ``debug`` configurations, logs are provided through the UART. + The :option:`CONFIG_DESKTOP_BLE_ADV_CTRL_ENABLE` and :option:`CONFIG_DESKTOP_BLE_ADV_CTRL_SUSPEND_ON_USB` Kconfig options are enabled in mouse configurations to improve the HID report rate over USB. + * In ``debug``, ``ram_load``, and ``llvm`` configurations, logs are provided through the UART. For detailed information on working with the nRF54LM20 DK, see the :ref:`ug_nrf54l15_gs` documentation. * In ``llvm`` configurations, the partition layout is different to accommodate for the higher memory footprint of the ``llvm`` toolchain. - * The configurations use the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``) and support firmware updates using the :ref:`nrf_desktop_dfu`. + * The ``debug``, ``release``, and ``llvm`` configurations use the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``) and support firmware updates using the :ref:`nrf_desktop_dfu`. All of the configurations enable hardware cryptography for the MCUboot bootloader. The application image is verified using a pure ED25519 signature. The public key that MCUboot uses for validating the application image is securely stored in the hardware Key Management Unit (KMU). For more details on nRF54L Series cryptography, see :ref:`ug_nrf54l_cryptography`. + * The ``ram_load`` and ``release_ram_load`` configurations use the MCUboot bootloader built in the RAM load mode (``MCUBOOT``) and support firmware updates using the :ref:`nrf_desktop_dfu`. + Configurations in this bootloader mode use the same security features as direct-xip mode (``MCUBOOT+XIP``), including hardware cryptography, signature type, and public key storage. + The application code is executed from the RAM in this mode to improve the HID report rate over USB. + For more details on the RAM load mode, see the MCUboot :ref:`nrf_desktop_configuring_mcuboot_bootloader_ram_load` documentation section. Sample mouse or dongle (``nrf54h20dk/nrf54h20/cpuapp``) * The configuration uses the nRF54H20 DK. @@ -193,7 +197,7 @@ Sample mouse or dongle (``nrf54h20dk/nrf54h20/cpuapp``) * Bluetooth LE and USB High-Speed transports are enabled. Bluetooth LE is configured to use Nordic Semiconductor's SoftDevice Link Layer and Low Latency Packet Mode (LLPM). USB High-Speed is configured to use the USB next stack (:kconfig:option:`CONFIG_USB_DEVICE_STACK_NEXT`). - The :option:`CONFIG_DESKTOP_BLE_ADV_CTRL_ENABLE` and :option:`CONFIG_DESKTOP_BLE_ADV_CTRL_SUSPEND_ON_USB` Kconfig options are enabled in mouse configurations to improve the USB High-Speed report rate. + The :option:`CONFIG_DESKTOP_BLE_ADV_CTRL_ENABLE` and :option:`CONFIG_DESKTOP_BLE_ADV_CTRL_SUSPEND_ON_USB` Kconfig options are enabled in mouse configurations to improve the HID report rate over USB. * In ``debug`` configurations, logs are provided through the UART. For detailed information on working with the nRF54H20 DK, see the :ref:`ug_nrf54h20_gs` documentation. * The configurations use the MCUboot bootloader built in the direct-xip mode (``MCUBOOT+XIP``) and support firmware updates using the :ref:`nrf_desktop_dfu`. diff --git a/applications/nrf_desktop/bootloader_dfu.rst b/applications/nrf_desktop/bootloader_dfu.rst index 58c3323a049e..4e80dd0e1042 100644 --- a/applications/nrf_desktop/bootloader_dfu.rst +++ b/applications/nrf_desktop/bootloader_dfu.rst @@ -189,6 +189,8 @@ For an example of a bootloader Kconfig configuration file defined by the applica Both mentioned firmware upgrade methods are not used simultaneously by any of the configurations. For example, the ``nrf52840dk/nrf52840`` board in ``mcuboot_smp`` file suffix uses only the background DFU and does not enable the serial recovery feature. +.. _nrf_desktop_configuring_mcuboot_bootloader_ram_load: + RAM load mode ~~~~~~~~~~~~~ From d0f84cb57d7e07a99e2cd487eeb8c0503dd579de Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Thu, 4 Dec 2025 11:13:03 +0100 Subject: [PATCH 127/155] tests: benchmarks: i2c_endless: fix nrf5340 and disable zephyr driver Set status "okay" for the i2c2 devicetree node for the nrf5340, and disable the zephyr TWIS device driver since its not used and may conflict with directly using nrfx as this test does. Unquarantine the test cases as it is now fixed. Signed-off-by: Bjarki Arge Andreasen --- scripts/quarantine.yaml | 7 ------- .../i2c_endless/boards/nrf5340dk_nrf5340_cpuapp.overlay | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/scripts/quarantine.yaml b/scripts/quarantine.yaml index c15578425357..5ce6418b371b 100644 --- a/scripts/quarantine.yaml +++ b/scripts/quarantine.yaml @@ -112,10 +112,3 @@ platforms: - nrf54ls05dk@0.0.0/nrf54ls05b/cpuapp comment: "https://nordicsemi.atlassian.net/browse/NCSDK-36650" - -- scenarios: - - boards.nrf.i2c.i2c_endless.host - - boards.nrf.i2c.i2c_endless.device - platforms: - - nrf5340dk/nrf5340/cpuapp - comment: "https://nordicsemi.atlassian.net/browse/NCSDK-36649" diff --git a/tests/benchmarks/i2c_endless/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/benchmarks/i2c_endless/boards/nrf5340dk_nrf5340_cpuapp.overlay index 6fdf59f55e1f..0bdf192fd510 100644 --- a/tests/benchmarks/i2c_endless/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/tests/benchmarks/i2c_endless/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -56,6 +56,7 @@ &i2c2 { compatible = "nordic,nrf-twis"; + status = "okay"; pinctrl-0 = <&i2c2_default_alt>; pinctrl-1 = <&i2c2_sleep_alt>; pinctrl-names = "default", "sleep"; From a7e1eda4b68179bc404080a733bcf3b540396c87 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Wed, 3 Dec 2025 14:35:20 +0000 Subject: [PATCH 128/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3596 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 9c06c2c31b7f..ffc612a8f708 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: 8c2f434f8e6788e542283f98d9f175140f2017a5 + revision: 18c1bc6ba28bc425f2567cf58f4c7353fca1b6eb import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From 89bc0c016ae7ce94b540b435efbd6c36035838cf Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Thu, 4 Dec 2025 08:42:06 +0100 Subject: [PATCH 129/155] applications: nrf_desktop: Align battery_def.h with nrfx 4.0 Change aligns battery_def.h configuration files used by nRF Desktop devices with nrfx 4.0. `NRF_SAADC_` macros can no longer be used here. Jira: NCSDK-36662 Signed-off-by: Marek Pieta Signed-off-by: Jakub Zymelka --- .../configuration/nrf52840gmouse_nrf52840/battery_def.h | 5 ++++- .../configuration/nrf52dmouse_nrf52832/battery_def.h | 5 ++++- .../configuration/nrf52kbd_nrf52832/battery_def.h | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/battery_def.h b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/battery_def.h index 0253d0a4030f..e8352676bde6 100644 --- a/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/battery_def.h +++ b/applications/nrf_desktop/configuration/nrf52840gmouse_nrf52840/battery_def.h @@ -8,12 +8,15 @@ * and holds information about battery characteristic. */ +#include +#include + /* This structure enforces the header file is included only once in the build. * Violating this requirement triggers a multiple definition error at link time. */ const struct {} battery_def_include_once; -#define BATTERY_MEAS_ADC_INPUT NRF_SAADC_INPUT_AIN3 +#define BATTERY_MEAS_ADC_INPUT NRFX_ANALOG_EXTERNAL_AIN3 #define BATTERY_MEAS_ADC_GAIN ADC_GAIN_1 #define BATTERY_MEAS_VOLTAGE_GAIN 1 diff --git a/applications/nrf_desktop/configuration/nrf52dmouse_nrf52832/battery_def.h b/applications/nrf_desktop/configuration/nrf52dmouse_nrf52832/battery_def.h index 067d0fff3d8f..55d636d49640 100644 --- a/applications/nrf_desktop/configuration/nrf52dmouse_nrf52832/battery_def.h +++ b/applications/nrf_desktop/configuration/nrf52dmouse_nrf52832/battery_def.h @@ -8,12 +8,15 @@ * module and holds information about battery characteristic. */ +#include +#include + /* This structure enforces the header file is included only once in the build. * Violating this requirement triggers a multiple definition error at link time. */ const struct {} battery_def_include_once; -#define BATTERY_MEAS_ADC_INPUT NRF_SAADC_INPUT_AIN2 +#define BATTERY_MEAS_ADC_INPUT NRFX_ANALOG_EXTERNAL_AIN2 #define BATTERY_MEAS_ADC_GAIN ADC_GAIN_1_4 #define BATTERY_MEAS_VOLTAGE_GAIN 4 diff --git a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/battery_def.h b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/battery_def.h index 7c65676838f5..8e271642f962 100644 --- a/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/battery_def.h +++ b/applications/nrf_desktop/configuration/nrf52kbd_nrf52832/battery_def.h @@ -8,12 +8,15 @@ * module and holds information about battery characteristic. */ +#include +#include + /* This structure enforces the header file is included only once in the build. * Violating this requirement triggers a multiple definition error at link time. */ const struct {} battery_def_include_once; -#define BATTERY_MEAS_ADC_INPUT NRF_SAADC_INPUT_VDD +#define BATTERY_MEAS_ADC_INPUT NRFX_ANALOG_INTERNAL_VDD #define BATTERY_MEAS_ADC_GAIN ADC_GAIN_1_6 #define BATTERY_MEAS_VOLTAGE_GAIN 6 From 4dc5927dade98b6bc5cbdfd1e96facb3c414ab43 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Thu, 4 Dec 2025 08:45:41 +0100 Subject: [PATCH 130/155] doc: Update nRF54H20 key provisioning page Replace the outdated information pertaining to SUIT SDFW with new info applicable to the latest release of IronSide SE. Signed-off-by: Grzegorz Swiderski --- .../nrf54h/ug_nrf54h20_ironside.rst | 4 + .../device_guides/nrf54h/ug_nrf54h20_keys.rst | 93 +++++++++---------- 2 files changed, 50 insertions(+), 47 deletions(-) diff --git a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst index 824587b9ce12..29ec6b2feebc 100644 --- a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst +++ b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_ironside.rst @@ -381,6 +381,8 @@ It is divided into a 16-bit major version and a 16-bit minor version. This versioning scheme allows IronSide to support multiple UICR formats, enabling updates to the format without breaking compatibility with existing configurations. +.. _ug_nrf54h20_ironside_se_uicr_lock: + UICR.LOCK ========= @@ -1261,6 +1263,8 @@ See the following table for a summary of the available boot commands: The following chapters describe each command in detail. +.. _ug_nrf54h20_ironside_se_eraseall_command: + ``ERASEALL`` command ==================== diff --git a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_keys.rst b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_keys.rst index c5c41bfdab85..8da52a0c722e 100644 --- a/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_keys.rst +++ b/doc/nrf/app_dev/device_guides/nrf54h/ug_nrf54h20_keys.rst @@ -7,82 +7,77 @@ Provisioning keys on the nRF54H20 SoC :local: :depth: 2 -This guide describes how to generate and provision cryptographic public keys on an nRF54H20 SoC in the Root of Trust (RoT) lifecycle state. -It is intended for developers defining manifest signing keys for the application core, radio core, and OEM root. -A successful provisioning makes the keys available to Secure Domain Firmware through PSA Crypto key identifiers. +This guide describes how to provision pre-generated cryptographic keys on an nRF54H20 SoC. +It is intended for developers who wish to create a predefined set of keys for their application, made available through PSA Crypto key identifiers. Prerequisites ============= -To follow this guide, your nRF54H20 device must meet the following requirement: +To follow this guide, your nRF54H20 device must meet the following requirements: * On the nRF54H20 DK, you must :ref:`provision ` the DK as described in the :ref:`ug_nrf54h20_gs` page. * On a custom nRF54H20-based device, you must :ref:`configure, generate, and program the BICR ` as described in the :ref:`ug_nrf54h20_custom_pcb` page. -* You must configure :ref:`ug_nrf54h20_ironside_uicr_securestorage` in your |ISE| UICR configuration. Overview ======== -The keys provisioning workflow for the nRF54H20 SoC consists of two main steps: +The keys provisioning workflow for the nRF54H20 SoC consists of three main steps: -1. Generating the required metadata using a script provided with the |NCS|. +1. Choosing key identifiers based on the desired properties for each key. +#. Generating the required metadata using a script provided with the |NCS|. #. Provisioning the keys to the nRF54H20 SoC. -.. note:: - The nRF54H20 SoC must be in RoT lifecycle state for key provisioning to work. - For more details on lifecycle states, see :ref:`ug_nrf54h20_architecture_lifecycle`. +.. rst-class:: numbered-step -.. _ug_nrf54h20_keys_generating: +Choosing a key ID +================= + +Key provisioning is supported by the |ISE| firmware through the :ref:`ug_crypto_architecture_implementation_standards_ironside` of the PSA Crypto API. +|ISE| defines two categories of keys that can be provisioned: standard *user keys* and non-standard *revocable keys*. +These categories are tied to distinct key ID ranges. -Generating the keys -=================== +User keys +--------- -A script is used to generate the necessary cryptographic keys, BLOBs, and metadata required for provisioning. -The script follows the PSA Crypto standard to generate the required 28-byte key. -It is located in the :file:`nrf/scripts/generate_psa_key_attributes.py` file. +These are the standard persistent keys conforming to the :ref:`supported version of the PSA Crypto API `: -To generate the keys, follow these steps: +* Minimum ID: ``0x00000001`` (``PSA_KEY_ID_USER_MIN``) +* Maximum ID: ``0x3FFFFFFF`` (``PSA_KEY_ID_USER_MAX``) -1. Generate private keys using Ed25519:: +In order to successfully provision user keys, you must first configure cryptographic partitions in your :ref:`ug_nrf54h20_ironside_uicr_securestorage` configuration. - openssl genpkey -algorithm Ed25519 -out MANIFEST_APPLICATION_GEN1_priv.pem - openssl genpkey -algorithm Ed25519 -out MANIFEST_RADIOCORE_GEN1_priv.pem - openssl genpkey -algorithm Ed25519 -out MANIFEST_OEM_ROOT_GEN1_priv.pem +Revocable keys +-------------- -#. Extract public keys:: +These are an extension of user keys with special properties for secure provisioning during device manufacturing: - openssl pkey -in MANIFEST_APPLICATION_GEN1_priv.pem -pubout -out MANIFEST_APPLICATION_GEN1_pub.pem - openssl pkey -in MANIFEST_RADIOCORE_GEN1_priv.pem -pubout -out MANIFEST_RADIOCORE_GEN1_pub.pem - openssl pkey -in MANIFEST_OEM_ROOT_GEN1_priv.pem -pubout -out MANIFEST_OEM_ROOT_GEN1_pub.pem +* Minimum ID: ``0x40002000`` +* Maximum ID: ``0x4FFFFFFF`` -#. Check the required key IDs:: +Revocable keys can only be provisioned as long as the :ref:`ug_nrf54h20_ironside_se_uicr_lock` configuration is disabled. +Once the UICR is locked, no more keys can be created in this range, which means that when a revocable key is destroyed, it cannot be replaced. - MANIFEST_PUBKEY_APPLICATION_GEN1 = 0x40022100 - MANIFEST_PUBKEY_APPLICATION_GEN2 = 0x40022101 - MANIFEST_PUBKEY_APPLICATION_GEN3 = 0x40022102 - MANIFEST_PUBKEY_OEM_ROOT_GEN1 = 0x4000AA00 - MANIFEST_PUBKEY_OEM_ROOT_GEN2 = 0x4000AA01 - MANIFEST_PUBKEY_OEM_ROOT_GEN3 = 0x4000AA02 - MANIFEST_PUBKEY_RADIOCORE_GEN1 = 0x40032100 - MANIFEST_PUBKEY_RADIOCORE_GEN2 = 0x40032101 - MANIFEST_PUBKEY_RADIOCORE_GEN3 = 0x40032102 +These keys are provisioned into |ISE|'s internal storage, not the location controlled by :ref:`ug_nrf54h20_ironside_uicr_securestorage`. -#. Create a JSON input file with the :ref:`generate_psa_key_attributes_script`: +.. _ug_nrf54h20_keys_generating: - * For the application core:: +.. rst-class:: numbered-step - python generate_psa_key_attributes.py --usage VERIFY --allow-usage-export --id 0x40022100 --type ECC_PUBLIC_KEY_TWISTED_EDWARDS --key-bits 255 --algorithm EDDSA_PURE --location LOCATION_CRACEN --key-from-file MANIFEST_APPLICATION_GEN1_pub.pem --file all_keys.json --cracen-usage RAW --persistence PERSISTENCE_DEFAULT +Generating key metadata +======================= - * For the radio core:: +The :ref:`generate_psa_key_attributes_script` is used to generate a JSON file containing the necessary cryptographic keys, BLOBs, and metadata required for provisioning. - python generate_psa_key_attributes.py --usage VERIFY --allow-usage-export --id 0x40032100 --type ECC_PUBLIC_KEY_TWISTED_EDWARDS --key-bits 255 --algorithm EDDSA_PURE --location LOCATION_CRACEN --key-from-file MANIFEST_RADIOCORE_GEN1_pub.pem --file all_keys.json --cracen-usage RAW --persistence PERSISTENCE_DEFAULT +Here is an example command to generate metadata for provisioning the public key part of an Ed25519 key, from a pre-existing PEM file, as a revocable key: - * For the main root manifest:: +.. parsed-literal:: + :class: highlight - python generate_psa_key_attributes.py --usage VERIFY --allow-usage-export --id 0x4000AA00 --type ECC_PUBLIC_KEY_TWISTED_EDWARDS --key-bits 255 --algorithm EDDSA_PURE --location LOCATION_CRACEN --key-from-file MANIFEST_OEM_ROOT_GEN1_pub.pem --file all_keys.json --cracen-usage RAW --persistence PERSISTENCE_DEFAULT + python generate_psa_key_attributes.py --usage VERIFY --id 0x40002000 --type ECC_PUBLIC_KEY_TWISTED_EDWARDS --key-bits 255 --algorithm EDDSA_PURE --location LOCATION_LOCAL_STORAGE --key-from-file public_key.pem --file all_keys.json --persistence PERSISTENCE_DEFAULT +The output file (named :file:`all_keys.json` in the previous example) serves as an input for the next step. -The generated key data is stored in a JSON file, which serves as an input for the next step. +.. rst-class:: numbered-step Provisioning the keys ===================== @@ -91,13 +86,17 @@ Provisioning the keys :start-after: nrfutil_provision_keys_info_start :end-before: nrfutil_provision_keys_info_end -The Secure Domain Firmware on the device handles the actual key provisioning using PSA Crypto's ``psa_import_key`` function. +The |ISE| firmware on the device handles the actual key provisioning using PSA Crypto's ``psa_import_key`` function. Provisioning a key calls the function to import the key: -* The ``metadata`` field from the JSON file is used for the function's attributes argument. -* The ``value`` field is passed to the function's data argument. -* The function's ``data_length`` is set to the length of the value field. +* The ``metadata`` field from the JSON file is used for the function's ``attributes`` argument. +* The ``value`` field is passed to the function's ``data`` argument. +* The length of the ``value`` field is passed to the function's ``data_length`` argument. .. include:: ../../../../../scripts/generate_psa_key_attributes/generate_psa_key_attributes.rst :start-after: nrfutil_provision_keys_command_start :end-before: nrfutil_provision_keys_command_end + +.. note:: + The :ref:`ug_nrf54h20_ironside_se_eraseall_command` destroys all keys stored on the device. + Whenever you execute this boot command, you have to provision your keys all over again. From af76f4a9447fb15eb8f06b38bcf60a97a6da3ea9 Mon Sep 17 00:00:00 2001 From: Dhanoo Surasarang Date: Wed, 3 Dec 2025 16:58:22 +0000 Subject: [PATCH 131/155] tests: drivers: i2s: Add nRF7120 support for I2S test suites All added testsuites worked, apart from aclk_mck test variant which uses ACLK for MCK only (while SCK uses PCLK) and does not work reliably in TX-only mode. Signed-off-by: Dhanoo Surasarang --- .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 23 ++++++++ tests/drivers/i2s/i2s_instances/testcase.yaml | 1 + .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 32 +++++++++++ tests/drivers/i2s/i2s_latency/testcase.yaml | 3 + .../boards/nrf7120pdk_nrf7120_cpuapp.conf | 1 + .../boards/nrf7120pdk_nrf7120_cpuapp.overlay | 45 +++++++++++++++ .../boards/tdm_mck_audio_auxpll.overlay | 13 +++++ .../boards/tdm_sck_audio_auxpll.overlay | 13 +++++ tests/drivers/i2s/i2s_mclk/testcase.yaml | 55 ++++++++++++++----- 9 files changed, 173 insertions(+), 13 deletions(-) create mode 100644 tests/drivers/i2s/i2s_instances/boards/nrf7120pdk_nrf7120_cpuapp.overlay create mode 100644 tests/drivers/i2s/i2s_latency/boards/nrf7120pdk_nrf7120_cpuapp.overlay create mode 100644 tests/drivers/i2s/i2s_mclk/boards/nrf7120pdk_nrf7120_cpuapp.conf create mode 100644 tests/drivers/i2s/i2s_mclk/boards/nrf7120pdk_nrf7120_cpuapp.overlay create mode 100644 tests/drivers/i2s/i2s_mclk/boards/tdm_mck_audio_auxpll.overlay create mode 100644 tests/drivers/i2s/i2s_mclk/boards/tdm_sck_audio_auxpll.overlay diff --git a/tests/drivers/i2s/i2s_instances/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/drivers/i2s/i2s_instances/boards/nrf7120pdk_nrf7120_cpuapp.overlay new file mode 100644 index 000000000000..5c7c0e4b7b25 --- /dev/null +++ b/tests/drivers/i2s/i2s_instances/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&pinctrl { + tdm_default_test: tdm_default_test { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&tdm { + status = "okay"; + pinctrl-0 = <&tdm_default_test>; + pinctrl-names = "default"; + sck-clock-source = "ACLK"; +}; diff --git a/tests/drivers/i2s/i2s_instances/testcase.yaml b/tests/drivers/i2s/i2s_instances/testcase.yaml index a8aabe610313..80b4c92c4e4f 100644 --- a/tests/drivers/i2s/i2s_instances/testcase.yaml +++ b/tests/drivers/i2s/i2s_instances/testcase.yaml @@ -11,5 +11,6 @@ tests: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf7120pdk/nrf7120/cpuapp integration_platforms: - nrf54h20dk/nrf54h20/cpuapp diff --git a/tests/drivers/i2s/i2s_latency/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/drivers/i2s/i2s_latency/boards/nrf7120pdk_nrf7120_cpuapp.overlay new file mode 100644 index 000000000000..2d5409b1195f --- /dev/null +++ b/tests/drivers/i2s/i2s_latency/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + aliases { + tst-timer = &timer20; + }; +}; + +&pinctrl { + tdm20_default_test: tdm20_default_test { + group1 { + psels = , + , + , + ; + }; + }; +}; + +i2s_dut: &tdm { + status = "okay"; + pinctrl-0 = <&tdm20_default_test>; + pinctrl-names = "default"; +}; + +&timer20 { + status = "okay"; +}; diff --git a/tests/drivers/i2s/i2s_latency/testcase.yaml b/tests/drivers/i2s/i2s_latency/testcase.yaml index 1524ee8a98e7..50364ada6779 100644 --- a/tests/drivers/i2s/i2s_latency/testcase.yaml +++ b/tests/drivers/i2s/i2s_latency/testcase.yaml @@ -9,6 +9,7 @@ tests: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - nrf54l15dk/nrf54l15/cpuapp + - nrf7120pdk/nrf7120/cpuapp integration_platforms: - nrf54l15dk/nrf54l15/cpuapp harness: ztest @@ -21,6 +22,7 @@ tests: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - nrf54l15dk/nrf54l15/cpuapp + - nrf7120pdk/nrf7120/cpuapp integration_platforms: - nrf54l15dk/nrf54l15/cpuapp harness: ztest @@ -32,6 +34,7 @@ tests: platform_allow: - nrf5340dk/nrf5340/cpuapp - nrf54l15dk/nrf54l15/cpuapp + - nrf7120pdk/nrf7120/cpuapp integration_platforms: - nrf54l15dk/nrf54l15/cpuapp harness: ztest diff --git a/tests/drivers/i2s/i2s_mclk/boards/nrf7120pdk_nrf7120_cpuapp.conf b/tests/drivers/i2s/i2s_mclk/boards/nrf7120pdk_nrf7120_cpuapp.conf new file mode 100644 index 000000000000..b21efebbc862 --- /dev/null +++ b/tests/drivers/i2s/i2s_mclk/boards/nrf7120pdk_nrf7120_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_I2S_TEST_SKIP_I2S_DIR_RX=y diff --git a/tests/drivers/i2s/i2s_mclk/boards/nrf7120pdk_nrf7120_cpuapp.overlay b/tests/drivers/i2s/i2s_mclk/boards/nrf7120pdk_nrf7120_cpuapp.overlay new file mode 100644 index 000000000000..1e2e7fe14769 --- /dev/null +++ b/tests/drivers/i2s/i2s_mclk/boards/nrf7120pdk_nrf7120_cpuapp.overlay @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* i2s-node0 is the transmitter/receiver */ + +/ { + aliases { + i2s-node0 = &tdm; + }; + + zephyr,user { + gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>, /* Connect with TDM_MCK */ + <&gpio1 11 GPIO_ACTIVE_HIGH>; /* Connect with TDM_FSYNC_M */ + }; +}; + +&gpio1 { + status = "okay"; +}; + +&gpiote20 { + status = "okay"; +}; + +&pinctrl { + tdm_default_alt: tdm_default_alt { + group1 { + psels = , + , + , + , /* TDM_SDOUT shorted to TDM_SDIN */ + ; + }; + }; +}; + +&tdm { + status = "okay"; + pinctrl-0 = <&tdm_default_alt>; + pinctrl-names = "default"; + mck-frequency = <64000>; +}; diff --git a/tests/drivers/i2s/i2s_mclk/boards/tdm_mck_audio_auxpll.overlay b/tests/drivers/i2s/i2s_mclk/boards/tdm_mck_audio_auxpll.overlay new file mode 100644 index 000000000000..c4012dc5fe87 --- /dev/null +++ b/tests/drivers/i2s/i2s_mclk/boards/tdm_mck_audio_auxpll.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&tdm { + mck-clock-source = "ACLK"; +}; + +&audio_auxpll { + status = "okay"; +}; diff --git a/tests/drivers/i2s/i2s_mclk/boards/tdm_sck_audio_auxpll.overlay b/tests/drivers/i2s/i2s_mclk/boards/tdm_sck_audio_auxpll.overlay new file mode 100644 index 000000000000..92ea4373f57d --- /dev/null +++ b/tests/drivers/i2s/i2s_mclk/boards/tdm_sck_audio_auxpll.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&tdm { + sck-clock-source = "ACLK"; +}; + +&audio_auxpll { + status = "okay"; +}; diff --git a/tests/drivers/i2s/i2s_mclk/testcase.yaml b/tests/drivers/i2s/i2s_mclk/testcase.yaml index 8fc4c701b544..0671dddb31bd 100644 --- a/tests/drivers/i2s/i2s_mclk/testcase.yaml +++ b/tests/drivers/i2s/i2s_mclk/testcase.yaml @@ -17,8 +17,10 @@ tests: - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf7120pdk/nrf7120/cpuapp integration_platforms: - nrf54lm20dk/nrf54lm20a/cpuapp + drivers.i2s.i2s_mclk.gpio_loopback.2ch.54h: harness_config: fixture: i2s_loopback @@ -27,6 +29,17 @@ tests: integration_platforms: - nrf54h20dk/nrf54h20/cpuapp + drivers.i2s.i2s_mclk.gpio_loopback.4ch: + harness_config: + fixture: gpio_loopback + extra_args: + - CONFIG_I2S_TEST_NUMBER_OF_CHANNELS=4 + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf7120pdk/nrf7120/cpuapp + integration_platforms: + - nrf54lm20dk/nrf54lm20a/cpuapp + drivers.i2s.i2s_mclk.gpio_loopback.4ch.54h: harness_config: fixture: i2s_loopback @@ -37,13 +50,16 @@ tests: integration_platforms: - nrf54h20dk/nrf54h20/cpuapp - drivers.i2s.i2s_mclk.gpio_loopback.4ch.54lm: + drivers.i2s.i2s_mclk.gpio_loopback.8ch: harness_config: fixture: gpio_loopback extra_args: - - CONFIG_I2S_TEST_NUMBER_OF_CHANNELS=4 + - CONFIG_I2S_TEST_NUMBER_OF_CHANNELS=8 platform_allow: - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf7120pdk/nrf7120/cpuapp + integration_platforms: + - nrf54lm20dk/nrf54lm20a/cpuapp drivers.i2s.i2s_mclk.gpio_loopback.8ch.54h: harness_config: @@ -55,25 +71,27 @@ tests: integration_platforms: - nrf54h20dk/nrf54h20/cpuapp - drivers.i2s.i2s_mclk.gpio_loopback.8ch.54lm: + drivers.i2s.i2s_mclk.gpio_loopback.2ch.aclk_sck: harness_config: fixture: gpio_loopback - extra_args: - - CONFIG_I2S_TEST_NUMBER_OF_CHANNELS=8 platform_allow: - - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf7120pdk/nrf7120/cpuapp + integration_platforms: + - nrf7120pdk/nrf7120/cpuapp + extra_args: + - EXTRA_DTC_OVERLAY_FILE="boards/tdm_sck_audio_auxpll.overlay" - drivers.i2s.i2s_mclk.gpio_loopback.2ch.54h.aclk_sck: + drivers.i2s.i2s_mclk.gpio_loopback.2ch.aclk_sck.54h: harness_config: fixture: i2s_loopback - extra_args: - - EXTRA_DTC_OVERLAY_FILE="boards/tdm_sck_audiopll.overlay" platform_allow: - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf54h20dk/nrf54h20/cpuapp + extra_args: + - EXTRA_DTC_OVERLAY_FILE="boards/tdm_sck_audiopll.overlay" - drivers.i2s.i2s_mclk.gpio_loopback.2ch.54h.aclk_mck: + drivers.i2s.i2s_mclk.gpio_loopback.2ch.aclk_mck.54h: harness_config: fixture: i2s_loopback extra_args: @@ -83,12 +101,23 @@ tests: integration_platforms: - nrf54h20dk/nrf54h20/cpuapp - drivers.i2s.i2s_mclk.gpio_loopback.2ch.54h.aclk_mck_sck: + drivers.i2s.i2s_mclk.gpio_loopback.2ch.aclk_mck_sck: harness_config: - fixture: i2s_loopback + fixture: gpio_loopback + platform_allow: + - nrf7120pdk/nrf7120/cpuapp + integration_platforms: + - nrf7120pdk/nrf7120/cpuapp extra_args: - - EXTRA_DTC_OVERLAY_FILE="boards/tdm_mck_audiopll.overlay boards/tdm_sck_audiopll.overlay" + - EXTRA_DTC_OVERLAY_FILE="boards/tdm_mck_audio_auxpll.overlay + boards/tdm_sck_audio_auxpll.overlay" + + drivers.i2s.i2s_mclk.gpio_loopback.2ch.aclk_mck_sck.54h: + harness_config: + fixture: i2s_loopback platform_allow: - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf54h20dk/nrf54h20/cpuapp + extra_args: + - EXTRA_DTC_OVERLAY_FILE="boards/tdm_mck_audiopll.overlay boards/tdm_sck_audiopll.overlay" From c071ed6f7e01068302e21785899b14959daf4be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Thu, 4 Dec 2025 12:30:56 +0100 Subject: [PATCH 132/155] all: nrfx_gppi: Fix parameter misuse in nrfx_gppi_ep_attach MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix all places where order of arguments in nrfx_gppi_ep_attach was wrong. Signed-off-by: Krzysztof Chruściński --- .../src/controller_time_nrf52.c | 2 +- .../src/controller_time_nrf53_app.c | 2 +- .../iso_time_sync/src/controller_time_nrf52.c | 2 +- .../src/controller_time_nrf53_app.c | 2 +- .../peripheral/radio_test/src/radio_test.c | 22 +++++++++---------- subsys/debug/cpu_load/cpu_load.c | 2 +- .../pin_debug/mpsl_pin_debug_radio_core.c | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/samples/bluetooth/conn_time_sync/src/controller_time_nrf52.c b/samples/bluetooth/conn_time_sync/src/controller_time_nrf52.c index efb24f384803..d1a6f386ce82 100644 --- a/samples/bluetooth/conn_time_sync/src/controller_time_nrf52.c +++ b/samples/bluetooth/conn_time_sync/src/controller_time_nrf52.c @@ -182,7 +182,7 @@ int config_egu_trigger_on_rtc_and_timer_match(void) printk("Failed allocating for RTC match\n"); return ret; } - (void)nrfx_gppi_ep_attach(ppi_on_timer_match, nrfx_gppi_group_task_dis_addr(group)); + (void)nrfx_gppi_ep_attach(nrfx_gppi_group_task_dis_addr(group), ppi_on_timer_match); return 0; } diff --git a/samples/bluetooth/conn_time_sync/src/controller_time_nrf53_app.c b/samples/bluetooth/conn_time_sync/src/controller_time_nrf53_app.c index f363b7423cad..e5ef4d7b63a9 100644 --- a/samples/bluetooth/conn_time_sync/src/controller_time_nrf53_app.c +++ b/samples/bluetooth/conn_time_sync/src/controller_time_nrf53_app.c @@ -153,7 +153,7 @@ int config_egu_trigger_on_rtc_and_timer_match(void) printk("Failed allocating for RTC match\n"); return ret; } - (void)nrfx_gppi_ep_attach(ppi_on_timer_match, nrfx_gppi_group_task_dis_addr(group)); + (void)nrfx_gppi_ep_attach(nrfx_gppi_group_task_dis_addr(group), ppi_on_timer_match); return 0; } diff --git a/samples/bluetooth/iso_time_sync/src/controller_time_nrf52.c b/samples/bluetooth/iso_time_sync/src/controller_time_nrf52.c index e0535c975d2f..27d5b84c2748 100644 --- a/samples/bluetooth/iso_time_sync/src/controller_time_nrf52.c +++ b/samples/bluetooth/iso_time_sync/src/controller_time_nrf52.c @@ -181,7 +181,7 @@ int config_egu_trigger_on_rtc_and_timer_match(void) printk("Failed allocating for RTC match\n"); return ret; } - (void)nrfx_gppi_ep_attach(ppi_on_timer_match, nrfx_gppi_group_task_dis_addr(group)); + (void)nrfx_gppi_ep_attach(nrfx_gppi_group_task_dis_addr(group), ppi_on_timer_match); return 0; } diff --git a/samples/bluetooth/iso_time_sync/src/controller_time_nrf53_app.c b/samples/bluetooth/iso_time_sync/src/controller_time_nrf53_app.c index 49f4c3d9004c..92039212a753 100644 --- a/samples/bluetooth/iso_time_sync/src/controller_time_nrf53_app.c +++ b/samples/bluetooth/iso_time_sync/src/controller_time_nrf53_app.c @@ -154,7 +154,7 @@ int config_egu_trigger_on_rtc_and_timer_match(void) printk("Failed allocating for RTC match\n"); return ret; } - (void)nrfx_gppi_ep_attach(ppi_on_timer_match, nrfx_gppi_group_task_dis_addr(group)); + (void)nrfx_gppi_ep_attach(nrfx_gppi_group_task_dis_addr(group), ppi_on_timer_match); return 0; } diff --git a/samples/peripheral/radio_test/src/radio_test.c b/samples/peripheral/radio_test/src/radio_test.c index dd0687e78135..d3981947ddc2 100644 --- a/samples/peripheral/radio_test/src/radio_test.c +++ b/samples/peripheral/radio_test/src/radio_test.c @@ -452,15 +452,15 @@ static void radio_ppi_config(bool rx) { endpoints_clear(); - nrfx_gppi_ep_attach(ppi_radio_start, - nrf_egu_event_address_get(RADIO_TEST_EGU, RADIO_TEST_EGU_EVENT)); - nrfx_gppi_ep_attach(ppi_radio_start, - nrf_radio_task_address_get(NRF_RADIO, - rx ? NRF_RADIO_TASK_RXEN : NRF_RADIO_TASK_TXEN)); + nrfx_gppi_ep_attach(nrf_egu_event_address_get(RADIO_TEST_EGU, RADIO_TEST_EGU_EVENT), + ppi_radio_start); + nrfx_gppi_ep_attach(nrf_radio_task_address_get(NRF_RADIO, + rx ? NRF_RADIO_TASK_RXEN : NRF_RADIO_TASK_TXEN), + ppi_radio_start); atomic_set_bit(&endpoint_state, (rx ? ENDPOINT_EGU_RADIO_RX : ENDPOINT_EGU_RADIO_TX)); - nrfx_gppi_ep_attach(ppi_radio_start, - nrf_timer_task_address_get(timer.p_reg, NRF_TIMER_TASK_START)); + nrfx_gppi_ep_attach(nrf_timer_task_address_get(timer.p_reg, NRF_TIMER_TASK_START), + ppi_radio_start); atomic_set_bit(&endpoint_state, ENDPOINT_FORK_EGU_TIMER); nrfx_gppi_conn_enable(ppi_radio_start); @@ -472,10 +472,10 @@ static void radio_ppi_tx_reconfigure(void) endpoints_clear(); - nrfx_gppi_ep_attach(ppi_radio_start, - nrf_timer_event_address_get(timer.p_reg, NRF_TIMER_EVENT_COMPARE1)); - nrfx_gppi_ep_attach(ppi_radio_start, - nrf_radio_task_address_get(NRF_RADIO, NRF_RADIO_TASK_TXEN)); + nrfx_gppi_ep_attach(nrf_timer_event_address_get(timer.p_reg, NRF_TIMER_EVENT_COMPARE1), + ppi_radio_start); + nrfx_gppi_ep_attach(nrf_radio_task_address_get(NRF_RADIO, NRF_RADIO_TASK_TXEN), + ppi_radio_start); atomic_set_bit(&endpoint_state, ENDPOINT_TIMER_RADIO_TX); nrfx_gppi_conn_enable(ppi_radio_start); diff --git a/subsys/debug/cpu_load/cpu_load.c b/subsys/debug/cpu_load/cpu_load.c index 0178553ebf2c..8649424fa537 100644 --- a/subsys/debug/cpu_load/cpu_load.c +++ b/subsys/debug/cpu_load/cpu_load.c @@ -83,7 +83,7 @@ static int ppi_setup(uint32_t eep, uint32_t tep) if (err >= 0) { /* It works only on single domain DPPI. */ handle = (nrfx_gppi_handle_t)err; - nrfx_gppi_ep_attach(handle, tep); + nrfx_gppi_ep_attach(tep, handle); return 0; } diff --git a/subsys/mpsl/pin_debug/mpsl_pin_debug_radio_core.c b/subsys/mpsl/pin_debug/mpsl_pin_debug_radio_core.c index 21ab37940f0e..ff5a61bf17d3 100644 --- a/subsys/mpsl/pin_debug/mpsl_pin_debug_radio_core.c +++ b/subsys/mpsl/pin_debug/mpsl_pin_debug_radio_core.c @@ -49,7 +49,7 @@ static int m_ppi_config(void) #endif for (size_t i = 0; ARRAY_SIZE(tep); i++) { #if defined(DPPI_PRESENT) - nrfx_gppi_ep_attach(handle[i], tep[i]); + nrfx_gppi_ep_attach(tep[i], handle[i]); #else int err = nrfx_gppi_conn_alloc(eep[i], tep[i], &handle[i]); From 29f2392440292c660155ea65de7f8480d51b120b Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Wed, 3 Dec 2025 15:39:24 +0100 Subject: [PATCH 133/155] applications: nrf_desktop: Update HID report rate measuring doc Change adds information about using MCUboot RAM load mode to improve performance of the application image. Jira: NCSDK-35515 Signed-off-by: Marek Pieta Signed-off-by: Pekka Niskanen --- applications/nrf_desktop/description.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/applications/nrf_desktop/description.rst b/applications/nrf_desktop/description.rst index 8678625263aa..9b7e8548f85d 100644 --- a/applications/nrf_desktop/description.rst +++ b/applications/nrf_desktop/description.rst @@ -1131,6 +1131,11 @@ Building information Use the configuration with the ``release`` file suffix for the HID report rate measurement. Debug features, such as logging or assertions, decrease the application performance. +.. note:: + You can run the application code from RAM instead of NVM to improve performance as code execution from the RAM is generally faster than from the NVM. + You can configure MCUboot to use the RAM load mode to run the whole application image from RAM. + For details, see the :ref:`nrf_desktop_configuring_mcuboot_bootloader_ram_load` section. + Use the nRF Desktop configuration that acts as a HID mouse reference design for the report rate measurement, as the motion data polling is synchronized with sending HID reports. Make sure your chosen motion data source will generate movement in each poll interval. From 4f99b6cb23caf1143bb3ef25050bc78a2e93676d Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Thu, 4 Dec 2025 16:31:34 +0000 Subject: [PATCH 134/155] manifest: Update sdk-nrfxlib revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-nrfxlib/pull/1954 Signed-off-by: Nordic Builder --- west.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/west.yml b/west.yml index ffc612a8f708..254f4e20846a 100644 --- a/west.yml +++ b/west.yml @@ -143,7 +143,7 @@ manifest: - name: nrfxlib repo-path: sdk-nrfxlib path: nrfxlib - revision: 62ac75ca9a03481b92850fc43f8d04a5a7dea2c7 + revision: 89a9dd32358bc2ca846e2f47fa7cce60d0688ccb - name: trusted-firmware-m repo-path: sdk-trusted-firmware-m path: modules/tee/tf-m/trusted-firmware-m @@ -181,7 +181,7 @@ manifest: # Only for internal Nordic development repo-path: dragoon.git remote: dragoon - revision: cf419408648ce1eee1fbea1d4b6a8366f9bcf737 + revision: d2500b737245346047ffbfe925048a3f1a5dd8aa groups: - dragoon - name: cjson From 1ddde354b13178e9107e694ba8a3c0cc558db2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Wed, 26 Nov 2025 15:02:27 +0100 Subject: [PATCH 135/155] tests: drivers: i2s: Test different length transmission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add test that verifies I2S/TDM communication (single instance with GPIO loopback from DOUT to DIN) at different configuration. Verify: - mono / stereo configuration; - 8/16/32 bit word size; - 8/16/24 bytes long data buffer. Signed-off-by: Sebastian Głąb --- scripts/ci/license_allow_list.yaml | 1 + tests/drivers/i2s/i2s_buffer/CMakeLists.txt | 13 + tests/drivers/i2s/i2s_buffer/Kconfig | 43 + .../boards/nrf52840dk_nrf52840.conf | 1 + .../boards/nrf52840dk_nrf52840.overlay | 32 + .../boards/nrf5340dk_nrf5340_cpuapp.overlay | 36 + .../nrf5340dk_nrf5340_cpuapp_aclk.overlay | 9 + .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 33 + .../boards/nrf54l15dk_nrf54l15_cpuapp.overlay | 32 + .../nrf54lm20dk_nrf54lm20a_cpuapp.overlay | 32 + tests/drivers/i2s/i2s_buffer/prj.conf | 4 + tests/drivers/i2s/i2s_buffer/src/i2s_buffer.c | 759 ++++++++++++++++++ tests/drivers/i2s/i2s_buffer/testcase.yaml | 104 +++ 13 files changed, 1099 insertions(+) create mode 100644 tests/drivers/i2s/i2s_buffer/CMakeLists.txt create mode 100644 tests/drivers/i2s/i2s_buffer/Kconfig create mode 100644 tests/drivers/i2s/i2s_buffer/boards/nrf52840dk_nrf52840.conf create mode 100644 tests/drivers/i2s/i2s_buffer/boards/nrf52840dk_nrf52840.overlay create mode 100644 tests/drivers/i2s/i2s_buffer/boards/nrf5340dk_nrf5340_cpuapp.overlay create mode 100644 tests/drivers/i2s/i2s_buffer/boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay create mode 100644 tests/drivers/i2s/i2s_buffer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/i2s/i2s_buffer/boards/nrf54l15dk_nrf54l15_cpuapp.overlay create mode 100644 tests/drivers/i2s/i2s_buffer/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay create mode 100644 tests/drivers/i2s/i2s_buffer/prj.conf create mode 100644 tests/drivers/i2s/i2s_buffer/src/i2s_buffer.c create mode 100644 tests/drivers/i2s/i2s_buffer/testcase.yaml diff --git a/scripts/ci/license_allow_list.yaml b/scripts/ci/license_allow_list.yaml index dd0dfe3f2bff..3e5e24a375de 100644 --- a/scripts/ci/license_allow_list.yaml +++ b/scripts/ci/license_allow_list.yaml @@ -49,6 +49,7 @@ Apache-2.0: | ^nrf/modules/openthread/ ^nrf/samples/net/http_server/src/main.c ^nrf/tests/benchmarks/kernel_freq_change/src/kernel_context.c + ^nrf/tests/drivers/i2s/i2s_buffer/src/i2s_buffer.c ^nrf/tests/subsys/suit/common/tls_config/user-tls-conf.h ^nrf/subsys/settings/ ^nrf/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c diff --git a/tests/drivers/i2s/i2s_buffer/CMakeLists.txt b/tests/drivers/i2s/i2s_buffer/CMakeLists.txt new file mode 100644 index 000000000000..987c2cb463a9 --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(i2s_buffer) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/i2s/i2s_buffer/Kconfig b/tests/drivers/i2s/i2s_buffer/Kconfig new file mode 100644 index 000000000000..70733e705d42 --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/Kconfig @@ -0,0 +1,43 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +mainmenu "I2S Buffer Test" + +config I2S_TEST_ALLOWED_DATA_OFFSET + int "Allowed offset in received data" + default 2 if DT_HAS_NORDIC_NRF_I2S_ENABLED + default 0 + help + Maximum allowed offset between sent and received samples. + Value is in "full" audio samples. + Offset of 1 "full" audio sample is: + - 1 byte for mono 8 bit word size. + - 2 bytes for stereo 8 bit word size. + - 2 bytes for mono 16 bit word size. + - 4 bytes for stereo 16 bit word size. + - 4 bytes for mono 32 bit word size. + - 8 bytes for stereo 32 bit word size. + +config I2S_TEST_BUFFER_SIZE + int "Number of bytes send in one transaction" + default 16 + help + Value has to be a multiple of 8 bytes. Test supports up to 32 bytes. + +config I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED + bool "32 bit word size is not supported by the driver" + help + When set to 'y' testing 32 bit word size is skipped. + +config I2S_TEST_BLOCK_SIZE_8_UNSUPPORTED + bool "Block_size of 8 bytes is not supported by the driver" + default y if DT_HAS_NORDIC_NRF_TDM_ENABLED + help + When set to 'y', test that use 8 bytes of data check if + i2s_configure() returns -EINVAL. + When set to 'n', test will do the I2S transmission. + +source "Kconfig.zephyr" diff --git a/tests/drivers/i2s/i2s_buffer/boards/nrf52840dk_nrf52840.conf b/tests/drivers/i2s/i2s_buffer/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 000000000000..8ed6ee234db2 --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1 @@ +CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED=y diff --git a/tests/drivers/i2s/i2s_buffer/boards/nrf52840dk_nrf52840.overlay b/tests/drivers/i2s/i2s_buffer/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 000000000000..a1e700fe9f6e --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Test requires GPIO loopback: + * P1.01 - P1.02 + */ + +/ { + aliases { + i2s-node0 = &i2s0; + }; +}; + +&pinctrl { + i2s0_default_alt: i2s0_default_alt { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&i2s0 { + status = "okay"; + pinctrl-0 = <&i2s0_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/i2s/i2s_buffer/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/drivers/i2s/i2s_buffer/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 000000000000..25599f281af7 --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Test requires GPIO loopback: + * P0.04 - P0.05 + */ + +/ { + aliases { + i2s-node0 = &i2s0; + }; +}; + +&pinctrl { + i2s0_default_alt: i2s0_default_alt { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&uart1 { + status = "disabled"; +}; + +&i2s0 { + status = "okay"; + pinctrl-0 = <&i2s0_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/i2s/i2s_buffer/boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay b/tests/drivers/i2s/i2s_buffer/boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay new file mode 100644 index 000000000000..e262ca8d8a87 --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay @@ -0,0 +1,9 @@ +/* Drive i2s peripheral from ACLK. */ + +&clock { + hfclkaudio-frequency = <11289600>; +}; + +&i2s0 { + clock-source = "ACLK"; +}; diff --git a/tests/drivers/i2s/i2s_buffer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/i2s/i2s_buffer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..4feb84e02e6a --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Test requires GPIO loopback: + * P1.04 - P1.05 + */ + +/ { + aliases { + i2s-node0 = &tdm130; + }; +}; + +&pinctrl { + tdm130_default_alt: tdm130_default_alt { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&tdm130 { + status = "okay"; + pinctrl-0 = <&tdm130_default_alt>; + pinctrl-names = "default"; + memory-regions = <&cpuapp_dma_region>; +}; diff --git a/tests/drivers/i2s/i2s_buffer/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/i2s/i2s_buffer/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 000000000000..f4ab0bef2852 --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Test requires GPIO loopback: + * P1.08 - P1.09 + */ + +/ { + aliases { + i2s-node0 = &i2s20; + }; +}; + +&pinctrl { + i2s20_default_alt: i2s20_default_alt { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&i2s20 { + status = "okay"; + pinctrl-0 = <&i2s20_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/i2s/i2s_buffer/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/i2s/i2s_buffer/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 000000000000..98e6b7e76a50 --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* Test requires GPIO loopback: + * P1.30 - P1.31 + */ + +/ { + aliases { + i2s-node0 = &tdm; + }; +}; + +&pinctrl { + tdm_default_alt: tdm_default_alt { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&tdm { + status = "okay"; + pinctrl-0 = <&tdm_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/i2s/i2s_buffer/prj.conf b/tests/drivers/i2s/i2s_buffer/prj.conf new file mode 100644 index 000000000000..b6870d663559 --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/prj.conf @@ -0,0 +1,4 @@ +CONFIG_I2S=y +CONFIG_ZTEST=y + +CONFIG_SPEED_OPTIMIZATIONS=y diff --git a/tests/drivers/i2s/i2s_buffer/src/i2s_buffer.c b/tests/drivers/i2s/i2s_buffer/src/i2s_buffer.c new file mode 100644 index 000000000000..dd9609e4faf8 --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/src/i2s_buffer.c @@ -0,0 +1,759 @@ +/* + * Copyright (c) 2017 comsuisse AG + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define I2S_DEV_NODE DT_ALIAS(i2s_node0) + +#define BLOCK_SIZE CONFIG_I2S_TEST_BUFFER_SIZE + +#define NUM_BLOCKS 4 +#define TIMEOUT 2000 + +#ifdef CONFIG_NOCACHE_MEMORY + #define MEM_SLAB_CACHE_ATTR __nocache +#else + #define MEM_SLAB_CACHE_ATTR +#endif /* CONFIG_NOCACHE_MEMORY */ + +/* Random data with no meaning. */ +static uint8_t data[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x10, 0x20, 0x40, 0x80, 0xAA, 0x55, 0x55, 0xAA, + 0xfe, 0xef, 0xfe, 0xee, 0x00, 0x01, 0x02, 0x04, + 0x0e, 0x12, 0x01, 0x80, 0x81, 0x18, 0xAA, 0x55, +}; + +/* + * NUM_BLOCKS is the number of blocks used by the test. Some of the drivers, + * permanently keep ownership of a few RX buffers. Add a two more + * RX blocks to satisfy this requirement + */ +static char MEM_SLAB_CACHE_ATTR __aligned(WB_UP(32)) + _k_mem_slab_buf_rx_0_mem_slab[(NUM_BLOCKS + 2) * WB_UP(BLOCK_SIZE)]; +STRUCT_SECTION_ITERABLE(k_mem_slab, rx_0_mem_slab) = + Z_MEM_SLAB_INITIALIZER(rx_0_mem_slab, _k_mem_slab_buf_rx_0_mem_slab, + WB_UP(BLOCK_SIZE), NUM_BLOCKS + 2); + +static char MEM_SLAB_CACHE_ATTR __aligned(WB_UP(32)) + _k_mem_slab_buf_tx_0_mem_slab[(NUM_BLOCKS) * WB_UP(BLOCK_SIZE)]; +STRUCT_SECTION_ITERABLE(k_mem_slab, tx_0_mem_slab) = + Z_MEM_SLAB_INITIALIZER(tx_0_mem_slab, _k_mem_slab_buf_tx_0_mem_slab, + WB_UP(BLOCK_SIZE), NUM_BLOCKS); + +static const struct device *dev_i2s = DEVICE_DT_GET_OR_NULL(I2S_DEV_NODE); + +static const struct i2s_config default_i2s_cfg = { + .word_size = 16U, + .channels = 2U, + .format = I2S_FMT_DATA_FORMAT_I2S, + .frame_clk_freq = 44100U, + .block_size = BLOCK_SIZE, + .timeout = TIMEOUT, + .options = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER, + .mem_slab = &tx_0_mem_slab, +}; + +#if (CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET > 0) +/* Data offset may differ from test to test if + * number of audio channels or word size has changed. + */ +static int offset; +#endif + +static void fill_buf(uint8_t *tx_block, uint8_t val) +{ + for (int i = 0; i < BLOCK_SIZE; i++) { + tx_block[i] = data[i] + val; + } +} + +static int verify_buf(uint8_t *rx_block, uint8_t val, uint32_t offset_in_bytes) +{ + int sample_no = BLOCK_SIZE; + bool data_match = true; + +#if (CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET > 0) + /* Offset -1 means that offset has to be detected. */ + if (offset < 0) { + do { + ++offset; + if (offset > offset_in_bytes) { + TC_PRINT("Allowed data offset exceeded\n"); + return -TC_FAIL; + } + } while (rx_block[offset] != data[0] + val); + + TC_PRINT("Using data offset: %d bytes\n", offset); + } + + rx_block += offset; + sample_no -= offset; +#else + ARG_UNUSED(offset_in_bytes); +#endif + + for (int i = 0; i < sample_no; i++) { + if (rx_block[i] != (uint8_t) (data[i] + val)) { + data_match = false; + break; + } + } + + /* Workaround for issue resulting from limited performance when buffer is small. + * When new write buffer is not delivered on time, previous buffer is retransmitted. + * + * (In the test, each buffer is contens of `data` with each byte incresed by `val`. + * `val` is equal to TX block number = 0, 1, 2,...) + */ + if (!data_match) { + TC_PRINT("%u RX block: Compare with data sent earlier (workaround).\n", val); + data_match = true; + for (int i = 0; i < sample_no; i++) { + if (rx_block[i] != (uint8_t) (data[i] + val - 1)) { + data_match = false; + break; + } + } + } + + if (!data_match) { + TC_PRINT("Index: Expected | Received\n"); + for (int i = 0; i < sample_no; i++) { + TC_PRINT("%u: 0x%02X | 0x%02X\n", + i, (uint8_t) (data[i] + val), rx_block[i]); + } + return -TC_FAIL; + } + + return TC_PASS; +} + +static int configure_stream(const struct device *dev, enum i2s_dir dir, + struct i2s_config *i2s_cfg) +{ + int ret; + + if (dir == I2S_DIR_TX) { + /* Configure the Transmit port as Master */ + i2s_cfg->options = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER; + } else if (dir == I2S_DIR_RX) { + /* Configure the Receive port as Slave */ + i2s_cfg->options = I2S_OPT_FRAME_CLK_SLAVE | I2S_OPT_BIT_CLK_SLAVE; + } else { /* dir == I2S_DIR_BOTH */ + i2s_cfg->options = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER; + } + + if (dir == I2S_DIR_TX || dir == I2S_DIR_BOTH) { + i2s_cfg->mem_slab = &tx_0_mem_slab; + ret = i2s_configure(dev, I2S_DIR_TX, i2s_cfg); + if (ret < 0) { + TC_PRINT("Failed to configure I2S TX stream (%d)\n", ret); + return ret; + } + } + + if (dir == I2S_DIR_RX || dir == I2S_DIR_BOTH) { + i2s_cfg->mem_slab = &rx_0_mem_slab; + ret = i2s_configure(dev, I2S_DIR_RX, i2s_cfg); + if (ret < 0) { + TC_PRINT("Failed to configure I2S RX stream (%d)\n", ret); + return ret; + } + } + + return TC_PASS; +} + +static void i2s_dir_both_transfer_long(struct i2s_config *i2s_cfg, uint32_t offset_in_bytes) +{ + void *rx_block[NUM_BLOCKS]; + void *tx_block[NUM_BLOCKS]; + size_t rx_size; + int tx_idx; + int rx_idx = 0; + int num_verified; + int ret; + + /* Configure I2S Dir Both transfer. */ + ret = configure_stream(dev_i2s, I2S_DIR_BOTH, i2s_cfg); +#if defined(CONFIG_I2S_TEST_BLOCK_SIZE_8_UNSUPPORTED) && (CONFIG_I2S_TEST_BUFFER_SIZE == 8) + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); + TC_PRINT("No communication check due to unsupported buffer size.\n"); + return; +#else + zassert_equal(ret, TC_PASS); +#endif + + /* Prepare TX data blocks */ + for (tx_idx = 0; tx_idx < NUM_BLOCKS; tx_idx++) { + ret = k_mem_slab_alloc(&tx_0_mem_slab, &tx_block[tx_idx], K_FOREVER); + zassert_equal(ret, 0); + fill_buf((uint8_t *)tx_block[tx_idx], tx_idx); + } + + tx_idx = 0; + + /* Prefill TX queue */ + ret = i2s_write(dev_i2s, tx_block[tx_idx++], BLOCK_SIZE); + zassert_equal(ret, 0); + + ret = i2s_write(dev_i2s, tx_block[tx_idx++], BLOCK_SIZE); + zassert_equal(ret, 0); + + ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START); + zassert_equal(ret, 0, "RX/TX START trigger failed\n"); + + while (tx_idx < NUM_BLOCKS) { + ret = i2s_write(dev_i2s, tx_block[tx_idx++], BLOCK_SIZE); + zassert_equal(ret, 0); + + ret = i2s_read(dev_i2s, &rx_block[rx_idx++], &rx_size); + zassert_equal(ret, 0, "Got unexpected %d", ret); + zassert_equal(rx_size, BLOCK_SIZE); + } + + /* All data written, drain TX queue and stop both streams. */ + ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN); + zassert_equal(ret, 0, "RX/TX DRAIN trigger failed"); + + ret = i2s_read(dev_i2s, &rx_block[rx_idx++], &rx_size); + zassert_equal(ret, 0); + zassert_equal(rx_size, BLOCK_SIZE); + + ret = i2s_read(dev_i2s, &rx_block[rx_idx++], &rx_size); + zassert_equal(ret, 0); + zassert_equal(rx_size, BLOCK_SIZE); + + TC_PRINT("%d TX blocks sent\n", tx_idx); + TC_PRINT("%d RX blocks received\n", rx_idx); + + /* Verify received data */ + num_verified = 0; + for (rx_idx = 0; rx_idx < NUM_BLOCKS; rx_idx++) { + ret = verify_buf((uint8_t *)rx_block[rx_idx], rx_idx, offset_in_bytes); + if (ret != 0) { + TC_PRINT("Validation failed for %d RX block\n", rx_idx); + } else { + num_verified++; + } + k_mem_slab_free(&rx_0_mem_slab, rx_block[rx_idx]); + } + zassert_equal(num_verified, NUM_BLOCKS, "Invalid RX blocks received"); +} + +static uint32_t check_test_configuration(struct i2s_config *i2s_cfg) +{ + /* Convert max allowed offset in audio samples to bytes of data. */ + uint32_t offset_in_bytes = CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET * i2s_cfg->channels + * (i2s_cfg->word_size / 8); + + /* Skip test if allowed offset is same or larger than the buffer. */ + if (offset_in_bytes >= CONFIG_I2S_TEST_BUFFER_SIZE) { + TC_PRINT("Allowed data offset is to big for this test.\n"); + ztest_test_skip(); + } + + return offset_in_bytes; +} + +/* + * 1 audio channel, 8 bit word + */ +ZTEST(i2s_buffer, test_1ch_08bit_at_08000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 8U; + i2s_cfg.frame_clk_freq = 8000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_08bit_at_16000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 8U; + i2s_cfg.frame_clk_freq = 16000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_08bit_at_32000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 8U; + i2s_cfg.frame_clk_freq = 32000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_08bit_at_44100) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 8U; + i2s_cfg.frame_clk_freq = 44100; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_08bit_at_48000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 8U; + i2s_cfg.frame_clk_freq = 48000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + + +/* + * 2 audio channels, 8 bit word + */ +ZTEST(i2s_buffer, test_2ch_08bit_at_08000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 8U; + i2s_cfg.frame_clk_freq = 8000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_08bit_at_16000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 8U; + i2s_cfg.frame_clk_freq = 16000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_08bit_at_32000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 8U; + i2s_cfg.frame_clk_freq = 32000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_08bit_at_44100) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 8U; + i2s_cfg.frame_clk_freq = 44100; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_08bit_at_48000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 8U; + i2s_cfg.frame_clk_freq = 48000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + + +/* + * 1 audio channel, 16 bit word + */ +ZTEST(i2s_buffer, test_1ch_16bit_at_08000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 16U; + i2s_cfg.frame_clk_freq = 8000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_16bit_at_16000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 16U; + i2s_cfg.frame_clk_freq = 16000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_16bit_at_32000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 16U; + i2s_cfg.frame_clk_freq = 32000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_16bit_at_44100) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 16U; + i2s_cfg.frame_clk_freq = 44100; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_16bit_at_48000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 16U; + i2s_cfg.frame_clk_freq = 48000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + + +/* + * 2 audio channels, 16 bit word + */ +ZTEST(i2s_buffer, test_2ch_16bit_at_08000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 16U; + i2s_cfg.frame_clk_freq = 8000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_16bit_at_16000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 16U; + i2s_cfg.frame_clk_freq = 16000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_16bit_at_32000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 16U; + i2s_cfg.frame_clk_freq = 32000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_16bit_at_44100) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 16U; + i2s_cfg.frame_clk_freq = 44100; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_16bit_at_48000) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 16U; + i2s_cfg.frame_clk_freq = 48000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + + +/* + * 1 audio channel, 32 bit word + */ +ZTEST(i2s_buffer, test_1ch_32bit_at_08000) +{ + Z_TEST_SKIP_IFDEF(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED); + + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 32U; + i2s_cfg.frame_clk_freq = 8000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_32bit_at_16000) +{ + Z_TEST_SKIP_IFDEF(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED); + + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 32U; + i2s_cfg.frame_clk_freq = 16000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_32bit_at_32000) +{ + Z_TEST_SKIP_IFDEF(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED); + + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 32U; + i2s_cfg.frame_clk_freq = 32000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_32bit_at_44100) +{ + Z_TEST_SKIP_IFDEF(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED); + + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 32U; + i2s_cfg.frame_clk_freq = 44100; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_1ch_32bit_at_48000) +{ + Z_TEST_SKIP_IFDEF(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED); + + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 1U; + i2s_cfg.word_size = 32U; + i2s_cfg.frame_clk_freq = 48000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + + +/* + * 2 audio channels, 32 bit word + */ +ZTEST(i2s_buffer, test_2ch_32bit_at_08000) +{ + Z_TEST_SKIP_IFDEF(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED); + + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 32U; + i2s_cfg.frame_clk_freq = 8000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_32bit_at_16000) +{ + Z_TEST_SKIP_IFDEF(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED); + + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 32U; + i2s_cfg.frame_clk_freq = 16000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_32bit_at_32000) +{ + Z_TEST_SKIP_IFDEF(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED); + + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 32U; + i2s_cfg.frame_clk_freq = 32000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_32bit_at_44100) +{ + Z_TEST_SKIP_IFDEF(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED); + + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 32U; + i2s_cfg.frame_clk_freq = 44100; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + +ZTEST(i2s_buffer, test_2ch_32bit_at_48000) +{ + Z_TEST_SKIP_IFDEF(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED); + + struct i2s_config i2s_cfg = default_i2s_cfg; + uint32_t offset_in_bytes; + + i2s_cfg.channels = 2U; + i2s_cfg.word_size = 32U; + i2s_cfg.frame_clk_freq = 48000; + + offset_in_bytes = check_test_configuration(&i2s_cfg); + + i2s_dir_both_transfer_long(&i2s_cfg, offset_in_bytes); +} + + +static void *suite_setup(void) +{ + TC_PRINT("I2S buffer size test on %s\n", CONFIG_BOARD_TARGET); + TC_PRINT("Testing I2S device %s\n", dev_i2s->name); + TC_PRINT("BUFFER_SIZE = %d\n", CONFIG_I2S_TEST_BUFFER_SIZE); + + /* Check I2S Device. */ + zassert_not_null(dev_i2s, "I2S device not found"); + zassert(device_is_ready(dev_i2s), "I2S device not ready"); + + TC_PRINT("===================================================================\n"); + + return 0; +} + +static void before(void *not_used) +{ + ARG_UNUSED(not_used); + +#if (CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET > 0) + /* Data offset may differ when test uses I2S + * with different configuration. + * Force offset callculation for every test. + */ + offset = -1; +#endif +} + +ZTEST_SUITE(i2s_buffer, NULL, suite_setup, before, NULL, NULL); diff --git a/tests/drivers/i2s/i2s_buffer/testcase.yaml b/tests/drivers/i2s/i2s_buffer/testcase.yaml new file mode 100644 index 000000000000..d1d2b3bb55fb --- /dev/null +++ b/tests/drivers/i2s/i2s_buffer/testcase.yaml @@ -0,0 +1,104 @@ +common: + tags: + - drivers + - i2s + - ci_tests_zephyr_drivers_i2s + depends_on: + - i2s + - gpio + harness: ztest + +tests: + # buffer of 8 bytes + drivers.i2s.i2s_buffer.8bytes: + harness_config: + fixture: gpio_loopback + extra_args: + - CONFIG_I2S_TEST_BUFFER_SIZE=8 + platform_allow: + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp + drivers.i2s.i2s_buffer.8bytes.aclk: + harness_config: + fixture: gpio_loopback + extra_args: + - EXTRA_DTC_OVERLAY_FILE="boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay" + - CONFIG_I2S_TEST_BUFFER_SIZE=8 + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: + - nrf5340dk/nrf5340/cpuapp + drivers.i2s.i2s_buffer.8bytes.nrf54h: + harness_config: + fixture: i2s_loopback + extra_args: + - CONFIG_I2S_TEST_BUFFER_SIZE=8 + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + + # buffer of 16 bytes + drivers.i2s.i2s_buffer.16bytes: + harness_config: + fixture: gpio_loopback + platform_allow: + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp + drivers.i2s.i2s_buffer.16bytes.aclk: + harness_config: + fixture: gpio_loopback + extra_args: + - EXTRA_DTC_OVERLAY_FILE="boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay" + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: + - nrf5340dk/nrf5340/cpuapp + drivers.i2s.i2s_buffer.16bytes.nrf54h: + harness_config: + fixture: i2s_loopback + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + + # buffer of 24 bytes + drivers.i2s.i2s_buffer.24bytes: + harness_config: + fixture: gpio_loopback + extra_args: + - CONFIG_I2S_TEST_BUFFER_SIZE=24 + platform_allow: + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp + drivers.i2s.i2s_buffer.24bytes.aclk: + harness_config: + fixture: gpio_loopback + extra_args: + - EXTRA_DTC_OVERLAY_FILE="boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay" + - CONFIG_I2S_TEST_BUFFER_SIZE=24 + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: + - nrf5340dk/nrf5340/cpuapp + drivers.i2s.i2s_buffer.24bytes.nrf54h: + harness_config: + fixture: i2s_loopback + extra_args: + - CONFIG_I2S_TEST_BUFFER_SIZE=24 + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp From 1ed975b9770697433edc789ab6618e841874724b Mon Sep 17 00:00:00 2001 From: Szymon Antkowiak Date: Thu, 4 Dec 2025 13:57:57 +0100 Subject: [PATCH 136/155] esb: fix fast switching causing retransmissions When both PTX and PRX where have fast switching enabled, PRX was sending ACK packet when PTX was still in RX ramp up. Now PTX completes RX ramp up earlier by shorting PHYEND to RXEN over DPPI, and radio interrupt triggers START instead of RXEN. Signed-off-by: Szymon Antkowiak --- subsys/esb/esb.c | 42 +++++++++++++++++++++++++++++------------- subsys/esb/esb_dppi.c | 8 ++++++++ 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/subsys/esb/esb.c b/subsys/esb/esb.c index 20d9eeb57e5c..4fea7351030b 100644 --- a/subsys/esb/esb.c +++ b/subsys/esb/esb.c @@ -90,8 +90,7 @@ LOG_MODULE_REGISTER(esb, CONFIG_ESB_LOG_LEVEL); NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | NRF_RADIO_SHORT_DISABLED_RSSISTOP_MASK) #else /* Devices without RSSISTOP task will stop RSSI measurement after specific period. */ -#define RADIO_SHORTS_FAST_SWITCHING_NO_RSSISTOP \ - (NRF_RADIO_SHORT_READY_START_MASK | NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK) +#define RADIO_SHORTS_FAST_SWITCHING_NO_RSSISTOP (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK) #define RADIO_SHORTS_NO_FAST_SWITCHING_NO_RSSISTOP \ (NRF_RADIO_SHORT_READY_START_MASK | ESB_SHORT_DISABLE_MASK | \ NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK) @@ -111,6 +110,14 @@ LOG_MODULE_REGISTER(esb, CONFIG_ESB_LOG_LEVEL); NRF_RADIO_SHORT_READY_START_MASK) #endif /* !defined(CONFIG_SOC_SERIES_NRF54LX) */ +/* Define empty shorts for nRF52 devices. These shorts are used only for fast switching. */ +#if !defined(RADIO_SHORTS_TXREADY_START_Msk) +#define NRF_RADIO_SHORT_TXREADY_START_MASK 0 +#endif +#if !defined(RADIO_SHORTS_RXREADY_START_Msk) +#define NRF_RADIO_SHORT_RXREADY_START_MASK 0 +#endif + /* Flag for changing radio channel. */ #define RF_CHANNEL_UPDATE_FLAG 0 @@ -1182,7 +1189,8 @@ static void start_tx_transaction(void) memcpy(pdu->data, current_payload->data, current_payload->length); if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common); + nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | + NRF_RADIO_SHORT_TXREADY_START_MASK)); nrf_radio_event_clear(NRF_RADIO, ESB_RADIO_EVENT_END); nrf_radio_int_enable(NRF_RADIO, ESB_RADIO_INT_END_MASK); } else { @@ -1210,7 +1218,8 @@ static void start_tx_transaction(void) /* Handling ack if noack is set to false or if selective auto ack is turned off */ if (ack) { if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common); + nrf_radio_shorts_set(NRF_RADIO, + (radio_shorts_common | NRF_RADIO_SHORT_TXREADY_START_MASK)); nrf_radio_event_clear(NRF_RADIO, ESB_RADIO_EVENT_END); nrf_radio_int_enable(NRF_RADIO, ESB_RADIO_INT_END_MASK); } else { @@ -1244,8 +1253,9 @@ static void start_tx_transaction(void) (esb_state == ESB_STATE_PTX_TX)); esb_state = ESB_STATE_PTX_TX; } else { - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common | - ESB_SHORT_DISABLE_MASK); + nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | + NRF_RADIO_SHORT_READY_START_MASK | + ESB_SHORT_DISABLE_MASK)); on_radio_disabled = on_radio_disabled_tx_noack; esb_state = ESB_STATE_PTX_TX; @@ -1384,8 +1394,9 @@ static void on_radio_disabled_tx(void) nrf_radio_packetptr_set(NRF_RADIO, rx_payload_buffer); if (fast_switching) { nrf_radio_int_disable(NRF_RADIO, ESB_RADIO_INT_END_MASK); - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | ESB_SHORT_DISABLE_MASK)); - nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_RXEN); + nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | ESB_SHORT_DISABLE_MASK | + NRF_RADIO_SHORT_RXREADY_START_MASK)); + nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_START); } on_radio_disabled = on_radio_disabled_tx_wait_for_ack; esb_state = ESB_STATE_PTX_RX_ACK; @@ -1456,7 +1467,8 @@ static void on_radio_disabled_tx_wait_for_ack(void) nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY); if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common); + nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | + NRF_RADIO_SHORT_TXREADY_START_MASK)); nrf_radio_event_clear(NRF_RADIO, ESB_RADIO_EVENT_END); nrf_radio_int_enable(NRF_RADIO, ESB_RADIO_INT_END_MASK); } else { @@ -1526,7 +1538,8 @@ static void start_rx_listening(void) on_radio_disabled = NULL; } else { if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common); + nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | + NRF_RADIO_SHORT_READY_START_MASK)); nrf_radio_event_clear(NRF_RADIO, ESB_RADIO_EVENT_END); nrf_radio_int_enable(NRF_RADIO, ESB_RADIO_INT_END_MASK); } else { @@ -1580,7 +1593,8 @@ static void clear_events_restart_rx(void) nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED); - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | NRF_RADIO_SHORT_DISABLED_TXEN_MASK)); + nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | NRF_RADIO_SHORT_READY_START_MASK | + NRF_RADIO_SHORT_DISABLED_TXEN_MASK)); esb_ppi_for_txrx_set(true, false); esb_fem_for_rx_set(); @@ -1688,7 +1702,8 @@ static void on_radio_disabled_rx(void) nrf_radio_packetptr_set(NRF_RADIO, tx_pdu); if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common); + nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | + NRF_RADIO_SHORT_READY_START_MASK)); nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_TXEN); } else { nrf_radio_shorts_set(NRF_RADIO, @@ -1722,7 +1737,8 @@ static void on_radio_disabled_rx_send_ack(void) nrf_radio_packetptr_set(NRF_RADIO, rx_payload_buffer); if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common); + nrf_radio_shorts_set(NRF_RADIO, + (radio_shorts_common | NRF_RADIO_SHORT_READY_START_MASK)); nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_RXEN); } else { nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | diff --git a/subsys/esb/esb_dppi.c b/subsys/esb/esb_dppi.c index 858b1e8750aa..d1923e51d8dd 100644 --- a/subsys/esb/esb_dppi.c +++ b/subsys/esb/esb_dppi.c @@ -53,6 +53,10 @@ void esb_ppi_for_txrx_set(bool rx, bool timer_start) egu_timer_start); } + if (IS_ENABLED(CONFIG_ESB_FAST_SWITCHING) && timer_start && !rx) { + nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, disabled_phy_end_egu); + } + channels_mask = (BIT(egu_timer_start) | BIT(egu_ramp_up)); @@ -82,6 +86,10 @@ void esb_ppi_for_txrx_clear(bool rx, bool timer_start) if (timer_start) { nrf_timer_subscribe_clear(ESB_NRF_TIMER_INSTANCE, NRF_TIMER_TASK_START); } + + if (IS_ENABLED(CONFIG_ESB_FAST_SWITCHING) && timer_start && !rx) { + nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_RXEN); + } } void esb_ppi_for_fem_set(void) From ff39d5a55285d5037fbeec5cd43296840b3c7ec9 Mon Sep 17 00:00:00 2001 From: Szymon Antkowiak Date: Thu, 4 Dec 2025 16:52:05 +0100 Subject: [PATCH 137/155] esb: rework radio shorts Simplify common radio shorts to not depend on fast switching configuration. Rename alias for short between END/PHYEND and DISABLE. Signed-off-by: Szymon Antkowiak --- subsys/esb/esb.c | 88 ++++++++++++++++-------------------- subsys/esb/esb_peripherals.h | 6 +-- 2 files changed, 42 insertions(+), 52 deletions(-) diff --git a/subsys/esb/esb.c b/subsys/esb/esb.c index 4fea7351030b..9a148554a3bf 100644 --- a/subsys/esb/esb.c +++ b/subsys/esb/esb.c @@ -81,24 +81,16 @@ LOG_MODULE_REGISTER(esb, CONFIG_ESB_LOG_LEVEL); /* NRF5340 Radio high voltage gain. */ #define NRF5340_HIGH_VOLTAGE_GAIN 3 -/* Fast switching is available for the nRF54H20 SoC. - * The nRF54H20 is a non-RSSISTOP device. - */ #if defined(RADIO_SHORTS_DISABLED_RSSISTOP_Msk) -#define RADIO_SHORTS_COMMON \ - (NRF_RADIO_SHORT_READY_START_MASK | ESB_SHORT_DISABLE_MASK | \ - NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | NRF_RADIO_SHORT_DISABLED_RSSISTOP_MASK) +#define RADIO_RSSI_SHORTS \ + (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | NRF_RADIO_SHORT_DISABLED_RSSISTOP_MASK) #else /* Devices without RSSISTOP task will stop RSSI measurement after specific period. */ -#define RADIO_SHORTS_FAST_SWITCHING_NO_RSSISTOP (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK) -#define RADIO_SHORTS_NO_FAST_SWITCHING_NO_RSSISTOP \ - (NRF_RADIO_SHORT_READY_START_MASK | ESB_SHORT_DISABLE_MASK | \ - NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK) +#define RADIO_RSSI_SHORTS (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK) +#endif /* !defined(RADIO_SHORTS_DISABLED_RSSISTOP_Msk) */ -#define RADIO_SHORTS_COMMON \ - (IS_ENABLED(CONFIG_ESB_FAST_SWITCHING) ? RADIO_SHORTS_FAST_SWITCHING_NO_RSSISTOP : \ - RADIO_SHORTS_NO_FAST_SWITCHING_NO_RSSISTOP) -#endif /* !defined(RADIO_SHORTS_DISABLED_RSSISTOP_Msk) */ +#define RADIO_NORMAL_SW_SHORTS \ + (RADIO_RSSI_SHORTS | NRF_RADIO_SHORT_READY_START_MASK | ESB_RADIO_SHORT_END_DISABLE) #if defined(CONFIG_SOC_SERIES_NRF54LX) #define RADIO_SHORTS_MONITOR \ @@ -296,7 +288,6 @@ static volatile uint32_t retransmits_remaining; static volatile uint32_t last_tx_attempts; static volatile uint32_t wait_for_ack_timeout_us; -static uint32_t radio_shorts_common = RADIO_SHORTS_COMMON; static const bool fast_switching = IS_ENABLED(CONFIG_ESB_FAST_SWITCHING); static const mpsl_fem_event_t rx_event = { @@ -1189,13 +1180,13 @@ static void start_tx_transaction(void) memcpy(pdu->data, current_payload->data, current_payload->length); if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | + nrf_radio_shorts_set(NRF_RADIO, (RADIO_RSSI_SHORTS | NRF_RADIO_SHORT_TXREADY_START_MASK)); nrf_radio_event_clear(NRF_RADIO, ESB_RADIO_EVENT_END); nrf_radio_int_enable(NRF_RADIO, ESB_RADIO_INT_END_MASK); } else { - nrf_radio_shorts_set(NRF_RADIO, - (radio_shorts_common | NRF_RADIO_SHORT_DISABLED_RXEN_MASK)); + nrf_radio_shorts_set(NRF_RADIO, (RADIO_NORMAL_SW_SHORTS | + NRF_RADIO_SHORT_DISABLED_RXEN_MASK)); } nrf_radio_int_enable(NRF_RADIO, NRF_RADIO_INT_DISABLED_MASK); @@ -1218,13 +1209,15 @@ static void start_tx_transaction(void) /* Handling ack if noack is set to false or if selective auto ack is turned off */ if (ack) { if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, - (radio_shorts_common | NRF_RADIO_SHORT_TXREADY_START_MASK)); + nrf_radio_shorts_set( + NRF_RADIO, + (RADIO_RSSI_SHORTS | NRF_RADIO_SHORT_TXREADY_START_MASK)); nrf_radio_event_clear(NRF_RADIO, ESB_RADIO_EVENT_END); nrf_radio_int_enable(NRF_RADIO, ESB_RADIO_INT_END_MASK); } else { nrf_radio_shorts_set(NRF_RADIO, - (radio_shorts_common | NRF_RADIO_SHORT_DISABLED_RXEN_MASK)); + (RADIO_NORMAL_SW_SHORTS | + NRF_RADIO_SHORT_DISABLED_RXEN_MASK)); } /* Configure the retransmit counter */ @@ -1233,8 +1226,8 @@ static void start_tx_transaction(void) esb_state = ESB_STATE_PTX_TX_ACK; nrf_radio_int_enable(NRF_RADIO, NRF_RADIO_INT_DISABLED_MASK); } else if (IS_ENABLED(CONFIG_ESB_NEVER_DISABLE_TX)) { - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common & - ~ESB_SHORT_DISABLE_MASK); + nrf_radio_shorts_set( + NRF_RADIO, (RADIO_RSSI_SHORTS | NRF_RADIO_SHORT_READY_START_MASK)); nrf_timer_shorts_set(esb_timer.p_reg, (NRF_TIMER_SHORT_COMPARE1_STOP_MASK | NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK)); @@ -1253,9 +1246,7 @@ static void start_tx_transaction(void) (esb_state == ESB_STATE_PTX_TX)); esb_state = ESB_STATE_PTX_TX; } else { - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | - NRF_RADIO_SHORT_READY_START_MASK | - ESB_SHORT_DISABLE_MASK)); + nrf_radio_shorts_set(NRF_RADIO, RADIO_NORMAL_SW_SHORTS); on_radio_disabled = on_radio_disabled_tx_noack; esb_state = ESB_STATE_PTX_TX; @@ -1352,7 +1343,7 @@ static void on_radio_disabled_tx(void) /* Remove the DISABLED -> RXEN shortcut, to make sure the radio stays * disabled after the RX window */ - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common); + nrf_radio_shorts_set(NRF_RADIO, RADIO_NORMAL_SW_SHORTS); /* Make sure the timer is started the next time the radio is ready, * and that it will disable the radio automatically if no packet is @@ -1394,8 +1385,6 @@ static void on_radio_disabled_tx(void) nrf_radio_packetptr_set(NRF_RADIO, rx_payload_buffer); if (fast_switching) { nrf_radio_int_disable(NRF_RADIO, ESB_RADIO_INT_END_MASK); - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | ESB_SHORT_DISABLE_MASK | - NRF_RADIO_SHORT_RXREADY_START_MASK)); nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_START); } on_radio_disabled = on_radio_disabled_tx_wait_for_ack; @@ -1431,10 +1420,6 @@ static void on_radio_disabled_tx_wait_for_ack(void) } } - if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common); - } - if ((atomic_get(&tx_fifo.count) == 0) || (esb_cfg.tx_mode == ESB_TXMODE_MANUAL)) { esb_state = ESB_STATE_IDLE; errata_216_off(); @@ -1467,13 +1452,13 @@ static void on_radio_disabled_tx_wait_for_ack(void) nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY); if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | + nrf_radio_shorts_set(NRF_RADIO, (RADIO_RSSI_SHORTS | NRF_RADIO_SHORT_TXREADY_START_MASK)); nrf_radio_event_clear(NRF_RADIO, ESB_RADIO_EVENT_END); nrf_radio_int_enable(NRF_RADIO, ESB_RADIO_INT_END_MASK); } else { - nrf_radio_shorts_set(NRF_RADIO, - (radio_shorts_common | NRF_RADIO_SHORT_DISABLED_RXEN_MASK)); + nrf_radio_shorts_set(NRF_RADIO, (RADIO_NORMAL_SW_SHORTS | + NRF_RADIO_SHORT_DISABLED_RXEN_MASK)); } if (esb_cfg.protocol == ESB_PROTOCOL_ESB) { @@ -1538,12 +1523,12 @@ static void start_rx_listening(void) on_radio_disabled = NULL; } else { if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | - NRF_RADIO_SHORT_READY_START_MASK)); + nrf_radio_shorts_set(NRF_RADIO, (RADIO_RSSI_SHORTS | + NRF_RADIO_SHORT_RXREADY_START_MASK)); nrf_radio_event_clear(NRF_RADIO, ESB_RADIO_EVENT_END); nrf_radio_int_enable(NRF_RADIO, ESB_RADIO_INT_END_MASK); } else { - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | + nrf_radio_shorts_set(NRF_RADIO, (RADIO_NORMAL_SW_SHORTS | NRF_RADIO_SHORT_DISABLED_TXEN_MASK)); } @@ -1576,7 +1561,7 @@ static void clear_events_restart_rx(void) esb_fem_lna_reset(); esb_ppi_for_txrx_clear(true, false); - nrf_radio_shorts_set(NRF_RADIO, radio_shorts_common); + nrf_radio_shorts_set(NRF_RADIO, 0); if (esb_cfg.protocol == ESB_PROTOCOL_ESB) { update_rf_payload_format_esb(0); @@ -1593,8 +1578,13 @@ static void clear_events_restart_rx(void) nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED); - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | NRF_RADIO_SHORT_READY_START_MASK | - NRF_RADIO_SHORT_DISABLED_TXEN_MASK)); + if (fast_switching) { + nrf_radio_shorts_set(NRF_RADIO, + (RADIO_RSSI_SHORTS | NRF_RADIO_SHORT_RXREADY_START_MASK)); + } else { + nrf_radio_shorts_set(NRF_RADIO, + (RADIO_NORMAL_SW_SHORTS | NRF_RADIO_SHORT_DISABLED_TXEN_MASK)); + } esb_ppi_for_txrx_set(true, false); esb_fem_for_rx_set(); @@ -1702,12 +1692,12 @@ static void on_radio_disabled_rx(void) nrf_radio_packetptr_set(NRF_RADIO, tx_pdu); if (fast_switching) { - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | - NRF_RADIO_SHORT_READY_START_MASK)); + nrf_radio_shorts_set(NRF_RADIO, (RADIO_RSSI_SHORTS | + NRF_RADIO_SHORT_TXREADY_START_MASK)); nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_TXEN); } else { - nrf_radio_shorts_set(NRF_RADIO, - (radio_shorts_common | NRF_RADIO_SHORT_DISABLED_RXEN_MASK)); + nrf_radio_shorts_set(NRF_RADIO, (RADIO_NORMAL_SW_SHORTS | + NRF_RADIO_SHORT_DISABLED_RXEN_MASK)); } on_radio_disabled = on_radio_disabled_rx_send_ack; @@ -1738,11 +1728,11 @@ static void on_radio_disabled_rx_send_ack(void) nrf_radio_packetptr_set(NRF_RADIO, rx_payload_buffer); if (fast_switching) { nrf_radio_shorts_set(NRF_RADIO, - (radio_shorts_common | NRF_RADIO_SHORT_READY_START_MASK)); + (RADIO_RSSI_SHORTS | NRF_RADIO_SHORT_RXREADY_START_MASK)); nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_RXEN); } else { - nrf_radio_shorts_set(NRF_RADIO, (radio_shorts_common | - NRF_RADIO_SHORT_DISABLED_TXEN_MASK)); + nrf_radio_shorts_set(NRF_RADIO, + (RADIO_NORMAL_SW_SHORTS | NRF_RADIO_SHORT_DISABLED_TXEN_MASK)); } on_radio_disabled = on_radio_disabled_rx; diff --git a/subsys/esb/esb_peripherals.h b/subsys/esb/esb_peripherals.h index 66f46806513a..7de10088fc42 100644 --- a/subsys/esb/esb_peripherals.h +++ b/subsys/esb/esb_peripherals.h @@ -34,7 +34,7 @@ extern "C" { /** Use end of packet send/received over the air for nRF54 devices. */ #define ESB_RADIO_EVENT_END NRF_RADIO_EVENT_PHYEND - #define ESB_SHORT_DISABLE_MASK NRF_RADIO_SHORT_PHYEND_DISABLE_MASK + #define ESB_RADIO_SHORT_END_DISABLE NRF_RADIO_SHORT_PHYEND_DISABLE_MASK #define ESB_RADIO_INT_END_MASK NRF_RADIO_INT_PHYEND_MASK @@ -55,7 +55,7 @@ extern "C" { /** Use end of packet send/received over the air for nRF54 devices. */ #define ESB_RADIO_EVENT_END NRF_RADIO_EVENT_PHYEND - #define ESB_SHORT_DISABLE_MASK NRF_RADIO_SHORT_PHYEND_DISABLE_MASK + #define ESB_RADIO_SHORT_END_DISABLE NRF_RADIO_SHORT_PHYEND_DISABLE_MASK #define ESB_RADIO_INT_END_MASK NRF_RADIO_INT_PHYEND_MASK #else @@ -71,7 +71,7 @@ extern "C" { /** nRF52 and nRF53 device has just one kind of end event. */ #define ESB_RADIO_EVENT_END NRF_RADIO_EVENT_END - #define ESB_SHORT_DISABLE_MASK NRF_RADIO_SHORT_END_DISABLE_MASK + #define ESB_RADIO_SHORT_END_DISABLE NRF_RADIO_SHORT_END_DISABLE_MASK #define ESB_RADIO_INT_END_MASK NRF_RADIO_INT_END_MASK From 54dfbc522f0deebc927d5ae34037a174cc6e5336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Fri, 5 Dec 2025 09:30:20 +0100 Subject: [PATCH 138/155] samples: zephyr: subsys: settings: Remove sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sample uses NVS and shall not be run on devices with RRAM. Remove sample for now. Signed-off-by: Sebastian Głąb --- CODEOWNERS | 1 - samples/zephyr/subsys/settings/CMakeLists.txt | 11 ----- samples/zephyr/subsys/settings/README.txt | 4 -- samples/zephyr/subsys/settings/prj.conf | 9 ---- samples/zephyr/subsys/settings/testcase.yaml | 42 ------------------- scripts/ci/tags.yaml | 5 --- 6 files changed, 72 deletions(-) delete mode 100644 samples/zephyr/subsys/settings/CMakeLists.txt delete mode 100644 samples/zephyr/subsys/settings/README.txt delete mode 100644 samples/zephyr/subsys/settings/prj.conf delete mode 100644 samples/zephyr/subsys/settings/testcase.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 782daddbfcee..fa4d2adde995 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -691,7 +691,6 @@ /samples/zephyr/smp_svr_mini_boot/ @nrfconnect/ncs-eris /samples/zephyr/subsys/ipc/ @nrfconnect/ncs-low-level-test /samples/zephyr/subsys/mgmt/mcumgr/smp_svr/ @nrfconnect/ncs-eris -/samples/zephyr/subsys/settings/ @nrfconnect/ncs-low-level-test /samples/zephyr/subsys/usb/ @nrfconnect/ncs-low-level-test /samples/zephyr/sysbuild/ @nrfconnect/ncs-low-level-test diff --git a/samples/zephyr/subsys/settings/CMakeLists.txt b/samples/zephyr/subsys/settings/CMakeLists.txt deleted file mode 100644 index 32b6271e57b1..000000000000 --- a/samples/zephyr/subsys/settings/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# -# Copyright (c) 2025 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(settings_sample) - -target_sources(app PRIVATE ${ZEPHYR_BASE}/samples/subsys/settings/src/main.c) diff --git a/samples/zephyr/subsys/settings/README.txt b/samples/zephyr/subsys/settings/README.txt deleted file mode 100644 index f5833d2631e3..000000000000 --- a/samples/zephyr/subsys/settings/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -This sample extends the same-named Zephyr sample to verify it -with Nordic development kits. - -Source code and basic configuration files can be found in the corresponding folder structure in zephyr/samples/subsys/settings. diff --git a/samples/zephyr/subsys/settings/prj.conf b/samples/zephyr/subsys/settings/prj.conf deleted file mode 100644 index d9ae787141af..000000000000 --- a/samples/zephyr/subsys/settings/prj.conf +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG_STDOUT_CONSOLE=y -CONFIG_FLASH=y -CONFIG_FLASH_MAP=y -CONFIG_SETTINGS=y -CONFIG_SETTINGS_RUNTIME=y -CONFIG_NVS=y -CONFIG_SETTINGS_NVS=y -CONFIG_HEAP_MEM_POOL_SIZE=256 -CONFIG_MPU_ALLOW_FLASH_WRITE=y diff --git a/samples/zephyr/subsys/settings/testcase.yaml b/samples/zephyr/subsys/settings/testcase.yaml deleted file mode 100644 index fd1d4fba73ba..000000000000 --- a/samples/zephyr/subsys/settings/testcase.yaml +++ /dev/null @@ -1,42 +0,0 @@ -sample: - name: Settings Sample - -tests: - nrf.extended.sample.subsys.settings: - integration_platforms: - - nrf54ls05dk/nrf54ls05b/cpuapp - platform_allow: - - nrf54ls05dk@0.0.0/nrf54ls05b/cpuapp - - nrf54ls05dk/nrf54ls05b/cpuapp - tags: - - settings - - ci_samples_zephyr_subsys_settings - timeout: 10 - harness: console - harness_config: - type: multi_line - regex: - - "subtree handler registered: OK" - - "# iteration 0" - - "[.]* value exist in the storage" - - "[.]*Can\\'t to load the value as expected" - - " = 0 \\(default\\)" - - "# iteration 1" - - " = 59" - - "# iteration 2" - - " = 42" - - "# iteration 3" - - " = -3100" - - "# iteration 4" - - " = abcd" - - "# iteration 5" - - " = 5" - - " is not compatible with the application" - - "direct.length = 100" - - "direct.length_1 = 46" - - "direct.length_2 = 54" - - " = 5" - - "The settings destination off the key has got value:\ - \ \"RT\"" - - "String value \"rtos\" was retrieved from the settings destination off the\ - \ key " diff --git a/scripts/ci/tags.yaml b/scripts/ci/tags.yaml index dc3ec8918831..f90224db710b 100644 --- a/scripts/ci/tags.yaml +++ b/scripts/ci/tags.yaml @@ -1580,11 +1580,6 @@ ci_samples_zephyr_sensor_qdec: - nrf/samples/zephyr/sensor/qdec/ - zephyr/samples/sensor/qdec/ -ci_samples_zephyr_subsys_settings: - files: - - nrf/samples/zephyr/subsys/settings/ - - zephyr/samples/subsys/settings/ - ci_samples_zephyr_sysbuild_hello_world: files: - nrf/samples/zephyr/sysbuild/hello_world/ From d91bad772b99e80a0192c3caeffbac81f1335a02 Mon Sep 17 00:00:00 2001 From: Bartosz Miller Date: Fri, 5 Dec 2025 09:43:08 +0100 Subject: [PATCH 139/155] tests: drivers: pwm: Fix PWM events test Fix incorrect DTS led assignemnt for ls05 Signed-off-by: Bartosz Miller --- .../pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 4 ++++ .../pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay | 4 ++++ .../pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay | 4 ++++ .../pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay | 4 ++++ tests/drivers/pwm/pwm_events/src/main.c | 2 +- 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 0f736b52db0a..6227ed62ea43 100644 --- a/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -17,3 +17,7 @@ tst_timer: &timer131 { sink-channels = <1>; status = "okay"; }; + +pwm_led: &led2 { + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index de54b0bf3f9c..908b8dc6caf9 100644 --- a/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -15,3 +15,7 @@ tst_timer: &timer20 { &dppic20 { status = "okay"; }; + +pwm_led: &led2 { + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index de54b0bf3f9c..908b8dc6caf9 100644 --- a/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay +++ b/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -15,3 +15,7 @@ tst_timer: &timer20 { &dppic20 { status = "okay"; }; + +pwm_led: &led2 { + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay index de54b0bf3f9c..8bac2dbf0feb 100644 --- a/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay +++ b/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay @@ -15,3 +15,7 @@ tst_timer: &timer20 { &dppic20 { status = "okay"; }; + +pwm_led: &led0 { + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_events/src/main.c b/tests/drivers/pwm/pwm_events/src/main.c index 05c32dd7aa27..672b13c25fb0 100644 --- a/tests/drivers/pwm/pwm_events/src/main.c +++ b/tests/drivers/pwm/pwm_events/src/main.c @@ -10,7 +10,7 @@ #include #include -#define PWM_OUTPUT_PIN NRF_DT_GPIOS_TO_PSEL(DT_NODELABEL(led2), gpios) +#define PWM_OUTPUT_PIN NRF_DT_GPIOS_TO_PSEL(DT_NODELABEL(pwm_led), gpios) #define SLEEP_TIME_MS 500 From 8c4003ba44a6a8033c2412a938a3bf14091614f4 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Wed, 3 Dec 2025 11:28:37 +0000 Subject: [PATCH 140/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3588 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 254f4e20846a..a12d3320a789 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: 18c1bc6ba28bc425f2567cf58f4c7353fca1b6eb + revision: 084b65b8f4e8b30b1d0b3b12a363f9b52b315c06 import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From fe3571ec8fa7f2280179bbae62545af6f2278d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Wed, 3 Dec 2025 12:23:11 +0100 Subject: [PATCH 141/155] samples: esb: Fix nrf54h20 cpurad target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use new version of GPPI helper on cpurad for managing DPPI channels on local slow and fast radio domains. Signed-off-by: Krzysztof Chruściński --- samples/esb/esb_prx/boards/nrf54h20dk_nrf54h20_cpurad.conf | 1 + samples/esb/esb_ptx/boards/nrf54h20dk_nrf54h20_cpurad.conf | 1 + 2 files changed, 2 insertions(+) create mode 100644 samples/esb/esb_prx/boards/nrf54h20dk_nrf54h20_cpurad.conf create mode 100644 samples/esb/esb_ptx/boards/nrf54h20dk_nrf54h20_cpurad.conf diff --git a/samples/esb/esb_prx/boards/nrf54h20dk_nrf54h20_cpurad.conf b/samples/esb/esb_prx/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 000000000000..cd068ebe840a --- /dev/null +++ b/samples/esb/esb_prx/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +CONFIG_NRFX_GPPI_V1=n diff --git a/samples/esb/esb_ptx/boards/nrf54h20dk_nrf54h20_cpurad.conf b/samples/esb/esb_ptx/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 000000000000..cd068ebe840a --- /dev/null +++ b/samples/esb/esb_ptx/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +CONFIG_NRFX_GPPI_V1=n From a4367fdc0db21331df42b79fd16d5797b559f732 Mon Sep 17 00:00:00 2001 From: Magdalena Pastula Date: Thu, 4 Dec 2025 17:02:05 +0100 Subject: [PATCH 142/155] samples: zephyr: drivers: adc: fix test for nRF54LS05B Fix test after integration of 8.73.0 MDK which decreased number of channels in nRF54LS05B SAADC from 8 to 4. Signed-off-by: Magdalena Pastula --- .../adc/adc_dt/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/zephyr/drivers/adc/adc_dt/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay b/samples/zephyr/drivers/adc/adc_dt/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay index ab79ca4f73ee..4acd596500ee 100644 --- a/samples/zephyr/drivers/adc/adc_dt/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay +++ b/samples/zephyr/drivers/adc/adc_dt/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay @@ -6,7 +6,7 @@ / { zephyr,user { - io-channels = <&adc 0>, <&adc 1>, <&adc 7>; + io-channels = <&adc 0>, <&adc 1>, <&adc 3>; }; }; @@ -34,8 +34,8 @@ zephyr,oversampling = <8>; }; - channel@7 { - reg = <7>; + channel@3 { + reg = <3>; zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = ; From 58059dfbaa56ed0f4cfc7e3bb261167baa1c5121 Mon Sep 17 00:00:00 2001 From: Francesco Domenico Servidio Date: Thu, 4 Dec 2025 19:11:24 +0100 Subject: [PATCH 143/155] doc: updated misc docs post 3.2.0-rc2 to main Updated misc docs post 3.2.0-rc2 to main. Signed-off-by: Francesco Domenico Servidio --- applications/nrf5340_audio/doc/configuration.rst | 6 +++--- .../nrf5340_audio/doc/configuration_options.rst | 2 +- doc/nrf/links.txt | 4 ---- doc/nrf/releases_and_maturity/abi_compatibility.rst | 11 +++++++++++ ...ion_guide_2.4.99-cs3_to_2.6.99-cs2_environment.rst | 2 +- .../migration_guide_2.6.99-cs2_to_2_7_environment.rst | 2 +- ...transition_guide_2.4.99-cs3_to_2.7_environment.rst | 2 +- .../releases/release-notes-2.8.0.rst | 4 ++-- .../releases/release-notes-3.2.0-preview2.rst | 2 +- .../releases/release-notes-3.2.0-preview3.rst | 2 +- .../releases/release-notes-changelog.rst | 4 +--- doc/nrf/security.rst | 4 ++-- doc/nrf/shortcuts.txt | 1 + 13 files changed, 26 insertions(+), 20 deletions(-) diff --git a/applications/nrf5340_audio/doc/configuration.rst b/applications/nrf5340_audio/doc/configuration.rst index 7288f18a1e1b..9401b9f35f5d 100644 --- a/applications/nrf5340_audio/doc/configuration.rst +++ b/applications/nrf5340_audio/doc/configuration.rst @@ -25,7 +25,7 @@ See the :file:`Kconfig.defaults` file in the :file:`nrf5340_audio` directory for The default Kconfig option values are automatically updated if configuration changes are applied directly in the configuration files. -The application-specific Kconfig options mentioned on this page are listed in :ref:`nRF5340 Audio: Application-specific Kconfig options `. +The application-specific Kconfig options mentioned on this page are listed in :ref:`nRF5340 Audio: Application-specific Kconfig options `. |config| @@ -211,7 +211,7 @@ Configuring audio quality The nRF5340 Audio application provides extensive configuration options for audio quality. These settings affect the :ref:`nrf53_audio_app_overview_architecture_sync_module` and overall audio performance. -See :ref:`config_audio_app_options` for the list of options to configure the following audio quality settings: +See :ref:`nrf53_audio_app_config_audio_app_options` for the list of options to configure the following audio quality settings: * Frame duration (example: :option:`CONFIG_AUDIO_FRAME_DURATION_10_MS`) * Sample rates (example: :option:`CONFIG_AUDIO_SAMPLE_RATE_16000_HZ`) @@ -226,7 +226,7 @@ Configuring Bluetooth LE Audio The nRF5340 Audio application introduces application-specific configuration options related to Bluetooth LE Audio. These options configure the Bluetooth stack components described in :ref:`nrf53_audio_app_overview_architecture`. -See :ref:`config_audio_app_options` for options starting with ``CONFIG_BT_AUDIO``. +See :ref:`nrf53_audio_app_config_audio_app_options` for options starting with ``CONFIG_BT_AUDIO``. .. _nrf53_audio_app_configuration_power_measurements: diff --git a/applications/nrf5340_audio/doc/configuration_options.rst b/applications/nrf5340_audio/doc/configuration_options.rst index c5a3fdb53cfe..d39c7db8a942 100644 --- a/applications/nrf5340_audio/doc/configuration_options.rst +++ b/applications/nrf5340_audio/doc/configuration_options.rst @@ -1,4 +1,4 @@ -.. _config_audio_app_options: +.. _nrf53_audio_app_config_audio_app_options: nRF5340 Audio: Application-specific Kconfig options ################################################### diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index 5083ace8a432..ca6f8e5156e1 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -1987,10 +1987,6 @@ .. _`latest nRF54H20 SoC binaries`: https://files.nordicsemi.com/artifactory/SDSC/external/ .. _`latest nRF54H20 IronSide SE binaries`: https://files.nordicsemi.com/artifactory/SDSC/external/ -.. ### Descr: Old 54H BICR file - -.. _`BICR binary file`: https://files.nordicsemi.com/artifactory/SDSC/external/bicr_ext_loadcap.hex - .. ### Descr: New 54H BICR file .. _`nRF54H20 DK BICR binary file`: https://files.nordicsemi.com/artifactory/SDSC/external/bicr/bicr.hex diff --git a/doc/nrf/releases_and_maturity/abi_compatibility.rst b/doc/nrf/releases_and_maturity/abi_compatibility.rst index 6eac3f859c59..9f3fc7c2176b 100644 --- a/doc/nrf/releases_and_maturity/abi_compatibility.rst +++ b/doc/nrf/releases_and_maturity/abi_compatibility.rst @@ -74,6 +74,17 @@ nRF54H20 IronSide SE binaries changelog The following sections provide detailed lists of changes by component. + +IronSide Secure Element (IronSide SE) v23.1.1+20 +================================================ + +Fixed +----- + +* L2CACHE now prefetches several cache lines when an L2 cache miss occurs. (HM-26346) + This will improve L2 cache performance in some situations and reduce L2 cache performance in other situations. +* Fixed unintentional behavior of ``psa_copy_key()`` when it was used in an attempt to create a revocable key. (NCSDK-36369) + IronSide Secure Element (IronSide SE) v23.1.0+19 ================================================ diff --git a/doc/nrf/releases_and_maturity/migration/2.4.99-cs3_to_2.6.99-cs2/migration_guide_2.4.99-cs3_to_2.6.99-cs2_environment.rst b/doc/nrf/releases_and_maturity/migration/2.4.99-cs3_to_2.6.99-cs2/migration_guide_2.4.99-cs3_to_2.6.99-cs2_environment.rst index 6cb1e79c1ca6..97cb2c27600d 100644 --- a/doc/nrf/releases_and_maturity/migration/2.4.99-cs3_to_2.6.99-cs2/migration_guide_2.4.99-cs3_to_2.6.99-cs2_environment.rst +++ b/doc/nrf/releases_and_maturity/migration/2.4.99-cs3_to_2.6.99-cs2/migration_guide_2.4.99-cs3_to_2.6.99-cs2_environment.rst @@ -257,7 +257,7 @@ Programming the BICR The Board Information Configuration Registers (BICR) are non-volatile memory (NVM) registers that contain information on how the nRF54H20 SoC must interact with other board elements, including the information about the power and clock delivery to the SoC. To prepare the nRF54H20 DK for first use, you must manually program the values of the BICR using a precompiled BICR binary file (:file:`bicr_ext_loadcap.hex`). -1. Download the `BICR binary file`_ . +1. Download the ``BICR binary file``. #. List all the connected development kits to see their serial number (matching the one on the DK's sticker):: nrfutil device list diff --git a/doc/nrf/releases_and_maturity/migration/nRF54H20_migration_2.7/migration_guide_2.6.99-cs2_to_2_7_environment.rst b/doc/nrf/releases_and_maturity/migration/nRF54H20_migration_2.7/migration_guide_2.6.99-cs2_to_2_7_environment.rst index 30e74fed69ff..4b229109e81d 100644 --- a/doc/nrf/releases_and_maturity/migration/nRF54H20_migration_2.7/migration_guide_2.6.99-cs2_to_2_7_environment.rst +++ b/doc/nrf/releases_and_maturity/migration/nRF54H20_migration_2.7/migration_guide_2.6.99-cs2_to_2_7_environment.rst @@ -210,7 +210,7 @@ Programming the BICR The Board Information Configuration Registers (BICR) are non-volatile memory (NVM) registers that contain information on how the nRF54H20 SoC must interact with other board elements, including the information about the power and clock delivery to the SoC. To prepare the nRF54H20 DK for first use, you must manually program the values of the BICR using a precompiled BICR binary file (:file:`bicr_ext_loadcap.hex`). -1. Download the `BICR binary file`_ . +1. Download the ``BICR binary file``. #. Connect the nRF54H20 DK to your computer using the **DEBUGGER** port on the DK. .. note:: diff --git a/doc/nrf/releases_and_maturity/migration/nRF54H20_migration_2.7/transition_guide_2.4.99-cs3_to_2.7_environment.rst b/doc/nrf/releases_and_maturity/migration/nRF54H20_migration_2.7/transition_guide_2.4.99-cs3_to_2.7_environment.rst index e411f77a1f04..e965df3b2f51 100644 --- a/doc/nrf/releases_and_maturity/migration/nRF54H20_migration_2.7/transition_guide_2.4.99-cs3_to_2.7_environment.rst +++ b/doc/nrf/releases_and_maturity/migration/nRF54H20_migration_2.7/transition_guide_2.4.99-cs3_to_2.7_environment.rst @@ -214,7 +214,7 @@ Programming the BICR The Board Information Configuration Registers (BICR) are non-volatile memory (NVM) registers that contain information on how the nRF54H20 SoC must interact with other board elements, including the information about the power and clock delivery to the SoC. To prepare the nRF54H20 DK for first use, you must manually program the values of the BICR using a precompiled BICR binary file (:file:`bicr_ext_loadcap.hex`). -1. Download the `BICR binary file`_ . +1. Download the ``BICR binary file``. #. Connect the nRF54H20 DK to your computer using the **DEBUGGER** port on the DK. .. note:: diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-2.8.0.rst b/doc/nrf/releases_and_maturity/releases/release-notes-2.8.0.rst index 59328891d392..d45671a53545 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-2.8.0.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-2.8.0.rst @@ -530,11 +530,11 @@ nRF5340 Audio * The functions ``bt_hci_err_to_str()`` and ``bt_security_err_to_str()`` that are used to allow printing error codes as strings. Each function returns string representations of the error codes when the corresponding Kconfig option, :kconfig:option:`CONFIG_BT_HCI_ERR_TO_STR` or :kconfig:option:`CONFIG_BT_SECURITY_ERR_TO_STR`, is enabled. - * CSIS to the BIS sink if the scan delegator feature, :ref:`CONFIG_BT_AUDIO_SCAN_DELEGATOR `, is enabled. + * CSIS to the BIS sink if the scan delegator feature, :ref:`CONFIG_BT_AUDIO_SCAN_DELEGATOR `, is enabled. Once a phone is connected to a BIS sink, the phone will find and connect to the second headset. Also, the phone can control the BIS headset in a group and deliver the PAST to both headsets at the same time. * Create CIG after reading the PACS from the first connected unicast server. - * A minimal scan delegator to the unicast server if the feature, :ref:`CONFIG_BT_AUDIO_SCAN_DELEGATOR `, is enabled. + * A minimal scan delegator to the unicast server if the feature, :ref:`CONFIG_BT_AUDIO_SCAN_DELEGATOR `, is enabled. * Available or support context type to PACS in broadcast sink and unicast client if the feature, :kconfig:option:`CONFIG_BT_PAC_SRC_NOTIFIABLE` is enabled. * The :ref:`nrf_auraconfig` sample. diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-3.2.0-preview2.rst b/doc/nrf/releases_and_maturity/releases/release-notes-3.2.0-preview2.rst index 6ab14a2b5fc1..da979b3e3e16 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-3.2.0-preview2.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-3.2.0-preview2.rst @@ -235,7 +235,7 @@ nRF5340 Audio * Added: * The :ref:`Audio application API documentation ` page. - * The :ref:`config_audio_app_options` page. + * The :ref:`nrf53_audio_app_config_audio_app_options` page. * The API documentation in the header files listed on the :ref:`audio_api` page. * Ability to connect by address as a unicast client. diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-3.2.0-preview3.rst b/doc/nrf/releases_and_maturity/releases/release-notes-3.2.0-preview3.rst index 65c83f0185fe..a7646e6868cd 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-3.2.0-preview3.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-3.2.0-preview3.rst @@ -244,7 +244,7 @@ nRF5340 Audio This means that if another device appears with the same address, it will be treated as the same server. * Experimental support for stereo in :ref:`unicast server application`. * The :ref:`Audio application API documentation ` page. - * The :ref:`config_audio_app_options` page. + * The :ref:`nrf53_audio_app_config_audio_app_options` page. * The API documentation in the header files listed on the :ref:`audio_api` page. * Ability to connect by address as a unicast client. diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index cc3e61ef698f..7678e3454f1a 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -53,7 +53,7 @@ Bootloaders and DFU Developing with nRF91 Series ============================ -* Moved the sections about updating the firmware using the Programmer app to the `Programming nRF91 Series DK firmware`_ tools page. +|no_changes_yet_note| Developing with nRF70 Series ============================ @@ -138,8 +138,6 @@ DECT NR+ Enhanced ShockBurst (ESB) ------------------------- -|no_changes_yet_note| - * Updated: * Workaround handling for the hardware erratas. diff --git a/doc/nrf/security.rst b/doc/nrf/security.rst index 68c2f7befafe..76a5dc3f8586 100644 --- a/doc/nrf/security.rst +++ b/doc/nrf/security.rst @@ -21,7 +21,7 @@ The |NCS| |release| allows you to develop applications with the following versio - Mbed TLS version * - |release| - v2.2.0 - - v23.1.0+19 + - |ironside_se_ver| - 3.6.5 .. security_components_ver_table_end @@ -52,7 +52,7 @@ Expand the following section to see the table listing versions of different secu - 3.6.5 * - v3.2.0 - v2.2.0 - - v23.1.0+19 + - |ironside_se_ver| - 3.6.5 * - v3.1.0, v3.1.1 - v2.1.2 diff --git a/doc/nrf/shortcuts.txt b/doc/nrf/shortcuts.txt index f292268647ab..9e21e5faf6da 100644 --- a/doc/nrf/shortcuts.txt +++ b/doc/nrf/shortcuts.txt @@ -10,6 +10,7 @@ .. |54H_nrfutil_device_ver| replace:: 2.15.2 .. |54H_nrfutil_trace_ver| replace:: 4.4.0 +.. |ironside_se_ver| replace:: v23.1.1+20 .. ### Config shortcuts From 1769e44925c26c62d871abe8b949e824e2f8824d Mon Sep 17 00:00:00 2001 From: Tommi Kangas Date: Thu, 4 Dec 2025 15:07:48 +0200 Subject: [PATCH 144/155] lib: lte_link_control: Add PDN suspend/resume support Added new PDN events LTE_LC_EVT_PDN_SUSPENDED and LTE_LC_EVT_PDN_RESUMED. These events supported by the mfw_nrf9151-ntn modem firmware are used with cellular profiles to indicate when PDNs are active, but temporarily not usable. Signed-off-by: Tommi Kangas --- .../releases/release-notes-changelog.rst | 4 ++- include/modem/lte_lc.h | 34 +++++++++++++++++-- lib/lte_link_control/modules/pdn.c | 6 ++++ .../modem_shell/src/link/link_shell_pdn.c | 2 ++ tests/lib/lte_lc_pdn/src/main.c | 18 ++++++++++ 5 files changed, 61 insertions(+), 3 deletions(-) diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index 7678e3454f1a..e02fa56f0eb3 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -406,7 +406,9 @@ Security libraries Modem libraries --------------- -|no_changes_yet_note| +* :ref:`lte_lc_readme` library: + + * Added support for new PDN events :c:enumerator:`LTE_LC_EVT_PDN_SUSPENDED` and :c:enumerator:`LTE_LC_EVT_PDN_RESUMED`. Multiprotocol Service Layer libraries ------------------------------------- diff --git a/include/modem/lte_lc.h b/include/modem/lte_lc.h index 8a2261d5d082..70a008becdfa 100644 --- a/include/modem/lte_lc.h +++ b/include/modem/lte_lc.h @@ -455,8 +455,8 @@ enum lte_lc_evt_type { * @ref lte_lc_rai_cfg in the event. * * @note This is only supported by the following modem firmware: - * - mfw_nrf91x1 >= v2.0.2 - * - mfw_nrf9151-ntn + * - mfw_nrf91x1 >= v2.0.2 + * - mfw_nrf9151-ntn */ LTE_LC_EVT_RAI_UPDATE = 12, #endif /* CONFIG_LTE_LC_RAI_MODULE */ @@ -1481,6 +1481,36 @@ enum lte_lc_pdn_evt_type { */ LTE_LC_EVT_PDN_IPV6_DOWN, + /** + * PDN is suspended. + * + * PDNs can be suspended when cellular profiles are used. While suspended, the PDNs remain + * active, but can not be used for data transmission. PDNs associated with a cellular + * profile are suspended when the device is switched to flight mode using + * @ref LTE_LC_FUNC_MODE_OFFLINE_KEEP_REG or @ref LTE_LC_FUNC_MODE_OFFLINE_KEEP_REG_UICC_ON. + * The PDNs remain suspended when switching to a different access technology. When the + * device is switched back to the original access technology and LTE is activated, the + * associated PDNs are resumed. + * + * The associated payload is the @c lte_lc_evt.pdn member of type + * @ref lte_lc_pdn_evt in the event. + * + * @note This is only supported by the following modem firmware: + * - mfw_nrf9151-ntn + */ + LTE_LC_EVT_PDN_SUSPENDED, + + /** + * PDN is resumed. + * + * The associated payload is the @c lte_lc_evt.pdn member of type + * @ref lte_lc_pdn_evt in the event. + * + * @note This is only supported by the following modem firmware: + * - mfw_nrf9151-ntn + */ + LTE_LC_EVT_PDN_RESUMED, + /** * Network detached. * diff --git a/lib/lte_link_control/modules/pdn.c b/lib/lte_link_control/modules/pdn.c index 03a5fe49f011..bde25b6eefee 100644 --- a/lib/lte_link_control/modules/pdn.c +++ b/lib/lte_link_control/modules/pdn.c @@ -196,6 +196,10 @@ static void parse_cgev(const char *notif) {"ME PDN DEACT ", LTE_LC_EVT_PDN_DEACTIVATED}, /* +CGEV: NW PDN DEACT */ {"NW PDN DEACT ", LTE_LC_EVT_PDN_DEACTIVATED}, + /* +CGEV: ME PDN SUSPENDED */ + {"ME PDN SUSPENDED ", LTE_LC_EVT_PDN_SUSPENDED}, + /* +CGEV: ME PDN RESUMED */ + {"ME PDN RESUMED ", LTE_LC_EVT_PDN_RESUMED}, /* +CGEV: ME DETACH [] */ {"ME DETACH", LTE_LC_EVT_PDN_NETWORK_DETACH}, /* +CGEV: NW DETACH [] */ @@ -244,6 +248,8 @@ static void parse_cgev(const char *notif) case LTE_LC_EVT_PDN_DEACTIVATED: case LTE_LC_EVT_PDN_IPV6_UP: case LTE_LC_EVT_PDN_IPV6_DOWN: + case LTE_LC_EVT_PDN_SUSPENDED: + case LTE_LC_EVT_PDN_RESUMED: evt.pdn.cid = (int8_t)strtoul(p, &p, 10); break; diff --git a/samples/cellular/modem_shell/src/link/link_shell_pdn.c b/samples/cellular/modem_shell/src/link/link_shell_pdn.c index 2a976673b597..d17f6cb48b3d 100644 --- a/samples/cellular/modem_shell/src/link/link_shell_pdn.c +++ b/samples/cellular/modem_shell/src/link/link_shell_pdn.c @@ -41,6 +41,8 @@ const char *link_pdn_event_to_string(enum lte_lc_evt_type event, char *out_str_b { LTE_LC_EVT_PDN_DEACTIVATED, "deactivated" }, { LTE_LC_EVT_PDN_IPV6_UP, "IPv6 up" }, { LTE_LC_EVT_PDN_IPV6_DOWN, "IPv6 down" }, + { LTE_LC_EVT_PDN_SUSPENDED, "suspended" }, + { LTE_LC_EVT_PDN_RESUMED, "resumed" }, { LTE_LC_EVT_PDN_NETWORK_DETACH, "network detach" }, { LTE_LC_EVT_PDN_APN_RATE_CONTROL_ON, "APN rate control on" }, { LTE_LC_EVT_PDN_APN_RATE_CONTROL_OFF, "APN rate control off" }, diff --git a/tests/lib/lte_lc_pdn/src/main.c b/tests/lib/lte_lc_pdn/src/main.c index 925fe0033809..965ef296d753 100644 --- a/tests/lib/lte_lc_pdn/src/main.c +++ b/tests/lib/lte_lc_pdn/src/main.c @@ -943,6 +943,8 @@ static void lte_lc_event_handler(const struct lte_lc_evt *const evt) case LTE_LC_EVT_PDN_DEACTIVATED: case LTE_LC_EVT_PDN_IPV6_UP: case LTE_LC_EVT_PDN_IPV6_DOWN: + case LTE_LC_EVT_PDN_SUSPENDED: + case LTE_LC_EVT_PDN_RESUMED: case LTE_LC_EVT_PDN_NETWORK_DETACH: case LTE_LC_EVT_PDN_APN_RATE_CONTROL_ON: case LTE_LC_EVT_PDN_APN_RATE_CONTROL_OFF: @@ -1388,6 +1390,22 @@ void test_lte_lc_pdn_deactivate(void) TEST_ASSERT_EQUAL(LTE_LC_EVT_PDN_DEACTIVATED, pdn_evt.pdn.type); } +void test_lte_lc_pdn_suspended(void) +{ + on_cgev("+CGEV: ME PDN SUSPENDED " STRINGIFY(CID_0) "\r\n"); + TEST_ASSERT_EQUAL(LTE_LC_EVT_PDN, pdn_evt.type); + TEST_ASSERT_EQUAL(LTE_LC_EVT_PDN_SUSPENDED, pdn_evt.pdn.type); + TEST_ASSERT_EQUAL(CID_0, pdn_evt.pdn.cid); +} + +void test_lte_lc_pdn_resumed(void) +{ + on_cgev("+CGEV: ME PDN RESUMED " STRINGIFY(CID_1) "\r\n"); + TEST_ASSERT_EQUAL(LTE_LC_EVT_PDN, pdn_evt.type); + TEST_ASSERT_EQUAL(LTE_LC_EVT_PDN_RESUMED, pdn_evt.pdn.type); + TEST_ASSERT_EQUAL(CID_1, pdn_evt.pdn.cid); +} + void test_lte_lc_pdn_detach(void) { on_cgev("+CGEV: NW DETACH\r\n"); From 90f9611db1c826a9d28b6295a58f94f23baa9d51 Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Thu, 4 Dec 2025 13:59:15 +0000 Subject: [PATCH 145/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3605 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index a12d3320a789..e4e99e314ae1 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: 084b65b8f4e8b30b1d0b3b12a363f9b52b315c06 + revision: c09c6abd11695d6b9c2ea24c4e88822eee9ff3f9 import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From 52ea3d71c4e7837acf2c83f44c7338eae835169b Mon Sep 17 00:00:00 2001 From: Bartosz Miller Date: Fri, 5 Dec 2025 09:33:30 +0100 Subject: [PATCH 146/155] tests: drivers: i2c: Add test for MLTPAN-105 Verify MLTPAN-105 workaorund implementation I2C transaction cannot recover from TWIM reset Signed-off-by: Bartosz Miller --- tests/drivers/i2c/i2c_pan/CMakeLists.txt | 13 ++ .../boards/nrf52840dk_nrf52840.overlay | 59 +++++++ .../boards/nrf5340dk_nrf5340_cpuapp.overlay | 57 +++++++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 61 +++++++ .../boards/nrf54l15dk_nrf54l15_cpuapp.overlay | 58 +++++++ .../nrf54lm20dk_nrf54lm20a_cpuapp.overlay | 58 +++++++ .../nrf54lv10dk_nrf54lv10a_cpuapp.overlay | 58 +++++++ tests/drivers/i2c/i2c_pan/prj.conf | 4 + tests/drivers/i2c/i2c_pan/src/main.c | 154 ++++++++++++++++++ tests/drivers/i2c/i2c_pan/testcase.yaml | 22 +++ 10 files changed, 544 insertions(+) create mode 100644 tests/drivers/i2c/i2c_pan/CMakeLists.txt create mode 100644 tests/drivers/i2c/i2c_pan/boards/nrf52840dk_nrf52840.overlay create mode 100644 tests/drivers/i2c/i2c_pan/boards/nrf5340dk_nrf5340_cpuapp.overlay create mode 100644 tests/drivers/i2c/i2c_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/i2c/i2c_pan/boards/nrf54l15dk_nrf54l15_cpuapp.overlay create mode 100644 tests/drivers/i2c/i2c_pan/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay create mode 100644 tests/drivers/i2c/i2c_pan/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay create mode 100644 tests/drivers/i2c/i2c_pan/prj.conf create mode 100644 tests/drivers/i2c/i2c_pan/src/main.c create mode 100644 tests/drivers/i2c/i2c_pan/testcase.yaml diff --git a/tests/drivers/i2c/i2c_pan/CMakeLists.txt b/tests/drivers/i2c/i2c_pan/CMakeLists.txt new file mode 100644 index 000000000000..9fe4ffde808b --- /dev/null +++ b/tests/drivers/i2c/i2c_pan/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(i2c_pan) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/drivers/i2c/i2c_pan/boards/nrf52840dk_nrf52840.overlay b/tests/drivers/i2c/i2c_pan/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 000000000000..f681c5fd6177 --- /dev/null +++ b/tests/drivers/i2c/i2c_pan/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,59 @@ +/ { + aliases { + i2c-slave = &i2c1; + }; +}; + +&pinctrl { + i2c0_default_alt: i2c0_default_alt { + group1 { + psels = , + ; + }; + }; + + i2c0_sleep_alt: i2c0_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c1_default_alt: i2c1_default_alt { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c1_sleep_alt: i2c1_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut_twim: &i2c0 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c0_default_alt>; + pinctrl-1 = <&i2c0_sleep_alt>; + pinctrl-names = "default", "sleep"; + + sensor: sensor@54 { + reg = <0x54>; + }; +}; + + +dut_twis: &i2c1 { + compatible = "nordic,nrf-twis"; + status = "okay"; + pinctrl-0 = <&i2c1_default_alt>; + pinctrl-1 = <&i2c1_sleep_alt>; + pinctrl-names = "default", "sleep"; +}; diff --git a/tests/drivers/i2c/i2c_pan/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/drivers/i2c/i2c_pan/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 000000000000..8cabd53a7afd --- /dev/null +++ b/tests/drivers/i2c/i2c_pan/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,57 @@ +/ { + aliases { + i2c-slave = &i2c2; + }; +}; + +&pinctrl { + i2c1_default_alt: i2c1_default_alt { + group1 { + psels = , + ; + }; + }; + + i2c1_sleep_alt: i2c1_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c2_default_alt: i2c2_default_alt { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c2_sleep_alt: i2c2_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut_twim: &i2c1 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c1_default_alt>; + pinctrl-1 = <&i2c1_sleep_alt>; + pinctrl-names = "default", "sleep"; + + sensor: sensor@54 { + reg = <0x54>; + }; +}; + +dut_twis: &i2c2 { + compatible = "nordic,nrf-twis"; + pinctrl-0 = <&i2c2_default_alt>; + pinctrl-1 = <&i2c2_sleep_alt>; + pinctrl-names = "default", "sleep"; +}; diff --git a/tests/drivers/i2c/i2c_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/i2c/i2c_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..24e46f9f2df8 --- /dev/null +++ b/tests/drivers/i2c/i2c_pan/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,61 @@ +/ { + aliases { + i2c-slave = &i2c131; + }; +}; + +&pinctrl { + i2c130_default_alt: i2c130_default_alt { + group1 { + psels = , + ; + }; + }; + + i2c130_sleep_alt: i2c130_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c131_default_alt: i2c131_default_alt { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c131_sleep_alt: i2c131_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut_twim: &i2c130 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c130_default_alt>; + pinctrl-1 = <&i2c130_sleep_alt>; + pinctrl-names = "default", "sleep"; + memory-regions = <&cpuapp_dma_region>; + zephyr,concat-buf-size = <512>; + + sensor: sensor@54 { + reg = <0x54>; + }; +}; + +dut_twis: &i2c131 { + compatible = "nordic,nrf-twis"; + status = "okay"; + pinctrl-0 = <&i2c131_default_alt>; + pinctrl-1 = <&i2c131_sleep_alt>; + pinctrl-names = "default", "sleep"; + memory-regions = <&cpuapp_dma_region>; +}; diff --git a/tests/drivers/i2c/i2c_pan/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/i2c/i2c_pan/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 000000000000..288973409f33 --- /dev/null +++ b/tests/drivers/i2c/i2c_pan/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,58 @@ +/ { + aliases { + i2c-slave = &i2c22; + }; +}; + +&pinctrl { + i2c21_default_alt: i2c21_default_alt { + group1 { + psels = , + ; + }; + }; + + i2c21_sleep_alt: i2c21_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c22_default_alt: i2c22_default_alt { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c22_sleep_alt: i2c22_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut_twim: &i2c21 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c21_default_alt>; + pinctrl-1 = <&i2c21_sleep_alt>; + pinctrl-names = "default", "sleep"; + + sensor: sensor@54 { + reg = <0x54>; + }; +}; + +dut_twis: &i2c22 { + compatible = "nordic,nrf-twis"; + status = "okay"; + pinctrl-0 = <&i2c22_default_alt>; + pinctrl-1 = <&i2c22_sleep_alt>; + pinctrl-names = "default", "sleep"; +}; diff --git a/tests/drivers/i2c/i2c_pan/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/i2c/i2c_pan/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 000000000000..288973409f33 --- /dev/null +++ b/tests/drivers/i2c/i2c_pan/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,58 @@ +/ { + aliases { + i2c-slave = &i2c22; + }; +}; + +&pinctrl { + i2c21_default_alt: i2c21_default_alt { + group1 { + psels = , + ; + }; + }; + + i2c21_sleep_alt: i2c21_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c22_default_alt: i2c22_default_alt { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c22_sleep_alt: i2c22_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut_twim: &i2c21 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c21_default_alt>; + pinctrl-1 = <&i2c21_sleep_alt>; + pinctrl-names = "default", "sleep"; + + sensor: sensor@54 { + reg = <0x54>; + }; +}; + +dut_twis: &i2c22 { + compatible = "nordic,nrf-twis"; + status = "okay"; + pinctrl-0 = <&i2c22_default_alt>; + pinctrl-1 = <&i2c22_sleep_alt>; + pinctrl-names = "default", "sleep"; +}; diff --git a/tests/drivers/i2c/i2c_pan/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay b/tests/drivers/i2c/i2c_pan/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay new file mode 100644 index 000000000000..af3344679308 --- /dev/null +++ b/tests/drivers/i2c/i2c_pan/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay @@ -0,0 +1,58 @@ +/ { + aliases { + i2c-slave = &i2c21; + }; +}; + +&pinctrl { + i2c20_default_alt: i2c20_default_alt { + group1 { + psels = , + ; + }; + }; + + i2c20_sleep_alt: i2c20_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c21_default_alt: i2c21_default_alt { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c21_sleep_alt: i2c21_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut_twim: &i2c20 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c20_default_alt>; + pinctrl-1 = <&i2c20_sleep_alt>; + pinctrl-names = "default", "sleep"; + + sensor: sensor@54 { + reg = <0x54>; + }; +}; + +dut_twis: &i2c21 { + compatible = "nordic,nrf-twis"; + status = "okay"; + pinctrl-0 = <&i2c21_default_alt>; + pinctrl-1 = <&i2c21_sleep_alt>; + pinctrl-names = "default", "sleep"; +}; diff --git a/tests/drivers/i2c/i2c_pan/prj.conf b/tests/drivers/i2c/i2c_pan/prj.conf new file mode 100644 index 000000000000..b7da57b303b1 --- /dev/null +++ b/tests/drivers/i2c/i2c_pan/prj.conf @@ -0,0 +1,4 @@ +CONFIG_I2C=y +CONFIG_NRFX_TWIS=y + +CONFIG_ZTEST=y diff --git a/tests/drivers/i2c/i2c_pan/src/main.c b/tests/drivers/i2c/i2c_pan/src/main.c new file mode 100644 index 000000000000..46fe1d40b708 --- /dev/null +++ b/tests/drivers/i2c/i2c_pan/src/main.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define NODE_TWIM DT_NODELABEL(sensor) +#define NODE_TWIS DT_ALIAS(i2c_slave) +#define MEASUREMENT_REPEATS 10 + +#define TWIS_MEMORY_SECTION \ + COND_CODE_1(DT_NODE_HAS_PROP(NODE_TWIS, memory_regions), \ + (__attribute__((__section__( \ + LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(NODE_TWIS, memory_regions)))))), \ + ()) + +#define TEST_BUFFER_SIZE 128 + +static nrfx_twis_t twis = {.p_reg = (NRF_TWIS_Type *)DT_REG_ADDR(NODE_TWIS)}; +static uint8_t i2c_slave_buffer[TEST_BUFFER_SIZE] TWIS_MEMORY_SECTION; +static uint8_t i2c_master_buffer[TEST_BUFFER_SIZE]; + +struct i2c_api_twis_fixture { + const struct device *dev; + uint8_t addr; + uint8_t *const master_buffer; + uint8_t *const slave_buffer; +}; + +static struct i2c_api_twis_fixture fixture = { + .dev = DEVICE_DT_GET(DT_BUS(NODE_TWIM)), + .addr = DT_REG_ADDR(NODE_TWIM), + .master_buffer = i2c_master_buffer, + .slave_buffer = i2c_slave_buffer, +}; + +static void i2s_slave_handler(nrfx_twis_event_t const *p_event) +{ + switch (p_event->type) { + case NRFX_TWIS_EVT_READ_REQ: + nrfx_twis_tx_prepare(&twis, i2c_slave_buffer, TEST_BUFFER_SIZE); + break; + case NRFX_TWIS_EVT_READ_DONE: + break; + case NRFX_TWIS_EVT_WRITE_REQ: + nrfx_twis_rx_prepare(&twis, i2c_slave_buffer, TEST_BUFFER_SIZE); + break; + case NRFX_TWIS_EVT_WRITE_DONE: + break; + default: + break; + } +} + +static void *test_setup(void) +{ + const nrfx_twis_config_t config = { + .addr = {fixture.addr, 0}, + .skip_gpio_cfg = true, + .skip_psel_cfg = true, + }; + int ret; + + zassert_true(device_is_ready(fixture.dev), "TWIM device is not ready"); + zassert_equal(0, nrfx_twis_init(&twis, &config, i2s_slave_handler), + "TWIS initialization failed"); + + PINCTRL_DT_DEFINE(NODE_TWIS); + ret = pinctrl_apply_state(PINCTRL_DT_DEV_CONFIG_GET(NODE_TWIS), PINCTRL_STATE_DEFAULT); + zassert_ok(ret); + + IRQ_CONNECT(DT_IRQN(NODE_TWIS), DT_IRQ(NODE_TWIS, priority), nrfx_twis_irq_handler, &twis, + 0); + + nrfx_twis_enable(&twis); + + return NULL; +} + +static void prepare_test_data(uint8_t *const buffer) +{ + for (size_t counter = 0; counter < TEST_BUFFER_SIZE; counter++) { + buffer[counter] = counter; + } +} + +static void cleanup_buffers(void *nullp) +{ + memset(fixture.slave_buffer, 0, TEST_BUFFER_SIZE); + memset(fixture.master_buffer, 0, TEST_BUFFER_SIZE); +} + +static void configure_twim(void) +{ + uint32_t i2c_config = I2C_SPEED_SET(I2C_SPEED_STANDARD) | I2C_MODE_CONTROLLER; + + zassert_ok(i2c_configure(fixture.dev, i2c_config)); +} + +/* + * MLTPAN-105 + * During I2C transaction, TWIM SCL is 0 either before or after disabling TWIM. + */ +ZTEST(i2c_pan, test_mltpan_105_workaround) +{ + int ret; + uint32_t scl_pin; + + configure_twim(); + prepare_test_data(fixture.master_buffer); + memset(fixture.slave_buffer, 0, TEST_BUFFER_SIZE); + + TC_PRINT("STEP 1: TWIM - TWIS transmission with valid configuration\n"); + scl_pin = nrf_twis_scl_pin_get(twis.p_reg); + TC_PRINT("TWIS SCL pin: 0x%x\n", scl_pin); + ret = i2c_read(fixture.dev, fixture.master_buffer, TEST_BUFFER_SIZE, fixture.addr); + zassert_ok(ret, "i2c_read failed: %d\n", ret); + zassert_mem_equal(fixture.master_buffer, fixture.slave_buffer, TEST_BUFFER_SIZE); + + TC_PRINT("STEP 2: TWIM - TWIS transmission with SCL pulled low (EIO error is expected)\n"); + /* Pull TWIS SCL pin low */ + nrf_twis_scl_pin_set(twis.p_reg, 1 << 31); + nrf_gpio_cfg_output(scl_pin); + nrf_gpio_pin_clear(scl_pin); + TC_PRINT("TWIS SCL pin (disconnected): 0x%x\n", nrf_twis_scl_pin_get(twis.p_reg)); + memset(fixture.slave_buffer, 0, TEST_BUFFER_SIZE); + ret = i2c_read(fixture.dev, fixture.master_buffer, TEST_BUFFER_SIZE, fixture.addr); + zassert_equal(ret, -EIO, "i2c_read failed with different error than expeced (EIO) %d\n", + ret); + + TC_PRINT("STEP 3: TWIM - TWIS transmission after TWIS pin reconfiguration\n"); + /* Restore original TWIS pin configuration */ + PINCTRL_DT_DEFINE(NODE_TWIS); + ret = pinctrl_apply_state(PINCTRL_DT_DEV_CONFIG_GET(NODE_TWIS), PINCTRL_STATE_DEFAULT); + zassert_ok(ret); + TC_PRINT("TWIS SCL pin (reconfigured): 0x%x\n", nrf_twis_scl_pin_get(twis.p_reg)); + + ret = i2c_read(fixture.dev, fixture.master_buffer, TEST_BUFFER_SIZE, fixture.addr); + zassert_ok(ret, "i2c_read failed (after SCL release): %d\n", ret); + zassert_mem_equal(fixture.master_buffer, fixture.slave_buffer, TEST_BUFFER_SIZE); +} + +ZTEST_SUITE(i2c_pan, NULL, test_setup, NULL, cleanup_buffers, NULL); diff --git a/tests/drivers/i2c/i2c_pan/testcase.yaml b/tests/drivers/i2c/i2c_pan/testcase.yaml new file mode 100644 index 000000000000..3e7c4a4824a9 --- /dev/null +++ b/tests/drivers/i2c/i2c_pan/testcase.yaml @@ -0,0 +1,22 @@ +common: + sysbuild: true + depends_on: gpio + harness: ztest + harness_config: + fixture: gpio_loopback + tags: + - drivers + - i2c + - ci_tests_zephyr_drivers_i2c + platform_allow: + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lv10dk/nrf54lv10a/cpuapp + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp + +tests: + drivers.i2c.i2c_pan: {} From 21d701498b6b22848f66f72caa57aef41c04b1a5 Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Fri, 5 Dec 2025 14:03:39 +0100 Subject: [PATCH 147/155] applications: nrf_desktop: doc: dfu: align with MCUboot RAM load Updated the documentation of the DFU application module that is part of the nRF Desktop application to describe the support for the MCUboot RAM load mode. Ref: NCSDK-36374 Signed-off-by: Kamil Piszczek --- applications/nrf_desktop/doc/dfu.rst | 38 +++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/applications/nrf_desktop/doc/dfu.rst b/applications/nrf_desktop/doc/dfu.rst index d5a608c3b000..4a3fd5aca55f 100644 --- a/applications/nrf_desktop/doc/dfu.rst +++ b/applications/nrf_desktop/doc/dfu.rst @@ -47,19 +47,43 @@ If the buffer is small, the host must perform the DFU progress synchronization m MCUboot bootloader mode ======================= -The MCUboot bootloader can either move the image to the primary slot before booting it (``swap mode``) or boot the image directly from the secondary slot (``direct-xip mode``). +This module supports the following modes of the MCUboot bootloader and reports the corresponding bootloader name: -If the MCUboot bootloader in the swap mode is selected, the DFU module does the following: +* ``swap`` (:kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_MOVE`) - ``MCUBOOT`` +* ``direct-xip`` (:kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP`) - ``MCUBOOT+XIP`` +* ``RAM load`` (:kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD`) - ``MCUBOOT`` + +The DFU module relies on the listed Kconfig options that indicate the MCUboot bootloader mode to determine the correct behavior. + +.. caution:: + Other bootloader modes might be compatible with this module, but they are not actively tested as part of the nRF Desktop configurations. + +See the :ref:`nrf_desktop_bootloader` section for more information on the MCUboot bootloader modes. + +Swap mode +--------- + +If this bootloader mode is selected, the DFU module does the following: * Requests the image upgrade after the whole image is transferred over the :ref:`nrf_desktop_config_channel`. * Confirms the running image after the device is rebooted. -If the MCUboot bootloader's direct-xip mode is used, the module does not mark the newly uploaded image as pending and does not confirm it after a successful boot. -In that case, the DFU module assumes that the MCUboot direct-xip bootloader simply boots an image with the higher version, so there is no need to mark the image as pending and confirm it. +Direct-xip mode +--------------- + +If this bootloader mode is selected, the DFU module does not mark the newly uploaded image as pending and does not confirm it after a successful boot. -The :kconfig:option:`CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP` Kconfig option is used to inform the DFU module that the device uses the MCUboot bootloader in the direct-xip mode. -If the option is enabled, the DFU module reports the ``MCUBOOT+XIP`` bootloader name instead of ``MCUBOOT`` to indicate that the bootloader working in the direct-xip mode is used. -See the :ref:`nrf_desktop_bootloader` section for more information on the MCUboot bootloader configuration. +RAM load mode +------------- + +If this bootloader mode is selected, the DFU module does not mark the newly uploaded image as pending and does not confirm it after a successful boot. + +.. note:: + Support for the RAM load mode in this module is experimental. + For more details about the support of the MCUboot RAM load mode in the nRF Desktop application, see the MCUboot :ref:`nrf_desktop_configuring_mcuboot_bootloader_ram_load` section in the nRF Desktop documentation. + +.. note:: + DTS is the only supported partitioning method when you use the MCUboot bootloader in the RAM load mode. Partitioning methods ==================== From 76b4c331c17f31ea52e696b6c94a4533e1a39a54 Mon Sep 17 00:00:00 2001 From: Dominik Chat Date: Thu, 4 Dec 2025 12:20:38 +0100 Subject: [PATCH 148/155] samples: direct_test_mode: Fix gppi implementation Fix the mismatch in API for nrfx_gppi_ep_attach function. Signed-off-by: Dominik Chat --- samples/bluetooth/direct_test_mode/src/dtm.c | 23 ++++++++++---------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/samples/bluetooth/direct_test_mode/src/dtm.c b/samples/bluetooth/direct_test_mode/src/dtm.c index 68e2eea0daff..9219984b1dc7 100644 --- a/samples/bluetooth/direct_test_mode/src/dtm.c +++ b/samples/bluetooth/direct_test_mode/src/dtm.c @@ -1647,16 +1647,16 @@ static void radio_ppi_clear(void) static void radio_ppi_configure(bool rx, uint32_t timer_short_mask) { - nrfx_gppi_ep_attach(dtm_inst.ppi_radio_start, - nrf_egu_event_address_get(DTM_EGU, DTM_EGU_EVENT)); - nrfx_gppi_ep_attach(dtm_inst.ppi_radio_start, - nrf_radio_task_address_get(NRF_RADIO, - rx ? NRF_RADIO_TASK_RXEN : NRF_RADIO_TASK_TXEN)); + nrfx_gppi_ep_attach(nrf_egu_event_address_get(DTM_EGU, DTM_EGU_EVENT), + dtm_inst.ppi_radio_start); + nrfx_gppi_ep_attach(nrf_radio_task_address_get(NRF_RADIO, + rx ? NRF_RADIO_TASK_RXEN : NRF_RADIO_TASK_TXEN), + dtm_inst.ppi_radio_start); atomic_set_bit(&dtm_inst.endpoint_state, (rx ? ENDPOINT_EGU_RADIO_RX : ENDPOINT_EGU_RADIO_TX)); - nrfx_gppi_ep_attach(dtm_inst.ppi_radio_start, - nrf_timer_task_address_get(dtm_inst.timer.p_reg, NRF_TIMER_TASK_START)); + nrfx_gppi_ep_attach(nrf_timer_task_address_get(dtm_inst.timer.p_reg, NRF_TIMER_TASK_START), + dtm_inst.ppi_radio_start); atomic_set_bit(&dtm_inst.endpoint_state, ENDPOINT_FORK_EGU_TIMER); nrfx_gppi_conn_enable(dtm_inst.ppi_radio_start); @@ -1672,10 +1672,11 @@ static void radio_tx_ppi_reconfigure(void) endpoints_clear(); - nrfx_gppi_ep_attach(dtm_inst.ppi_radio_start, - nrf_timer_event_address_get(dtm_inst.timer.p_reg, NRF_TIMER_EVENT_COMPARE0)); - nrfx_gppi_ep_attach(dtm_inst.ppi_radio_start, - nrf_radio_task_address_get(NRF_RADIO, NRF_RADIO_TASK_TXEN)); + nrfx_gppi_ep_attach(nrf_timer_event_address_get(dtm_inst.timer.p_reg, + NRF_TIMER_EVENT_COMPARE0), + dtm_inst.ppi_radio_start); + nrfx_gppi_ep_attach(nrf_radio_task_address_get(NRF_RADIO, NRF_RADIO_TASK_TXEN), + dtm_inst.ppi_radio_start); atomic_set_bit(&dtm_inst.endpoint_state, ENDPOINT_TIMER_RADIO_TX); nrfx_gppi_conn_enable(dtm_inst.ppi_radio_start); } From eef45c336f51a12e63bc8637e77c8d3db2305fbd Mon Sep 17 00:00:00 2001 From: Noah Pendleton Date: Thu, 13 Nov 2025 11:45:19 -0500 Subject: [PATCH 149/155] doc: Memfault integration doc to use "nRF CLoud" Update the doc to use the new naming convention. Signed-off-by: Noah Pendleton --- doc/nrf/external_comp/memfault.rst | 12 ++++++------ doc/nrf/links.txt | 5 ++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/doc/nrf/external_comp/memfault.rst b/doc/nrf/external_comp/memfault.rst index dca0cefa01d4..3081f0f7889f 100644 --- a/doc/nrf/external_comp/memfault.rst +++ b/doc/nrf/external_comp/memfault.rst @@ -1,21 +1,21 @@ .. _ug_memfault: -Memfault integration -#################### +nRF Cloud powered by Memfault integration +######################################### .. contents:: :local: :depth: 2 -`Memfault`_ is a cloud-based web application with |NCS| compatibility that monitors devices and allows you to debug issues remotely. -Memfault integration provides the following features to |NCS|: +`nRF Cloud`_ now integrates Memfault technology to monitor devices and allows you to debug issues remotely. +This integration provides the following features to |NCS|: -* `Remote debugging `_ - Memfault issues can be efficiently resolved with automatic detection, alerts, deduplication, and actionable insights sent through the cloud. +* `Remote debugging `_ - Issues can be efficiently resolved with automatic detection, alerts, deduplication, and actionable insights sent through the cloud. * `Continuous monitoring `_ - Monitors device and fleet-level metrics like connectivity and low power state in real-time dashboards and displays prepopulated metrics for your devices. You can access device level data to resolve bugs faster. -See the `Memfault sandbox `_ for a self-guided tour of the platform as well as the `Memfault documentation `_ for more details. +See the `Memfault documentation `_ for more details. .. note:: Memfault has been integrated in |NCS| since the v1.6.0 release. diff --git a/doc/nrf/links.txt b/doc/nrf/links.txt index ca6f8e5156e1..f8f2cf7024ed 100644 --- a/doc/nrf/links.txt +++ b/doc/nrf/links.txt @@ -1492,7 +1492,7 @@ .. _`Memfault`: https://memfault.com/ -.. _`Memfault registration page`: https://app.memfault.com/register-nordic +.. _`Memfault registration page`: https://app.nrfcloud.com/#/register .. _`Memfault Dashboards`: https://app.memfault.com .. _`Memfault Docs`: https://docs.memfault.com/ @@ -1513,11 +1513,10 @@ .. _`Memfault MCU Guide`: https://docs.memfault.com/docs/mcu/introduction .. _`Memfault: Reboot tracking`: https://docs.memfault.com/docs/mcu/reboot-reason-tracking .. _`Memfault: Coredumps`: https://docs.memfault.com/docs/mcu/coredumps -.. _`Memfault Sandbox`: https://mflt.io/demo .. ### Source: *.nrfcloud.com, https://docs.nordicsemi.com/bundle/nrf-cloud/ -.. _`nRF Cloud`: +.. _`nRF Cloud`: https://nrfcloud.com/ .. _`nRF Connect for Cloud`: https://nrfcloud.com/ .. _`User Account`: https://nrfcloud.com/#/account .. _`Provision Devices`: https://nrfcloud.com/#/provision-devices From ff60bec12b29005e73d516018eecb2f7bee0e3cf Mon Sep 17 00:00:00 2001 From: Bartosz Miller Date: Fri, 5 Dec 2025 15:40:18 +0100 Subject: [PATCH 150/155] tests: drivers: pwm: Update PWM events test Add COMPAREMATCH event testing and PPI trace debug option. Signed-off-by: Bartosz Miller --- .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 6 +++- .../boards/nrf54l15dk_nrf54l15_cpuapp.overlay | 6 +++- .../nrf54lm20dk_nrf54lm20a_cpuapp.overlay | 6 +++- .../nrf54ls05dk_nrf54ls05b_cpuapp.overlay | 4 +++ tests/drivers/pwm/pwm_events/prj.conf | 3 ++ tests/drivers/pwm/pwm_events/src/main.c | 36 +++++++++++++++++-- 6 files changed, 56 insertions(+), 5 deletions(-) diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 6227ed62ea43..1d534946b507 100644 --- a/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/pwm/pwm_events/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -18,6 +18,10 @@ tst_timer: &timer131 { status = "okay"; }; -pwm_led: &led2 { +pwm_led: &led3 { + status = "okay"; +}; + +debug_pin: &led1 { status = "okay"; }; diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index 908b8dc6caf9..c3ad86a33111 100644 --- a/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/pwm/pwm_events/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -16,6 +16,10 @@ tst_timer: &timer20 { status = "okay"; }; -pwm_led: &led2 { +pwm_led: &led3 { + status = "okay"; +}; + +debug_pin: &led1 { status = "okay"; }; diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 908b8dc6caf9..c3ad86a33111 100644 --- a/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay +++ b/tests/drivers/pwm/pwm_events/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -16,6 +16,10 @@ tst_timer: &timer20 { status = "okay"; }; -pwm_led: &led2 { +pwm_led: &led3 { + status = "okay"; +}; + +debug_pin: &led1 { status = "okay"; }; diff --git a/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay b/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay index 8bac2dbf0feb..72670ffbfb3b 100644 --- a/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay +++ b/tests/drivers/pwm/pwm_events/boards/nrf54ls05dk_nrf54ls05b_cpuapp.overlay @@ -19,3 +19,7 @@ tst_timer: &timer20 { pwm_led: &led0 { status = "okay"; }; + +debug_pin: &led1 { + status = "okay"; +}; diff --git a/tests/drivers/pwm/pwm_events/prj.conf b/tests/drivers/pwm/pwm_events/prj.conf index 66a4e32479e4..84730bb7a104 100644 --- a/tests/drivers/pwm/pwm_events/prj.conf +++ b/tests/drivers/pwm/pwm_events/prj.conf @@ -3,3 +3,6 @@ CONFIG_NRFX_TIMER=y CONFIG_NRFX_GPPI=y CONFIG_ZTEST=y + +# Enable for debugging purposes only +CONFIG_PPI_TRACE=n diff --git a/tests/drivers/pwm/pwm_events/src/main.c b/tests/drivers/pwm/pwm_events/src/main.c index 672b13c25fb0..102728946390 100644 --- a/tests/drivers/pwm/pwm_events/src/main.c +++ b/tests/drivers/pwm/pwm_events/src/main.c @@ -9,9 +9,14 @@ #include #include #include +#include #define PWM_OUTPUT_PIN NRF_DT_GPIOS_TO_PSEL(DT_NODELABEL(pwm_led), gpios) +#if defined(CONFIG_PPI_TRACE) +#define DEBUG_PIN NRF_DT_GPIOS_TO_PSEL(DT_NODELABEL(debug_pin), gpios) +#endif + #define SLEEP_TIME_MS 500 struct pwm_events_fixture { @@ -30,6 +35,7 @@ static void configure_pwm(nrfx_pwm_t *pwm) NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED); pwm_config.count_mode = NRF_PWM_MODE_UP_AND_DOWN; + pwm_config.top_value = 0x1000; zassert_ok(nrfx_pwm_init(pwm, &pwm_config, NULL, NULL), "NRFX PWM init failed\n"); } @@ -72,11 +78,27 @@ static void run_pwm_event_test_case(struct pwm_events_fixture *fixture, uint32_t pwm_event_address; uint32_t timer_cc_before, timer_cc_after; +#if defined(CONFIG_PPI_TRACE) + void *handle; +#endif + pwm_event_address = nrf_pwm_event_address_get(fixture->pwm->p_reg, tested_pwm_event); setup_dppi_connection(&fixture->gppi_handle, fixture->domain_id, fixture->timer_task_address, pwm_event_address); - nrf_pwm_event_clear(fixture->pwm->p_reg, tested_pwm_event); + +#if defined(CONFIG_PPI_TRACE) + /* + * Note that configuring PPI trace + * will break DPPI connection to the timer. + * Timer will not count events + */ + handle = ppi_trace_config(DEBUG_PIN, pwm_event_address); + zassert_not_null(handle, "PPI trace configuration failed\n"); + ppi_trace_enable(handle); +#endif + + timer_cc_before = nrfx_timer_capture(fixture->test_timer, NRF_TIMER_CC_CHANNEL0); nrfx_pwm_simple_playback(fixture->pwm, fixture->pwm_sequence, 1, NRFX_PWM_FLAG_STOP); k_msleep(SLEEP_TIME_MS); @@ -89,6 +111,10 @@ static void run_pwm_event_test_case(struct pwm_events_fixture *fixture, nrf_pwm_event_clear(fixture->pwm->p_reg, tested_pwm_event); clear_dppi_connection(&fixture->gppi_handle, fixture->domain_id, fixture->timer_task_address, pwm_event_address); + +#if defined(CONFIG_PPI_TRACE) + ppi_trace_disable(handle); +#endif } ZTEST_F(pwm_events, test_pwm_stop_event) @@ -117,12 +143,18 @@ ZTEST_F(pwm_events, test_pwm_loopsdone_event) run_pwm_event_test_case(fixture, NRF_PWM_EVENT_LOOPSDONE, 1, "LOOPSDONE"); } +ZTEST_F(pwm_events, test_pwm_comparematch_event) +{ + run_pwm_event_test_case(fixture, offsetof(NRF_PWM_Type, EVENTS_COMPAREMATCH[0]), + fixture->pwm_sequence->length * 2, "COMPAREMATCH"); +} + static void *test_setup(void) { static struct pwm_events_fixture fixture; static nrfx_timer_t test_timer = NRFX_TIMER_INSTANCE(DT_REG_ADDR(DT_NODELABEL(tst_timer))); static nrfx_pwm_t pwm = NRFX_PWM_INSTANCE(DT_REG_ADDR(DT_NODELABEL(dut_pwm))); - static nrf_pwm_values_common_t pwm_duty_cycle_values[] = {0x500, 0x600}; + static nrf_pwm_values_common_t pwm_duty_cycle_values[] = {0x500, 0x600, 0x500, 0x600}; static nrf_pwm_sequence_t pwm_sequence = {.values = {pwm_duty_cycle_values}, .length = ARRAY_SIZE(pwm_duty_cycle_values), .repeats = 0, From 8fc29123919b46c24e4a35d6964d4d41669e565c Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Fri, 5 Dec 2025 15:59:45 +0000 Subject: [PATCH 151/155] manifest: Update sdk-nrfxlib revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-nrfxlib/pull/1957 Signed-off-by: Nordic Builder --- west.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/west.yml b/west.yml index e4e99e314ae1..e6c643a7ad64 100644 --- a/west.yml +++ b/west.yml @@ -143,7 +143,7 @@ manifest: - name: nrfxlib repo-path: sdk-nrfxlib path: nrfxlib - revision: 89a9dd32358bc2ca846e2f47fa7cce60d0688ccb + revision: 9ef8718adab25805858c70f7ce46705c7488b7c1 - name: trusted-firmware-m repo-path: sdk-trusted-firmware-m path: modules/tee/tf-m/trusted-firmware-m @@ -181,7 +181,7 @@ manifest: # Only for internal Nordic development repo-path: dragoon.git remote: dragoon - revision: d2500b737245346047ffbfe925048a3f1a5dd8aa + revision: dbf89b7bb05209a68fe2f28b8132fb6b1e1b2368 groups: - dragoon - name: cjson From b58ef39469bf125d47c218a1af9fb63461bfada6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Ga=C5=82at?= Date: Thu, 27 Nov 2025 11:46:26 +0100 Subject: [PATCH 152/155] bt_rpc: fix issue with cleaning gatt buffer after last service is removed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixed memory leak on multiple bt init/disable calls. Signed-off-by: Robert Gałat --- subsys/bluetooth/rpc/common/bt_rpc_gatt_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/rpc/common/bt_rpc_gatt_common.c b/subsys/bluetooth/rpc/common/bt_rpc_gatt_common.c index 6c369d0c669f..a63f1181610a 100644 --- a/subsys/bluetooth/rpc/common/bt_rpc_gatt_common.c +++ b/subsys/bluetooth/rpc/common/bt_rpc_gatt_common.c @@ -92,7 +92,7 @@ const struct bt_gatt_attr *bt_rpc_gatt_index_to_attr(uint32_t index) const struct bt_gatt_service *bt_rpc_gatt_get_service_by_index(uint16_t svc_index) { - if (svc_index > svc_cache.count) { + if (svc_index >= svc_cache.count) { return NULL; } From c77d26c5db32019cbf06b6ed8d988f7f829d93f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Ga=C5=82at?= Date: Fri, 28 Nov 2025 14:13:50 +0100 Subject: [PATCH 153/155] bt_rpc: Added unit test to check for gatt service registration cycle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit check if gatt services are correctly clean after remove Signed-off-by: Robert Gałat --- CODEOWNERS | 1 + .../bluetooth/rpc/common/bt_rpc_gatt_common.c | 11 +- subsys/bluetooth/rpc/host/bt_rpc_gatt_host.c | 1 + .../bluetooth/rpc_gatt_service/CMakeLists.txt | 29 ++ .../bluetooth/rpc_gatt_service/prj.conf | 10 + .../bluetooth/rpc_gatt_service/src/log_stub.c | 13 + .../bluetooth/rpc_gatt_service/src/main.c | 414 ++++++++++++++++++ .../rpc_gatt_service/src/nrf_rpc_cbor.h | 16 + .../rpc_gatt_service/src/test_config.h | 27 ++ .../bluetooth/rpc_gatt_service/testcase.yaml | 9 + 10 files changed, 528 insertions(+), 3 deletions(-) create mode 100644 tests/subsys/bluetooth/rpc_gatt_service/CMakeLists.txt create mode 100644 tests/subsys/bluetooth/rpc_gatt_service/prj.conf create mode 100644 tests/subsys/bluetooth/rpc_gatt_service/src/log_stub.c create mode 100644 tests/subsys/bluetooth/rpc_gatt_service/src/main.c create mode 100644 tests/subsys/bluetooth/rpc_gatt_service/src/nrf_rpc_cbor.h create mode 100644 tests/subsys/bluetooth/rpc_gatt_service/src/test_config.h create mode 100644 tests/subsys/bluetooth/rpc_gatt_service/testcase.yaml diff --git a/CODEOWNERS b/CODEOWNERS index fa4d2adde995..60ff3dbb6a3b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -926,6 +926,7 @@ /tests/subsys/bluetooth/enocean/ @nrfconnect/ncs-paladin /tests/subsys/bluetooth/fast_pair/ @nrfconnect/ncs-si-bluebagel /tests/subsys/bluetooth/mesh/ @nrfconnect/ncs-paladin +/tests/subsys/bluetooth/rpc_gatt_service/ @nrfconnect/ncs-protocols-serialization /tests/subsys/bootloader/ @nrfconnect/ncs-eris /tests/subsys/caf/ @nrfconnect/ncs-si-muffin @nrfconnect/ncs-si-bluebagel /tests/subsys/debug/cpu_load/ @nordic-krch diff --git a/subsys/bluetooth/rpc/common/bt_rpc_gatt_common.c b/subsys/bluetooth/rpc/common/bt_rpc_gatt_common.c index a63f1181610a..f350735e8980 100644 --- a/subsys/bluetooth/rpc/common/bt_rpc_gatt_common.c +++ b/subsys/bluetooth/rpc/common/bt_rpc_gatt_common.c @@ -81,9 +81,14 @@ const struct bt_gatt_attr *bt_rpc_gatt_index_to_attr(uint32_t index) { uint32_t service_index = index >> ATTR_INDEX_POS; uint32_t attr_index = index & ATTR_INDEX_MASK; - const struct bt_gatt_service *service = svc_cache.services[service_index]; + const struct bt_gatt_service *service; + + if (service_index >= svc_cache.count) { + return NULL; + } - if ((service_index >= svc_cache.count) || (attr_index >= service->attr_count)) { + service = svc_cache.services[service_index]; + if (!service || (attr_index >= service->attr_count)) { return NULL; } @@ -203,7 +208,7 @@ void bt_rpc_gatt_foreach_attr_type(uint16_t start_handle, uint16_t end_handle, } for (size_t j = 0; j < svc->attr_count; j++) { - struct bt_gatt_attr *attr = &svc->attrs[j]; + const struct bt_gatt_attr *attr = &svc->attrs[j]; handle = bt_gatt_attr_get_handle(attr); diff --git a/subsys/bluetooth/rpc/host/bt_rpc_gatt_host.c b/subsys/bluetooth/rpc/host/bt_rpc_gatt_host.c index 5721bc82152d..c159970b9aa3 100644 --- a/subsys/bluetooth/rpc/host/bt_rpc_gatt_host.c +++ b/subsys/bluetooth/rpc/host/bt_rpc_gatt_host.c @@ -729,6 +729,7 @@ static void bt_rpc_gatt_service_unregister_rpc_handler(const struct nrf_rpc_grou svc = bt_rpc_gatt_get_service_by_index(svc_index); if (!svc) { + LOG_ERR("Service unregister: Invalid service index %u", svc_index); result = -EINVAL; } diff --git a/tests/subsys/bluetooth/rpc_gatt_service/CMakeLists.txt b/tests/subsys/bluetooth/rpc_gatt_service/CMakeLists.txt new file mode 100644 index 000000000000..2ac48cfd6e84 --- /dev/null +++ b/tests/subsys/bluetooth/rpc_gatt_service/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bluetooth_rpc_gatt_service_test) + +FILE(GLOB app_sources src/*.c) + +target_include_directories(app PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${ZEPHYR_NRF_MODULE_DIR}/subsys/bluetooth/rpc/common +) + +# Include the source file directly for unit testing +target_sources(app PRIVATE + ${app_sources} + ${ZEPHYR_NRF_MODULE_DIR}/subsys/bluetooth/rpc/common/bt_rpc_gatt_common.c +) + +# Include test config header before compilation to define config values +# that aren't available via Kconfig without CONFIG_BT_RPC +target_compile_options(app PRIVATE + -include ${CMAKE_CURRENT_SOURCE_DIR}/src/test_config.h +) diff --git a/tests/subsys/bluetooth/rpc_gatt_service/prj.conf b/tests/subsys/bluetooth/rpc_gatt_service/prj.conf new file mode 100644 index 000000000000..6788ff2194a3 --- /dev/null +++ b/tests/subsys/bluetooth/rpc_gatt_service/prj.conf @@ -0,0 +1,10 @@ +CONFIG_ZTEST=y + + + +# Minimal configuration for testing service cache only +# Note: CONFIG_BT_RPC_GATT_SRV_MAX and CONFIG_BT_RPC_LOG_LEVEL are defined +# via compile definitions in CMakeLists.txt since they require CONFIG_BT_RPC + +# Logging (minimal) +CONFIG_LOG=y diff --git a/tests/subsys/bluetooth/rpc_gatt_service/src/log_stub.c b/tests/subsys/bluetooth/rpc_gatt_service/src/log_stub.c new file mode 100644 index 000000000000..f8d6d81e10b2 --- /dev/null +++ b/tests/subsys/bluetooth/rpc_gatt_service/src/log_stub.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + * + * Stub implementation for logging module to avoid linker errors + * when testing without full BT RPC stack + */ + +#include + +/* Stub the log constant structure that's normally generated */ +LOG_MODULE_REGISTER(BT_RPC, 4); diff --git a/tests/subsys/bluetooth/rpc_gatt_service/src/main.c b/tests/subsys/bluetooth/rpc_gatt_service/src/main.c new file mode 100644 index 000000000000..367fd619b7a0 --- /dev/null +++ b/tests/subsys/bluetooth/rpc_gatt_service/src/main.c @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + + +#include + +/* Test helper: Get service count by checking until NULL */ +static size_t get_service_count(void) +{ + size_t count = 0; + + while (bt_rpc_gatt_get_service_by_index(count) != NULL) { + count++; + } + + return count; +} + +/* Test helper: Check if buffer is empty by verifying no services exist */ +static bool is_buffer_empty(void) +{ + return get_service_count() == 0; +} + +/* Test UUIDs - minimal structure for testing */ +static struct bt_uuid test_uuid_1 = {.type = 0x10}; +static struct bt_uuid test_uuid_2 = {.type = 0x11}; +static struct bt_uuid test_uuid_3 = {.type = 0x12}; + +/* Test attributes - minimal structure for testing */ +static struct bt_gatt_attr test_attrs_1[] = { + { + .uuid = &test_uuid_1, + .handle = 1, + .perm = 0, + .read = NULL, + .write = NULL, + .user_data = NULL, + }, + { + .uuid = &test_uuid_1, + .handle = 2, + .perm = 0, + .read = NULL, + .write = NULL, + .user_data = (void *)0x1234, + }, +}; + +static struct bt_gatt_attr test_attrs_2[] = { + { + .uuid = &test_uuid_2, + .handle = 3, + .perm = 0, + .read = NULL, + .write = NULL, + .user_data = NULL, + }, + { + .uuid = &test_uuid_2, + .handle = 4, + .perm = 0, + .read = NULL, + .write = NULL, + .user_data = (void *)0x5678, + }, +}; + +static struct bt_gatt_attr test_attrs_3[] = { + { + .uuid = &test_uuid_3, + .handle = 5, + .perm = 0, + .read = NULL, + .write = NULL, + .user_data = NULL, + }, + { + .uuid = &test_uuid_3, + .handle = 6, + .perm = 0, + .read = NULL, + .write = NULL, + .user_data = (void *)0x9ABC, + }, +}; + +static struct bt_gatt_service test_svc_1 = { + .attrs = test_attrs_1, + .attr_count = ARRAY_SIZE(test_attrs_1), +}; + +static struct bt_gatt_service test_svc_2 = { + .attrs = test_attrs_2, + .attr_count = ARRAY_SIZE(test_attrs_2), +}; + +static struct bt_gatt_service test_svc_3 = { + .attrs = test_attrs_3, + .attr_count = ARRAY_SIZE(test_attrs_3), +}; + +/** + * @brief Test setup - verify initial state is empty + */ +static void test_setup(void *fixture) +{ + ARG_UNUSED(fixture); + /* Verify initial state is empty */ + zassert_true(is_buffer_empty(), "Buffer should be empty initially"); +} + +/** + * @brief Test teardown - cleanup all services + */ +static void test_teardown(void *fixture) +{ + ARG_UNUSED(fixture); + size_t count = get_service_count(); + + /* Remove all services */ + for (size_t i = 0; i < count; i++) { + const struct bt_gatt_service *svc = bt_rpc_gatt_get_service_by_index(0); + + if (svc) { + bt_rpc_gatt_remove_service(svc); + } + } + + /* Verify cleanup */ + zassert_true(is_buffer_empty(), "Buffer should be empty after teardown"); +} + +/** + * @brief Test: Register a single service and verify it's added + */ +ZTEST(bt_rpc_gatt_service, test_register_single_service) +{ + uint32_t svc_index; + int err; + + /* Register service */ + err = bt_rpc_gatt_add_service(&test_svc_1, &svc_index); + zassert_equal(err, 0, "Service registration should succeed"); + zassert_equal(svc_index, 0, "First service should have index 0"); + + /* Verify service count */ + zassert_equal(get_service_count(), 1, "Service count should be 1"); + + /* Verify service can be retrieved */ + const struct bt_gatt_service *retrieved = bt_rpc_gatt_get_service_by_index(0); + + zassert_not_null(retrieved, "Service should be retrievable"); + zassert_equal(retrieved, &test_svc_1, "Retrieved service should match"); +} + +/** + * @brief Test: Register multiple services and verify all are added + */ +ZTEST(bt_rpc_gatt_service, test_register_multiple_services) +{ + uint32_t svc_index_1, svc_index_2, svc_index_3; + int err; + + /* Register first service */ + err = bt_rpc_gatt_add_service(&test_svc_1, &svc_index_1); + zassert_equal(err, 0, "First service registration should succeed"); + zassert_equal(svc_index_1, 0, "First service should have index 0"); + + /* Register second service */ + err = bt_rpc_gatt_add_service(&test_svc_2, &svc_index_2); + zassert_equal(err, 0, "Second service registration should succeed"); + zassert_equal(svc_index_2, 1, "Second service should have index 1"); + + /* Register third service */ + err = bt_rpc_gatt_add_service(&test_svc_3, &svc_index_3); + zassert_equal(err, 0, "Third service registration should succeed"); + zassert_equal(svc_index_3, 2, "Third service should have index 2"); + + /* Verify service count */ + zassert_equal(get_service_count(), 3, "Service count should be 3"); + + /* Verify all services can be retrieved */ + zassert_not_null(bt_rpc_gatt_get_service_by_index(0), "Service 0 should exist"); + zassert_not_null(bt_rpc_gatt_get_service_by_index(1), "Service 1 should exist"); + zassert_not_null(bt_rpc_gatt_get_service_by_index(2), "Service 2 should exist"); +} + +/** + * @brief Test: Deregister all services and verify buffer is reset + * + */ +ZTEST(bt_rpc_gatt_service, test_deregister_all_services_resets_buffer) +{ + uint32_t svc_index_1, svc_index_2, svc_index_3; + int err; + size_t initial_count, after_remove_count, final_count; + + /* Get initial state */ + initial_count = get_service_count(); + zassert_true(initial_count == 0, "Initial state should be empty"); + + /* Register 3 services */ + err = bt_rpc_gatt_add_service(&test_svc_1, &svc_index_1); + zassert_equal(err, 0, "Service 1 registration should succeed"); + + err = bt_rpc_gatt_add_service(&test_svc_2, &svc_index_2); + zassert_equal(err, 0, "Service 2 registration should succeed"); + + err = bt_rpc_gatt_add_service(&test_svc_3, &svc_index_3); + zassert_equal(err, 0, "Service 3 registration should succeed"); + + /* Verify all services are registered */ + zassert_equal(get_service_count(), 3, "All 3 services should be registered"); + + /* Remove first service */ + err = bt_rpc_gatt_remove_service(&test_svc_1); + zassert_equal(err, 0, "Service 1 removal should succeed"); + after_remove_count = get_service_count(); + zassert_equal(after_remove_count, 2, "Service count should be 2 after removing first"); + + /* Remove second service */ + err = bt_rpc_gatt_remove_service(&test_svc_2); + zassert_equal(err, 0, "Service 2 removal should succeed"); + zassert_equal(get_service_count(), 1, "Service count should be 1 after removing second"); + + /* Remove last service - this should trigger buffer reset */ + err = bt_rpc_gatt_remove_service(&test_svc_3); + zassert_equal(err, 0, "Service 3 removal should succeed"); + + /* Verify buffer is empty after removing all services */ + final_count = get_service_count(); + zassert_equal(final_count, 0, "Service count should be 0 after removing all services"); + zassert_true(is_buffer_empty(), "Buffer should be empty after removing all services"); + + /* Verify no services can be retrieved */ + zassert_is_null(bt_rpc_gatt_get_service_by_index(0), + "Service at index 0 should not exist after cleanup"); +} + +/** + * @brief Test: Multiple init/disable cycles + * + * This test simulates multiple bt_init/bt_disable cycles to ensure + * the buffer doesn't leak memory across cycles. + */ +ZTEST(bt_rpc_gatt_service, test_multiple_init_disable_cycles) +{ + const int num_cycles = 10; + uint32_t svc_index; + int err; + + for (int cycle = 0; cycle < num_cycles; cycle++) { + svc_index = (uint32_t)-1; + /* Verify initial state is empty */ + zassert_true(is_buffer_empty(), "Buffer should be empty at start of cycle %d", + cycle); + + /* Register service (simulating bt_init) */ + err = bt_rpc_gatt_add_service(&test_svc_1, &svc_index); + zassert_equal(err, 0, "Service registration should succeed in cycle %d", cycle); + zassert_equal(get_service_count(), 1, "Service count should be 1 in cycle %d", + cycle); + /* svc_index should be valid and when we retrieve the service by + * index it should be the same test_svc_1 that was added + */ + zassert_not_equal(svc_index, (uint32_t)-1, "svc_index should be valid in cycle %d", + cycle); + const struct bt_gatt_service *svc = bt_rpc_gatt_get_service_by_index(svc_index); + + zassert_not_null(svc, "Service should be retrievable by index in cycle %d", cycle); + zassert_equal_ptr(svc, &test_svc_1, + "Service at index should match test_svc_1 in cycle %d", cycle); + + /* Deregister service (simulating bt_disable) */ + err = bt_rpc_gatt_remove_service(&test_svc_1); + zassert_equal(err, 0, "Service removal should succeed in cycle %d", cycle); + + /* Verify buffer is empty after each cycle */ + zassert_true(is_buffer_empty(), "Buffer should be empty after cycle %d", cycle); + zassert_equal(get_service_count(), 0, "Service count should be 0 after cycle %d", + cycle); + } +} + +/** + * @brief Test: Remove services in different orders + */ +ZTEST(bt_rpc_gatt_service, test_remove_services_different_orders) +{ + uint32_t svc_index_1, svc_index_2, svc_index_3; + int err; + + /* Register 3 services */ + bt_rpc_gatt_add_service(&test_svc_1, &svc_index_1); + bt_rpc_gatt_add_service(&test_svc_2, &svc_index_2); + bt_rpc_gatt_add_service(&test_svc_3, &svc_index_3); + + zassert_equal(get_service_count(), 3, "All services should be registered"); + + /* Remove middle service first */ + err = bt_rpc_gatt_remove_service(&test_svc_2); + zassert_equal(err, 0, "Middle service removal should succeed"); + zassert_equal(get_service_count(), 2, "Service count should be 2"); + + /* Remove last service */ + err = bt_rpc_gatt_remove_service(&test_svc_3); + zassert_equal(err, 0, "Last service removal should succeed"); + zassert_equal(get_service_count(), 1, "Service count should be 1"); + + /* Remove first service (last remaining) */ + err = bt_rpc_gatt_remove_service(&test_svc_1); + zassert_equal(err, 0, "First service removal should succeed"); + + /* Verify buffer is empty */ + zassert_true(is_buffer_empty(), "Buffer should be empty after removing all services"); +} + +/** + * @brief Test: Service count should not exceed maximum even with many services + * + * This test adds services up to the maximum allowed and verifies that: + * 1. We can add up to CONFIG_BT_RPC_GATT_SRV_MAX services + * 2. Adding more than the maximum fails + * 3. Removing services allows adding new ones again + * 4. The count never exceeds the maximum + */ +ZTEST(bt_rpc_gatt_service, test_service_count_never_exceeds_maximum) +{ + const size_t max_services = CONFIG_BT_RPC_GATT_SRV_MAX; + struct bt_gatt_service test_services[10]; + struct bt_gatt_attr test_attrs_array[10][2]; + uint32_t svc_indices[10]; + int err; + size_t count; + + /* Create test services */ + for (size_t i = 0; i < 10; i++) { + test_attrs_array[i][0] = (struct bt_gatt_attr){ + .uuid = &test_uuid_1, + .handle = (uint16_t)(i * 10 + 1), + .perm = 0, + .read = NULL, + .write = NULL, + .user_data = NULL, + }; + test_attrs_array[i][1] = (struct bt_gatt_attr){ + .uuid = &test_uuid_1, + .handle = (uint16_t)(i * 10 + 2), + .perm = 0, + .read = NULL, + .write = NULL, + .user_data = (void *)(uintptr_t)(i + 100), + }; + test_services[i] = (struct bt_gatt_service){ + .attrs = test_attrs_array[i], + .attr_count = 2, + }; + } + + /* Add services up to maximum */ + for (size_t i = 0; i < max_services; i++) { + err = bt_rpc_gatt_add_service(&test_services[i], &svc_indices[i]); + zassert_equal(err, 0, "Adding service %zu should succeed", i); + count = get_service_count(); + zassert_equal(count, i + 1, "Service count should be %zu after adding service %zu", + i + 1, i); + zassert_true(count <= max_services, + "Service count (%zu) should not exceed maximum (%zu)", count, + max_services); + } + + /* Verify we're at maximum */ + count = get_service_count(); + zassert_equal(count, max_services, "Service count should equal maximum (%zu)", + max_services); + + /* Try to add one more - should fail */ + err = bt_rpc_gatt_add_service(&test_services[max_services], &svc_indices[max_services]); + zassert_not_equal(err, 0, "Adding service beyond maximum should fail"); + count = get_service_count(); + zassert_equal(count, max_services, "Service count should still be %zu after failed add", + max_services); + + /* Remove all services */ + for (size_t i = 0; i < max_services; i++) { + err = bt_rpc_gatt_remove_service(&test_services[i]); + zassert_equal(err, 0, "Removing service %zu should succeed", i); + count = get_service_count(); + zassert_equal(count, max_services - i - 1, + "Service count should be %zu after removing service %zu", + max_services - i - 1, i); + } + + /* Verify empty state */ + count = get_service_count(); + zassert_equal(count, 0, "Service count should be 0 after removing all"); + zassert_true(is_buffer_empty(), "Buffer should be empty after removing all services"); + + /* Now we should be able to add services again */ + err = bt_rpc_gatt_add_service(&test_svc_1, &svc_indices[0]); + zassert_equal(err, 0, "Should be able to add service after cleanup"); + count = get_service_count(); + zassert_equal(count, 1, "Service count should be 1 after re-adding"); +} + +ZTEST_SUITE(bt_rpc_gatt_service, NULL, NULL, test_setup, test_teardown, NULL); diff --git a/tests/subsys/bluetooth/rpc_gatt_service/src/nrf_rpc_cbor.h b/tests/subsys/bluetooth/rpc_gatt_service/src/nrf_rpc_cbor.h new file mode 100644 index 000000000000..f78ef9a6bb85 --- /dev/null +++ b/tests/subsys/bluetooth/rpc_gatt_service/src/nrf_rpc_cbor.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + * + * Stub header for nRF RPC CBOR types needed for unit testing + */ + +#ifndef NRF_RPC_CBOR_H_ +#define NRF_RPC_CBOR_H_ + +/* Forward declaration - full definition not needed for unit testing */ +struct nrf_rpc_cbor_ctx; + + +#endif /* NRF_RPC_CBOR_H_ */ diff --git a/tests/subsys/bluetooth/rpc_gatt_service/src/test_config.h b/tests/subsys/bluetooth/rpc_gatt_service/src/test_config.h new file mode 100644 index 000000000000..a45676044de4 --- /dev/null +++ b/tests/subsys/bluetooth/rpc_gatt_service/src/test_config.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + * + * Test configuration header - defines config values needed for unit testing + * without full BT RPC stack + * + * This header is included via -include flag to ensure it's processed before + * any source files that need these definitions. + */ + +#ifndef TEST_CONFIG_H_ +#define TEST_CONFIG_H_ + +/* Undefine first in case they're defined elsewhere, then define our test values */ +#ifdef CONFIG_BT_RPC_GATT_SRV_MAX +#undef CONFIG_BT_RPC_GATT_SRV_MAX +#endif +#define CONFIG_BT_RPC_GATT_SRV_MAX 10 + +#ifdef CONFIG_BT_RPC_LOG_LEVEL +#undef CONFIG_BT_RPC_LOG_LEVEL +#endif +#define CONFIG_BT_RPC_LOG_LEVEL 4 + +#endif /* TEST_CONFIG_H_ */ diff --git a/tests/subsys/bluetooth/rpc_gatt_service/testcase.yaml b/tests/subsys/bluetooth/rpc_gatt_service/testcase.yaml new file mode 100644 index 000000000000..f61537c1aa4d --- /dev/null +++ b/tests/subsys/bluetooth/rpc_gatt_service/testcase.yaml @@ -0,0 +1,9 @@ +tests: + bluetooth.rpc_gatt_service: + platform_allow: native_sim + tags: + - ci_build + - bluetooth + - ci_tests_subsys_bluetooth + integration_platforms: + - native_sim From 1f335c7a89b3cef23fcd7fced39ac4d173bc6636 Mon Sep 17 00:00:00 2001 From: Noah Pendleton Date: Thu, 13 Nov 2025 11:54:14 -0500 Subject: [PATCH 154/155] lib: hw_id: change name "BLE" to "Bluetooth"/"BT" Rename the option and the name string to adhere to Bluetooth naming convention. See original suggestion here: https://github.com/nrfconnect/sdk-nrf/pull/25313#discussion_r2503993542 Signed-off-by: Noah Pendleton --- doc/nrf/libraries/others/hw_id.rst | 2 +- .../releases/release-notes-changelog.rst | 4 ++++ include/hw_id.h | 2 +- lib/hw_id/Kconfig | 4 ++-- lib/hw_id/hw_id.c | 10 +++++----- samples/hw_id/overlay-ble-mac.conf | 2 +- tests/lib/hw_id/src/kconfig_override_ble.h | 2 +- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/doc/nrf/libraries/others/hw_id.rst b/doc/nrf/libraries/others/hw_id.rst index 63e840531994..a3df269f77b3 100644 --- a/doc/nrf/libraries/others/hw_id.rst +++ b/doc/nrf/libraries/others/hw_id.rst @@ -21,7 +21,7 @@ You can configure one of the following Kconfig options to choose the hardware ID * :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_IMEI` - This option specifies the :term:`International Mobile (Station) Equipment Identity (IMEI)` of the modem. * :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_UUID` - This option specifies the UUID of the modem. -* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC` - This option specifies the default Bluetooth® Low Energy MAC address. +* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_BT_DEVICE_ADDRESS` - This option specifies the Bluetooth® Device Address. * :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC` - This option specifies the MAC address of the default network interface. * :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID` - This option specifies a serial number provided by Zephyr's HW Info API. diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index e02fa56f0eb3..33f90c541a2c 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -435,6 +435,10 @@ Other libraries |no_changes_yet_note| +* :ref:`lib_hw_id` library: + + * The ``CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC`` Kconfig option has been renamed to :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_BT_DEVICE_ADDRESS`. + Shell libraries --------------- diff --git a/include/hw_id.h b/include/hw_id.h index dc1fc10de33d..41c2a39bf873 100644 --- a/include/hw_id.h +++ b/include/hw_id.h @@ -19,7 +19,7 @@ extern "C" { #endif -#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC) +#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BT_DEVICE_ADDRESS) #define HW_ID_LEN (12 + 1) #elif defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID) #define HW_ID_LEN (16 + 1) diff --git a/lib/hw_id/Kconfig b/lib/hw_id/Kconfig index 9763c0808aa5..b2e9b50225ea 100644 --- a/lib/hw_id/Kconfig +++ b/lib/hw_id/Kconfig @@ -26,8 +26,8 @@ config HW_ID_LIBRARY_SOURCE_UUID help This option requires modem firmware v1.3.0 or higher. -config HW_ID_LIBRARY_SOURCE_BLE_MAC - bool "BLE MAC address" +config HW_ID_LIBRARY_SOURCE_BT_DEVICE_ADDRESS + bool "Bluetooth Device Address" depends on BT config HW_ID_LIBRARY_SOURCE_NET_MAC diff --git a/lib/hw_id/hw_id.c b/lib/hw_id/hw_id.c index 3fe615d87345..878679296d8e 100644 --- a/lib/hw_id/hw_id.c +++ b/lib/hw_id/hw_id.c @@ -8,9 +8,9 @@ #include /* includes for the different HW ID sources */ -#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC) +#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BT_DEVICE_ADDRESS) #include -#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC) */ +#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_BT_DEVICE_ADDRESS) */ #if defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID) #include #endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID) */ @@ -26,8 +26,8 @@ #define IMEI_LEN 15 -#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC) -/* Ask BLE stack for default MAC address */ +#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BT_DEVICE_ADDRESS) +/* Ask Bluetooth stack for default MAC address */ int hw_id_get(char *buf, size_t buf_len) { @@ -53,7 +53,7 @@ int hw_id_get(char *buf, size_t buf_len) addr.a.val[0]); return 0; } -#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC) */ +#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_BT_DEVICE_ADDRESS) */ #if defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID) /* Directly read Device ID from registers */ diff --git a/samples/hw_id/overlay-ble-mac.conf b/samples/hw_id/overlay-ble-mac.conf index d54d4e98a7dd..4c92f96e5988 100644 --- a/samples/hw_id/overlay-ble-mac.conf +++ b/samples/hw_id/overlay-ble-mac.conf @@ -4,4 +4,4 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # CONFIG_BT=y -CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC=y +CONFIG_HW_ID_LIBRARY_SOURCE_BT_DEVICE_ADDRESS=y diff --git a/tests/lib/hw_id/src/kconfig_override_ble.h b/tests/lib/hw_id/src/kconfig_override_ble.h index 54c64e29d47f..d5a7bf3a04ae 100644 --- a/tests/lib/hw_id/src/kconfig_override_ble.h +++ b/tests/lib/hw_id/src/kconfig_override_ble.h @@ -4,4 +4,4 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -#define CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC y +#define CONFIG_HW_ID_LIBRARY_SOURCE_BT_DEVICE_ADDRESS y From 2f3c3650da04e1541c6040376b221c966025939b Mon Sep 17 00:00:00 2001 From: Nordic Builder Date: Fri, 5 Dec 2025 14:02:50 +0000 Subject: [PATCH 155/155] manifest: Update sdk-zephyr revision (auto-manifest PR) Automatically created by action-manifest-pr GH action from PR: https://github.com/nrfconnect/sdk-zephyr/pull/3613 Signed-off-by: Nordic Builder --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index e6c643a7ad64..4952fd0012c9 100644 --- a/west.yml +++ b/west.yml @@ -64,7 +64,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: c09c6abd11695d6b9c2ea24c4e88822eee9ff3f9 + revision: pull/3613/head import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above